Code
1
unit zjHashedTable;
2![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
3
interface
4![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
5
uses
6
SysUtils,
7
Classes;
8![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
9
type
10
TzjStringHashProc = function(const aKey:string):Cardinal;
11
TzjHashItemDisposeProc = procedure(aData:Pointer);
12
TzjHashTableIterator = function(aKey:string;aData:Pointer;aParam:LongInt):Boolean;
13![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
14
PPzjHashItem = ^PzjHashItem;
15
PzjHashItem = ^TzjHashItem;
16
TzjHashItem = record
17
Next: PzjHashItem;
18
Key: string;
19
Data: Pointer;
20
end;
21![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
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![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
50
implementation
51![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
52![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
53
function DefStringHash(const aKey:string):Cardinal;
54
var
55
I: Integer;
56
begin
57
Result := 0;
58
for I := 1 to Length(aKey) do
59
Result := ((Result shl 2) or (Result shr (SizeOf(Result) * 8 - 2))) xor
60
Ord(aKey[I]);
61
end;
62![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
63
{ TzjHashedTable }
64![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
65
procedure TzjHashedTable.Clear;
66
var
67
I: Integer;
68
P, N: PzjHashItem;
69
begin
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;
84
end;
85![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
86
constructor TzjHashedTable.Create(aHashProc:TzjStringHashProc;aSize: Cardinal);
87
begin
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;
95
end;
96![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
97
destructor TzjHashedTable.Destroy;
98
begin
99
Clear;
100
inherited;
101
end;
102![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
103
function TzjHashedTable.Exists(const aKey: string): Boolean;
104
begin
105
Result:=Find(aKey)<>nil;
106
end;
107![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
108
function TzjHashedTable.Extract(const aKey: string;out aData: Pointer): Boolean;
109
var
110
Hash: Integer;
111
P,Prev:PzjHashItem;
112
begin
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;
137
end;
138![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
139
function TzjHashedTable.Find(const aKey: string;aPos: Integer): PzjHashItem;
140
var
141
Hash: Integer;
142
begin
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;
155
end;
156![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
157
function TzjHashedTable.GetCapacity: Integer;
158
begin
159
Result:=Length(Buckets);
160
end;
161![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
162
function TzjHashedTable.GetContents: TList;
163
var
164
I,J: Integer;
165
P: PzjHashItem;
166
begin
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;
185
end;
186![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
187
function TzjHashedTable.GetItem(const aKey: string;out aData: Pointer): Boolean;
188
var
189
P: PzjHashItem;
190
begin
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;
199
end;
200![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
201
function TzjHashedTable.Insert(const aKey: string; aData: Pointer; FailIfExists:Boolean):Boolean;
202
var
203
Hash: Integer;
204
P,Bucket: PzjHashItem;
205
begin
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;
227
end;
228![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
229
function TzjHashedTable.Iterate(aIteratePrco: TzjHashTableIterator;
230
aParam: Integer): Boolean;
231
var
232
I: Integer;
233
P: PzjHashItem;
234
begin
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;
246
end;
247![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
248
function TzjHashedTable.Modify(const aKey: string;aData: Pointer): Boolean;
249
var
250
P: PzjHashItem;
251
begin
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;
267
end;
268![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
269
function TzjHashedTable.Remove(const aKey: string): Boolean;
270
var
271
P:Pointer;
272
begin
273
Result:=Self.Extract(aKey,P);
274
if Result and Self.FOwnsItem then
275
Self.FDisposeProc(P);
276
end;
277![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
278
end.
279
转载于:https://www.cnblogs.com/coderush/articles/1294811.html