?? hwstrhashmap.pas
字號:
if not Result then
Exit;
Result := IterateMethodNode(ANode^.Right, AUserData, AIterateMethod);
if not Result then
Exit;
end else
Result := True;
end;
procedure TStringHashMap.NodeIterate(ANode: PPHashNode; AUserData: Pointer;
AIterateFunc: TNodeIterateFunc);
begin
if ANode^ <> nil then
begin
AIterateFunc(AUserData, ANode);
NodeIterate(@ANode^.Left, AUserData, AIterateFunc);
NodeIterate(@ANode^.Right, AUserData, AIterateFunc);
end;
end;
procedure TStringHashMap.DeleteNode(var q: PHashNode);
var
t, r, s: PHashNode;
begin
{ we must delete node q without destroying binary tree }
{ Knuth 6.2.2 D (pg 432 Vol 3 2nd ed) }
{ alternating between left / right delete to preserve decent
performance over multiple insertion / deletion }
FLeftDelete := not FLeftDelete;
{ t will be the node we delete }
t := q;
if FLeftDelete then
begin
if t^.Right = nil then
q := t^.Left
else
begin
r := t^.Right;
if r^.Left = nil then
begin
r^.Left := t^.Left;
q := r;
end else
begin
s := r^.Left;
if s^.Left <> nil then
repeat
r := s;
s := r^.Left;
until s^.Left = nil;
{ now, s = symmetric successor of q }
s^.Left := t^.Left;
r^.Left := s^.Right;
s^.Right := t^.Right;
q := s;
end;
end;
end else
begin
if t^.Left = nil then
q := t^.Right
else
begin
r := t^.Left;
if r^.Right = nil then
begin
r^.Right := t^.Right;
q := r;
end else
begin
s := r^.Right;
if s^.Right <> nil then
repeat
r := s;
s := r^.Right;
until s^.Right = nil;
{ now, s = symmetric predecessor of q }
s^.Right := t^.Right;
r^.Right := s^.Left;
s^.Left := t^.Left;
q := s;
end;
end;
end;
{ we decrement before because the tree is already adjusted
=> any exception in FreeNode MUST be ignored.
It's unlikely that FreeNode would raise an exception anyway. }
Dec(FCount);
FreeNode(t);
end;
procedure TStringHashMap.DeleteNodes(var q: PHashNode);
begin
if q^.Left <> nil then
DeleteNodes(q^.Left);
if q^.Right <> nil then
DeleteNodes(q^.Right);
FreeNode(q);
q := nil;
end;
function TStringHashMap.AllocNode: PHashNode;
begin
New(Result);
Result^.Left := nil;
Result^.Right := nil;
end;
procedure TStringHashMap.FreeNode(ANode: PHashNode);
begin
Dispose(ANode);
end;
{
property access
}
function TStringHashMap.GetData(const s: string): Pointer;
var
ppn: PPHashNode;
begin
ppn := FindNode(s);
if ppn^ <> nil then
Result := ppn^^.Ptr
else
Result := nil;
end;
procedure TStringHashMap.SetData(const s: string; p: Pointer);
var
ppn: PPHashNode;
begin
ppn := FindNode(s);
if ppn^ <> nil then
ppn^^.Ptr := p
else
begin
{ add }
ppn^ := AllocNode;
{ we increment after in case of exception }
Inc(FCount);
ppn^^.Str := s;
ppn^^.Ptr := p;
end;
end;
{ public methods }
procedure TStringHashMap.Add(const s: string; const p{: Pointer});
var
ppn: PPHashNode;
begin
ppn := FindNode(s);
{ if reordered from SetData because ppn^ = nil is more common for Add }
if ppn^ = nil then
begin
{ add }
ppn^ := AllocNode;
{ we increment after in case of exception }
Inc(FCount);
ppn^^.Str := s;
ppn^^.Ptr := Pointer(p);
end else
raise EhwStringHashMapError.CreateResRecFmt(@RsStringHashMapDuplicate, [s]);
end;
type
PListNode = ^TListNode;
TListNode = record
Next: PListNode;
NodeLoc: PPHashNode;
end;
PDataParam = ^TDataParam;
TDataParam = record
Head: PListNode;
Data: Pointer;
end;
procedure NodeIterate_BuildDataList(AUserData: Pointer; ANode: PPHashNode);
var
dp: PDataParam;
t: PListNode;
begin
dp := PDataParam(AUserData);
if dp.Data = ANode^^.Ptr then
begin
New(t);
t^.Next := dp.Head;
t^.NodeLoc := ANode;
dp.Head := t;
end;
end;
procedure TStringHashMap.RemoveData(const p{: Pointer});
var
dp: TDataParam;
i: Integer;
n, t: PListNode;
begin
dp.Data := Pointer(p);
dp.Head := nil;
for i := 0 to FHashSize - 1 do
NodeIterate(@FList^[i], @dp, NodeIterate_BuildDataList);
n := dp.Head;
while n <> nil do
begin
DeleteNode(n^.NodeLoc^);
t := n;
n := n^.Next;
Dispose(t);
end;
end;
function TStringHashMap.Remove(const s: string): Pointer;
var
ppn: PPHashNode;
begin
ppn := FindNode(s);
if ppn^ <> nil then
begin
Result := ppn^^.Ptr;
DeleteNode(ppn^);
end
else
raise EhwStringHashMapError.CreateResRecFmt(@RsStringHashMapInvalidNode, [s]);
end;
procedure TStringHashMap.IterateMethod(AUserData: Pointer;
AIterateMethod: TIterateMethod);
var
i: Integer;
begin
for i := 0 to FHashSize - 1 do
if not IterateMethodNode(FList^[i], AUserData, AIterateMethod) then
Break;
end;
procedure TStringHashMap.Iterate(AUserData: Pointer; AIterateFunc: TIterateFunc);
var
i: Integer;
begin
for i := 0 to FHashSize - 1 do
if not IterateNode(FList^[i], AUserData, AIterateFunc) then
Break;
end;
function TStringHashMap.Has(const s: string): Boolean;
var
ppn: PPHashNode;
begin
ppn := FindNode(s);
Result := ppn^ <> nil;
end;
function TStringHashMap.Find(const s: string; var p{: Pointer}): Boolean;
var
ppn: PPHashNode;
begin
ppn := FindNode(s);
Result := ppn^ <> nil;
if Result then
Pointer(p) := ppn^^.Ptr;
end;
type
PFindDataResult = ^TFindDataResult;
TFindDataResult = record
Found: Boolean;
ValueToFind: Pointer;
Key: string;
end;
function Iterate_FindData(AUserData: Pointer; const AStr: string;
var APtr: Pointer): Boolean;
var
pfdr: PFindDataResult;
begin
pfdr := PFindDataResult(AUserData);
pfdr^.Found := (APtr = pfdr^.ValueToFind);
Result := not pfdr^.Found;
if pfdr^.Found then
pfdr^.Key := AStr;
end;
function TStringHashMap.FindData(const p{: Pointer}; var s: string): Boolean;
var
pfdr: PFindDataResult;
begin
New(pfdr);
try
pfdr^.Found := False;
pfdr^.ValueToFind := Pointer(p);
Iterate(pfdr, Iterate_FindData);
Result := pfdr^.Found;
if Result then
s := pfdr^.Key;
finally
Dispose(pfdr);
end;
end;
procedure TStringHashMap.Clear;
var
i: Integer;
ppn: PPHashNode;
begin
for i := 0 to FHashSize - 1 do
begin
ppn := @FList^[i];
if ppn^ <> nil then
DeleteNodes(ppn^);
end;
FCount := 0;
end;
function TStringHashMap.GetItems(Index: Cardinal): Pointer;
var pn: PHashNode;
i : Cardinal;
n: integer;
begin
if Index > Count -1 then
raise EhwStringHashMapError.Create('索引超出范圍');
n:= -1;
for i := 0 to FHashSize -1 do
begin
pn := FList^[i];
if pn <> nil then
begin
Result := pn^.Ptr;
inc(n);
if n=Index then Exit;
end;
end;
Result := nil;
end;
function TStringHashMap.GetItemsName(Index: Cardinal): string;
var pn: PHashNode;
i,n : Integer;
begin
if Index > Count -1 then
raise EhwStringHashMapError.Create('索引超出范圍');
n:= -1;
for i := 0 to FHashSize -1 do
begin
pn := FList^[i];
if pn <> nil then
begin
Result := pn^.Str;
inc(n);
if n=Index then Exit;
end;
end;
Result := '';
end;
end.
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -