改编自TStringHash的Delphi哈希表类
1
unit zjHashedTable;2

3
interface4

5
uses6
SysUtils,7
Classes;8

9
type10
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 = record17
Next: PzjHashItem;18
Key: string;19
Data: Pointer;20
end;21

22
TzjHashedTable = class(TObject)23
private24
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
public32
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

50
implementation51

52

53
function DefStringHash(const aKey:string):Cardinal;54
var55
I: Integer;56
begin57
Result := 0;58
for I := 1 to Length(aKey) do59
Result := ((Result shl 2) or (Result shr (SizeOf(Result) * 8 - 2))) xor60
Ord(aKey[I]);61
end;62

63
{ TzjHashedTable }64

65
procedure TzjHashedTable.Clear;66
var67
I: Integer;68
P, N: PzjHashItem;69
begin70
for I := 0 to Length(Buckets) - 1 do71
begin72
P := Buckets[I];73
while P <> nil do74
begin75
N := P^.Next;76
if Self.FOwnsItem then77
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

86
constructor TzjHashedTable.Create(aHashProc:TzjStringHashProc;aSize: Cardinal);87
begin88
if @aHashProc=nil then89
Self.FHashProc:=@DefStringHash90
else91
Self.FHashProc:=@aHashProc;92
SetLength(Buckets, aSize);93
FillChar(Buckets[0],Length(Buckets)*SizeOf(PzjHashItem),0);94
FCount:=0;95
end;96

97
destructor TzjHashedTable.Destroy;98
begin99
Clear;100
inherited;101
end;102

103
function TzjHashedTable.Exists(const aKey: string): Boolean;104
begin105
Result:=Find(aKey)<>nil;106
end;107

108
function TzjHashedTable.Extract(const aKey: string;out aData: Pointer): Boolean;109
var110
Hash: Integer;111
P,Prev:PzjHashItem;112
begin113
Result:=False;114
Hash := FHashProc(aKey) mod Cardinal(Length(Buckets));115
Prev:=nil;116
P := Buckets[Hash];117
while P <> nil do118
begin119
if P.Key = aKey then120
begin121
if Prev<>nil then122
Prev.Next:=P.Next123
else124
Buckets[Hash]:=P.Next;125
aData:=P.Data;126
Dispose(P);127
Dec(FCount);128
Result:=True;129
Break;130
end131
else132
begin133
Prev:=P;134
P:=P.Next;135
end;136
end;137
end;138

139
function TzjHashedTable.Find(const aKey: string;aPos: Integer): PzjHashItem;140
var141
Hash: Integer;142
begin143
if aPos < 0 then144
Hash := FHashProc(aKey) mod Cardinal(Length(Buckets))145
else146
Hash := aPos;147
Result := Buckets[Hash];148
while Result <> nil do149
begin150
if Result.Key = aKey then151
Exit152
else153
Result := Result.Next;154
end;155
end;156

157
function TzjHashedTable.GetCapacity: Integer;158
begin159
Result:=Length(Buckets);160
end;161

162
function TzjHashedTable.GetContents: TList;163
var164
I,J: Integer;165
P: PzjHashItem;166
begin167
if FCount=0 then168
begin169
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 do176
begin177
P := Buckets[I];178
while P <> nil do179
begin180
Result.Items[J]:=P.Data;181
Inc(J);182
P:=P.Next;183
end;184
end;185
end;186

187
function TzjHashedTable.GetItem(const aKey: string;out aData: Pointer): Boolean;188
var189
P: PzjHashItem;190
begin191
P := Find(aKey);192
if P=nil then193
Result:=False194
else195
begin196
aData:=P.Data;197
Result:=True;198
end;199
end;200

201
function TzjHashedTable.Insert(const aKey: string; aData: Pointer; FailIfExists:Boolean):Boolean;202
var203
Hash: Integer;204
P,Bucket: PzjHashItem;205
begin206
Result:=False;207
Hash := FHashProc(aKey) mod Cardinal(Length(Buckets));208
P:=Self.Find(aKey,Hash);209
if p=nil then210
begin211
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
end219
else if not FailIfExists then220
begin221
if Self.FOwnsItem then222
Self.FDisposeProc(P.Data);223
P.Data:=aData;224
Inc(FCount);225
Result:=True;226
end;227
end;228

229
function TzjHashedTable.Iterate(aIteratePrco: TzjHashTableIterator;230
aParam: Integer): Boolean;231
var232
I: Integer;233
P: PzjHashItem;234
begin235
Result:=False;236
for I := 0 to Length(Buckets) - 1 do237
begin238
P := Buckets[I];239
while P <> nil do240
begin241
Result:=aIteratePrco(P.Key,P.Data,aParam);242
if Result then Exit;243
P:=P.Next;244
end;245
end;246
end;247

248
function TzjHashedTable.Modify(const aKey: string;aData: Pointer): Boolean;249
var250
P: PzjHashItem;251
begin252
P := Find(aKey);253
if P = nil then254
Result:=False255
else256
begin257
if P.Data<>aData then258
begin259
if Self.FOwnsItem then260
Self.FDisposeProc(P.Data);261
P.Data:=aData;262
Result:=True;263
end264
else265
Result:=False;266
end;267
end;268

269
function TzjHashedTable.Remove(const aKey: string): Boolean;270
var271
P:Pointer;272
begin273
Result:=Self.Extract(aKey,P);274
if Result and Self.FOwnsItem then275
Self.FDisposeProc(P);276
end;277

278
end.279


浙公网安备 33010602011771号