改编自TStringHash的Delphi哈希表类

ContractedBlock.gif ExpandedBlockStart.gif Code
  1unit zjHashedTable;
  2
  3interface
  4
  5uses
  6  SysUtils,
  7  Classes;
  8
  9type
 10  TzjStringHashProc = function(const aKey:string):Cardinal;
 11  TzjHashItemDisposeProc = procedure(aData:Pointer);
 12  TzjHashTableIterator = function(aKey:string;aData:Pointer;aParam:LongInt):Boolean;
 13
 14  PPzjHashItem = ^PzjHashItem;
 15  PzjHashItem = ^TzjHashItem;
 16  TzjHashItem = record
 17    Next: PzjHashItem;
 18    Key: string;
 19    Data: Pointer;
 20  end;
 21
 22  TzjHashedTable = class(TObject)
 23  private
 24    Buckets: array of PzjHashItem;
 25    FHashProc: TzjStringHashProc;
 26    FDisposeProc:TzjHashItemDisposeProc;
 27    FOwnsItem:Boolean;
 28    FCount:Integer;
 29    function GetContents: TList;
 30    function GetCapacity: Integer;
 31  public
 32    constructor Create(aHashProc:TzjStringHashProc = nil;aSize: Cardinal = 256);
 33    destructor Destroy; override;
 34    function Find(const aKey: string;aPos: Integer = -1): PzjHashItem;
 35    function Insert(const aKey: string; aData: Pointer; FailIfExists:Boolean = False):Boolean;
 36    procedure Clear;
 37    function Remove(const aKey: string):Boolean;
 38    function Extract(const aKey: string;out aData:Pointer):Boolean;
 39    function Modify(const aKey: string; aData: Pointer): Boolean;
 40    function GetItem(const aKey: string;out aData:Pointer): Boolean;
 41    function Exists(const aKey:string):Boolean;
 42    function Iterate(aIteratePrco:TzjHashTableIterator;aParam:LongInt):Boolean;
 43    property Contents:TList read GetContents;
 44    property DisposeProc:TzjHashItemDisposeProc read FDisposeProc write FDisposeProc;
 45    property OwnsItem:Boolean read FOwnsItem write FOwnsItem;
 46    property Count:Integer read FCount;
 47    property Capacity:Integer read GetCapacity;
 48  end;
 49
 50implementation
 51
 52
 53function DefStringHash(const aKey:string):Cardinal;
 54var
 55  I: Integer;
 56begin
 57  Result := 0;
 58  for I := 1 to Length(aKey) do
 59    Result := ((Result shl 2or (Result shr (SizeOf(Result) * 8 - 2))) xor
 60      Ord(aKey[I]);
 61end;
 62
 63{ TzjHashedTable }
 64
 65procedure TzjHashedTable.Clear;
 66var
 67  I: Integer;
 68  P, N: PzjHashItem;
 69begin
 70  for I := 0 to Length(Buckets) - 1 do
 71  begin
 72    P := Buckets[I];
 73    while P <> nil do
 74    begin
 75      N := P^.Next;
 76      if Self.FOwnsItem then
 77        Self.FDisposeProc(P.Data);
 78      Dispose(P);
 79      P := N;
 80    end;
 81  end;
 82  FillChar(Buckets[0],Length(Buckets)*SizeOf(PzjHashItem),0);
 83  FCount:=0;
 84end;
 85
 86constructor TzjHashedTable.Create(aHashProc:TzjStringHashProc;aSize: Cardinal);
 87begin
 88  if @aHashProc=nil then
 89    Self.FHashProc:=@DefStringHash
 90  else
 91    Self.FHashProc:=@aHashProc;
 92  SetLength(Buckets, aSize);
 93  FillChar(Buckets[0],Length(Buckets)*SizeOf(PzjHashItem),0);
 94  FCount:=0;
 95end;
 96
 97destructor TzjHashedTable.Destroy;
 98begin
 99  Clear;
100  inherited;
101end;
102
103function TzjHashedTable.Exists(const aKey: string): Boolean;
104begin
105  Result:=Find(aKey)<>nil;
106end;
107
108function TzjHashedTable.Extract(const aKey: string;out aData: Pointer): Boolean;
109var
110  Hash: Integer;
111  P,Prev:PzjHashItem;
112begin
113  Result:=False;
114  Hash := FHashProc(aKey) mod Cardinal(Length(Buckets));
115  Prev:=nil;
116  P := Buckets[Hash];
117  while P <> nil do
118  begin
119    if P.Key = aKey then
120    begin
121      if Prev<>nil then
122        Prev.Next:=P.Next
123      else
124        Buckets[Hash]:=P.Next;
125      aData:=P.Data;
126      Dispose(P);
127      Dec(FCount);
128      Result:=True;
129      Break;
130    end
131    else
132    begin
133      Prev:=P;
134      P:=P.Next;
135    end;
136  end;
137end;
138
139function TzjHashedTable.Find(const aKey: string;aPos: Integer): PzjHashItem;
140var
141  Hash: Integer;
142begin
143  if aPos < 0 then
144    Hash := FHashProc(aKey) mod Cardinal(Length(Buckets))
145  else
146    Hash := aPos;
147  Result := Buckets[Hash];
148  while Result <> nil do
149  begin
150    if Result.Key = aKey then
151      Exit
152    else
153      Result := Result.Next;
154  end;
155end;
156
157function TzjHashedTable.GetCapacity: Integer;
158begin
159  Result:=Length(Buckets);
160end;
161
162function TzjHashedTable.GetContents: TList;
163var
164  I,J: Integer;
165  P: PzjHashItem;
166begin
167  if FCount=0 then
168  begin
169    Result:=nil;
170    Exit;
171  end;
172  Result:=TList.Create;
173  Result.Count:=Self.FCount;
174  J:=0;
175  for I := 0 to Length(Buckets) - 1 do
176  begin
177    P := Buckets[I];
178    while P <> nil do
179    begin
180      Result.Items[J]:=P.Data;
181      Inc(J);
182      P:=P.Next;
183    end;
184  end;
185end;
186
187function TzjHashedTable.GetItem(const aKey: string;out aData: Pointer): Boolean;
188var
189  P: PzjHashItem;
190begin
191  P := Find(aKey);
192  if P=nil then
193    Result:=False
194  else
195  begin
196    aData:=P.Data;
197    Result:=True;
198  end;
199end;
200
201function TzjHashedTable.Insert(const aKey: string; aData: Pointer; FailIfExists:Boolean):Boolean;
202var
203  Hash: Integer;
204  P,Bucket: PzjHashItem;
205begin
206  Result:=False;
207  Hash := FHashProc(aKey) mod Cardinal(Length(Buckets));
208  P:=Self.Find(aKey,Hash);
209  if p=nil then
210  begin
211    New(Bucket);
212    Bucket.Key := aKey;
213    Bucket.Data := aData;
214    Bucket.Next := Buckets[Hash];
215    Buckets[Hash] := Bucket;
216    Inc(FCount);
217    Result:=True;
218  end
219  else if not FailIfExists then
220  begin
221    if Self.FOwnsItem then
222      Self.FDisposeProc(P.Data);
223    P.Data:=aData;
224    Inc(FCount);
225    Result:=True;
226  end;
227end;
228
229function TzjHashedTable.Iterate(aIteratePrco: TzjHashTableIterator;
230  aParam: Integer): Boolean;
231var
232  I: Integer;
233  P: PzjHashItem;
234begin
235  Result:=False;
236  for I := 0 to Length(Buckets) - 1 do
237  begin
238    P := Buckets[I];
239    while P <> nil do
240    begin
241      Result:=aIteratePrco(P.Key,P.Data,aParam);
242      if Result then Exit;
243      P:=P.Next;
244    end;
245  end;
246end;
247
248function TzjHashedTable.Modify(const aKey: string;aData: Pointer): Boolean;
249var
250  P: PzjHashItem;
251begin
252  P := Find(aKey);
253  if P = nil then
254    Result:=False
255  else
256  begin
257    if P.Data<>aData then
258    begin
259      if Self.FOwnsItem then
260        Self.FDisposeProc(P.Data);
261      P.Data:=aData;
262      Result:=True;
263    end
264    else
265      Result:=False;
266  end;
267end;
268
269function TzjHashedTable.Remove(const aKey: string): Boolean;
270var
271  P:Pointer;
272begin
273  Result:=Self.Extract(aKey,P);
274  if Result and Self.FOwnsItem then
275    Self.FDisposeProc(P);
276end;
277
278end.
279

转载于:https://www.cnblogs.com/coderush/articles/1294811.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值