开放源代码 Delphi泛型库--DGL推荐(Pascal实现的STL)
开放源代码 Delphi泛型库--DGL推荐(Pascal实现的STL)
(第二次开贴推荐 希望DGL能成为你手边的利器!)
Delphi中的容器和算法实在太缺乏了,又存在很多不一致,使用也很不方便。在构造一些容器和算法的时候,总是怀念C++的泛型和STL;2004年的时候个人尝试在Delphi中编写泛型代码,所以就有了DGL(The Delphi Generic Library);简单来说DGL就是在Delphi中部分实现了STL;
DGL库能够以类型安全的方式支持基本类型、指针、Interface、结构(record)、Object结构(Delphi中已经不推荐使用)、类成员函数指针、类(class)的值语义(Delphi中不习惯使用类的值语义,所以不建议使用)等其它用户自定义类型,并且类型安全,容易使用,容易扩展;
DGL的框架来自STL,包括组织方式、命名规则、算法复杂度规格等(包括"陷阱":),实际实现性能和最有名的SGI的STL实现性能接近;
我使用这个库三年了,用它构造的程序已经有上百万人在使用:)
代码支持Delphi7、TurboDelphi、Delphi2007、FreePascal编译环境(其他环境没有测试过)
DGL的下载地址: http://cosoft.org.cn/projects/dgl/
DGL的更多相关信息(实现原理、与各种库的性能对比、简单的Demo实例等等)可以参看我的blog: http://blog.csdn.net/housisong/category/152693.aspx
摘录部分于STL库的性能对比数据:
DGL lib (Turbo Delphi2006 Compile)========================================================
Container: PushBack Next Visite Random Visite Insert At Middle PushFront
TVector 0.029 us 0.007 us 0.079 us 27600.000 us 66800.000 us
TDeque 0.007 us 0.009 us 0.234 us 113200.000 us 0.006 us
TList 0.029 us 0.015 us 8520.000 us 0.066 us 0.037 us
IVector 0.025 us 0.015 us 0.107 us 33000.000 us 79600.000 us
IDeque 0.010 us 0.015 us 0.245 us 103400.000 us 0.013 us
IList 0.050 us 0.017 us 8950.000 us 0.054 us 0.034 us
Container: Insert Find Next Visite
Map 0.370 us 3.592 us 0.075 us
MultiMap 0.388 us 3.873 us 0.104 us
Set 0.366 us 3.254 us 0.062 us
MultiSet 0.345 us 3.275 us 0.062 us
HashMap 0.292 us 0.832 us 0.039 us
HashMultiMap 0.275 us 0.898 us 0.060 us
HashSet 0.248 us 0.847 us 0.043 us
HashMultiSet 0.245 us 0.847 us 0.036 us
================================================================================
STL (VC6 Compile)===============================================================
Container: PushBack Next Visite Random Visite Insert At Middle PushFront
vector 0.041 us 0.005 us 0.078 us 31200 us 68800 us
deque 0.013 us 0.006 us 0.227 us 365600 us 0.012 us
list 0.169 us 0.022 us 21800 us 0.180 us 0.183 us
Container: Insert Find Next Visite
map 0.431 us 3.174 us 0.048 us
set 0.433 us 3.174 us 0.049 us
multimap 0.430 us 3.174 us 0.047 us
multiset 0.427 us 3.174 us 0.048 us
STL (VC2005 Compile)===============================================================
vector 0.019 us 0.009 us 0.078 us 62600 us 140600 us
deque 0.067 us 0.013 us 0.227 us 168800 us 0.061 us
list 0.269 us 0.017 us 15600 us 0.277 us 0.269 us
Container: Insert Find Next Visite
map 2.436 us 4.813 us 0.042 us
set 2.473 us 4.813 us 0.041 us
multimap 2.420 us 4.813 us 0.041 us
multiset 2.416 us 4.813 us 0.041 us
hash_map 0.888 us 1.501 us 0.207 us
hash_set 1.378 us 1.453 us 0.207 us
hash_multimap 1.373 us 1.450 us 0.207 us
hash_multiset 1.380 us 1.450 us 0.207 us
(SGI)STL (DEV-C++4.98 GCC max optimize Compile)=================================
Container: PushBack Next Visite Random Visite Insert At Middle PushFront
vector 0.016 us 0.005 us 0.070 us 34400 us 62400 us
deque 0.011 us 0.009 us 0.258 us 865600 us 0.013 us
list 0.047 us 0.014 us 9400 us 0.052 us 0.036 us
Container: Insert Find Next Visite
map 0.538 us 3.226 us 0.033 us
set 0.516 us 3.226 us 0.034 us
multimap 0.492 us 3.174 us 0.038 us
multiset 0.495 us 3.994 us 0.039 us
hash_map 0.145 us 0.701 us 0.043 us
hash_set 0.234 us 0.650 us 0.044 us
hash_multimap 0.639 us 0.698 us 0.044 us
hash_multiset 0.138 us 0.650 us 0.043 us
================================================================================
摘录部分使用Demo:
//Demo uses IIntVector ---------------------------------------------------------
procedure TFormDGLDemo.btn_IIntVectorClick(Sender: TObject);
var
intVector : IIntVector; //interface type ; Vector use as delphi's array;
i,Sum : integer;
begin
intVector :=TIntVector.Create;
for i:=0 to 100-1 do
intVector.PushBack(i);
Assert(intVector.Size()=100);
Sum:=0;
for i:=0 to intVector.Size()-1 do
Sum:=Sum+intVector.Items[i];
Assert(Sum=(0+99)*100 div 2);
// intVector is interface type not need free;
end;
//Demo uses TIntVector ---------------------------------------------------------
procedure TFormDGLDemo.btn_TIntVectorClick(Sender: TObject);
var
intVector : TIntVector; //class type
i,Sum : integer;
begin
intVector :=TIntVector.Create;
try
for i:=0 to 100-1 do
intVector.PushBack(i);
Assert(intVector.Size()=100);
Sum:=0;
for i:=0 to intVector.Size()-1 do
Sum:=Sum+intVector.Items[i];
Assert(Sum=(0+99)*100 div 2);
finally
intVector.Free; //intVector is class type;
//use class type is maybe faster than interface type;
//recommend priority use DGL container as interface by most time;
end;
end;
//Demo uses IIntDeque ----------------------------------------------------------
procedure TFormDGLDemo.btn_IIntDequeClick(Sender: TObject);
var
intDeque : IIntDeque;
i,Sum : integer;
begin
intDeque :=TIntDeque.Create;
for i:=0 to 100-1 do
intDeque.PushBack(i);
Assert(intDeque.Back()=99);Assert(intDeque.Front()=0);
Assert(intDeque.Size()=100);
for i:=0 to 100-1 do
intDeque.PushFront(i); //Deque's PushFront and PushBack is the same fast;
Assert(intDeque.Back()=99);Assert(intDeque.Front()=99);
Assert(intDeque.Size()=200);
Sum:=0;
for i:=0 to intDeque.Size()-1 do
Sum:=Sum+intDeque.Items[i];
Assert(Sum=((0+99)*100 div 2)*2);
end;
//Demo uses IPointerSet --------------------------------------------------------
procedure TFormDGLDemo.btn_IPointerSetClick(Sender: TObject);
var
piSet : IPointerSet;
it : IPointerIterator;
i,Sum : integer;
begin
piSet :=TPointerHashSet.Create;
for i:=0 to 200-1 do
piSet.Insert(Pointer(i div 2)); //values is [0,1,..99]
Assert(piSet.size()=100);
Sum:=0;
it:=piSet.ItBegin;
for i:=0 to piSet.Size-1 do
begin
inc(Sum,integer(it.Value));
it.Next;
end;
Assert(Sum=((0+99)*100 div 2));
for i:=0 to 100-1 do
begin
it:=piSet.Find(Pointer(i));
Assert(not it.IsEqual(piSet.ItEnd));
Assert(it.Value=Pointer(i));
end;
for i:=0 to 100-1 do
piSet.EraseValue(Pointer(i)); //== piSet.Erase(piSet.Find(Pointer(i)));
Assert(piSet.IsEmpty());
Assert(piSet.Size()=0);
end;