16,749
社区成员
发帖
与我相关
我的任务
分享
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
PPHashItem = ^PHashItem;
PHashItem = ^THashItem;
THashItem = record
Next: PHashItem;
Key: string;
Value: Integer;
end;
TStringHashEx = class
private
Buckets: array of PHashItem;
protected
function Find(const Key: string): PPHashItem;
public
function HashOf(const Key: string): Cardinal; virtual;
constructor Create(Size: Cardinal = 256);
destructor Destroy; override;
procedure Add(const Key: string; Value: Integer);
procedure Clear;
procedure Remove(const Key: string);
function Modify(const Key: string; Value: Integer): Boolean;
function ValueOf(const Key: string): Integer;
function GetIpNum(const ACount: Integer): Integer;
end;
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
Memo2: TMemo;
Memo3: TMemo;
Memo4: TMemo;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
Test: TStringHashEx;
Ip: string;
I, J: Integer;
begin
Test := TStringHashEx.Create(200000); //首先创建一个足够大的
for I := 0 to 20 do
begin
Ip := IntToStr(Random(9)) + IntToStr(Random(9)) ;
Test.Add(Ip, I); // 这里加入IP,另外保证VALUE没有重复
Memo1.Lines.Add(Ip);
end;
for I := 2 to 6 do
begin
Memo1.Lines.Add(Format('出现重复%d 的有 %d 个', [I, Test.GetIpNum(I)]));
end;
end;
{ TStringHashEx }
procedure TStringHashEx.Add(const Key: string; Value: Integer);
var
Hash: Integer;
Bucket: PHashItem;
begin
Hash := HashOf(Key) mod Cardinal(Length(Buckets));
New(Bucket);
Bucket^.Key := Key;
Bucket^.Value := Value;
Bucket^.Next := Buckets[Hash];
Buckets[Hash] := Bucket;
end;
procedure TStringHashEx.Clear;
var
I: Integer;
P, N: PHashItem;
begin
for I := 0 to Length(Buckets) - 1 do
begin
P := Buckets[I];
while P <> nil do
begin
N := P^.Next;
Dispose(P);
P := N;
end;
Buckets[I] := nil;
end;
end;
constructor TStringHashEx.Create(Size: Cardinal);
begin
inherited Create;
SetLength(Buckets, Size);
end;
destructor TStringHashEx.Destroy;
begin
Clear;
inherited Destroy;
end;
function TStringHashEx.Find(const Key: string): PPHashItem;
var
Hash: Integer;
begin
Hash := HashOf(Key) mod Cardinal(Length(Buckets));
Result := @Buckets[Hash];
while Result^ <> nil do
begin
if Result^.Key = Key then
Exit
else
Result := @Result^.Next;
end;
end;
function TStringHashEx.GetIpNum(const ACount: Integer): Integer;
var
I, Sum: Integer;
P, N: PHashItem;
TempKey: string;
begin
Result := 0;
Sum := 0;
for I := 0 to Length(Buckets) - 1 do
begin
Sum := 0;
TempKey := '';
P := Buckets[I];
if Assigned(P) then
TempKey := p^.Key; // 记录首个KEY值
while P <> nil do
begin
if (CompareStr(p^.Key, TempKey) = 0) then // 在这里做了个KEY判断,VCL自带HASHOF好象有点问题
Inc(Sum);
P := P^.Next;
if Sum >= ACount then
begin
Inc(Result);
Break;
end;
end;
end;
end;
function TStringHashEx.HashOf(const Key: string): Cardinal;
var
I: Integer;
begin
Result := 0;
for I := 1 to Length(Key) do
Result := ((Result shl 2) or (Result shr (SizeOf(Result) * 8 - 2))) xor
Ord(Key[I]);
end;
function TStringHashEx.Modify(const Key: string; Value: Integer): Boolean;
var
P: PHashItem;
begin
P := Find(Key)^;
if P <> nil then
begin
Result := True;
P^.Value := Value;
end
else
Result := False;
end;
procedure TStringHashEx.Remove(const Key: string);
var
P: PHashItem;
Prev: PPHashItem;
begin
Prev := Find(Key);
P := Prev^;
if P <> nil then
begin
Prev^ := P^.Next;
Dispose(P);
end;
end;
function TStringHashEx.ValueOf(const Key: string): Integer;
var
P: PHashItem;
begin
P := Find(Key)^;
if P <> nil then
Result := P^.Value
else
Result := -1;
end;
end.