gpt4 book ai didi

delphi - GUID 的高效数据结构

转载 作者:行者123 更新时间:2023-12-03 14:38:22 25 4
gpt4 key购买 nike

我正在寻找一种数据结构,它使我能够快速(最好是 O(1) 快速)确定给定的 GUID 是否是 GUID 集合的成员。

我当前的方法是使用值为 0 的 TDictionary。

虽然这工作得很快,但使用 Hashmap 重新哈希 GUID(根据定义被认为是唯一的)并让 Dictionary 处理不需要的值似乎是一种浪费。

一定有更好的解决方案,但我找不到。你可以吗?

最佳答案

很少有数据结构提供 O(1) 访问。一个是数组,另一个是 HashMap(David 的回答),我只知道另一个:Trie 。下面是按位 Trie 的简单实现: 有一些有趣的属性:

  • 不受内存碎片影响,因为不会发生重新分配。
  • O(1) 添加和存在测试。当然,O(1)涉及的常数是相当大的。

代码:

program Project23;

{$APPTYPE CONSOLE}

uses
SysUtils, Generics.Collections;

type

PGuidTrieNode=^TGuidTrieNode;
TGuidTrieNode = record
Sub:array[Boolean] of PGuidTrieNode;
end;
TGuidByteArray = array[0..15] of Byte;

TGuidTrie = class
protected
Root: PGuidTrieNode;
public
constructor Create;
destructor Destroy;override;

procedure Add(G: TGUID);
function Exists(G: TGUID): Boolean;
end;

{ TGuidTrie }

procedure TGuidTrie.Add(G: TGUID);
var GBA: TGuidByteArray absolute G;
Node: PGuidTrieNode;
i: Integer;
Bit: Integer;
IsBitSet: Boolean;
const BitMask: array[0..7] of Byte = (1, 2, 4, 8, 16, 32, 64, 128);
begin
Assert(SizeOf(G) = SizeOf(TGuidByteArray));
Node := Root;
for i:=0 to High(GBA) do
begin
for Bit := 0 to 7 do
begin
IsBitSet := (GBA[i] and BitMask[Bit]) <> 0;
if (i = High(GBA)) and (Bit = 7) then
begin
// Payload
Node.Sub[IsBitSet] := Pointer(1);
end
else
begin
if not Assigned(Node.Sub[IsBitSet]) then
Node.Sub[IsBitSet] := GetMemory(SizeOf(TGuidTrieNode));
Node := Node.Sub[IsBitSet];
end;
end;
end;
end;

constructor TGuidTrie.Create;
begin
Root := GetMemory(SizeOf(TGuidTrieNode))
end;

destructor TGuidTrie.Destroy;

procedure KillNode(Node: PGuidTrieNode);
var i:Integer;
begin
if Assigned(Node.Sub[True]) then
if Node.Sub[True] <> Pointer(1) then
begin
KillNode(Node.Sub[True]);
end;
FreeMemory(Node);
end;

begin
KillNode(Root);
inherited;
end;

function TGuidTrie.Exists(G: TGUID): Boolean;
var GBA: TGuidByteArray absolute G;
Node: PGuidTrieNode;
i: Integer;
Bit: Integer;
IsBitSet: Boolean;
const BitMask: array[0..7] of Byte = (1, 2, 4, 8, 16, 32, 64, 128);
begin
Assert(SizeOf(G) = SizeOf(TGuidByteArray));
Node := Root;
for i:=0 to 15 do
begin
for Bit := 0 to 7 do
begin
IsBitSet := (GBA[i] and BitMask[Bit]) <> 0;
if not Assigned(Node.Sub[IsBitSet]) then
begin
Result := False;
Exit;
end;
Node := Node.Sub[IsBitSet];
end;
end;
Result := True; // Node now contains the Payload
end;

const G1: TGUID = '{68D09F12-3E0D-4963-B32C-4EE3BD90F69C}';
G2: TGUID = '{BEED37F6-9757-41DC-8463-AF094392652B}';

var T: TGuidTrie;

begin
try

T := TGuidTrie.Create;
try
if T.Exists(G1) then WriteLn('Exists')
else WriteLn('NOT Exists');
T.Add(G1);
if T.Exists(G1) then WriteLn('Exists')
else WriteLn('NOT Exists');

if T.Exists(G2) then WriteLn('Exists')
else WriteLn('NOT Exists');
T.Add(G2);
if T.Exists(G2) then WriteLn('Exists')
else WriteLn('NOT Exists');
finally T.Free;
end;

except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.

关于delphi - GUID 的高效数据结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5297057/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com