如何实现不同元素类型的链表?
How to implement a linked list with different element types?
我想创建一个列表,其中每个元素都必须有 3 个字段:KeyType、KeyName、Value。 Value
字段的类型应为:String、Cardinal、Integer、Byte、Boolean... 取决于 KeyType
的值。我需要它来制作类似 windows 的注册表。有可能吗?
有两种选择。
您可以使用具有变体类型的常规 record/class,例如:
type
TDataType = (dtBoolean, dtString, ....);
PNode = ^TNode;
TNode = record
Prev, Next: PNode;
Keyname: string;
DataType: TDataType;
Data: variant; //or TValue
end;
或使用变体记录
TNode = record
Prev, next: PNode;
DataType: TDataType;
Keyname: string;
Datastring:string;
case DataType of
dtCardinal: (datacardinal: Cardinal);
dtBoolean: (databoolean: boolean);
....
end;
请注意,接口和字符串等托管类型不能包含在记录的变体部分中,因此您必须在此之前将它们放在普通部分中。
无法在链表中捕获注册表
请注意注册表是一棵树,您需要一棵树而不是链表,这意味着您需要 3 个链接:root, left, right
.
而且您需要使用树结构。任何树都可以映射到二叉树,因此您只需要 3 个(如果您省略根节点,则为 2 个)。
TDictionary<string, TNode>
也可以。
在那种情况下,TNode 不包括 Prev/next 成员,因为字典会处理这个问题。
我会使用现成的通用链表。我确定 Spring 有一些,但是如果您不想承担所有需要的依赖项,您可以使用 Chris Rolliston 的简单链表:https://code.google.com/p/ccr-exif/source/browse/blogstuff/CCR.SimpleLinkedList.pas?r=34
然后你只需要决定负载的类型。使用变体类型,例如 TValue
或 Variant
,尽管后者会限制您使用 Windows。或者您可以制作自己的定制变体类型:
type
TMyValue = record
StringValue: string; // managed type must be outside variant part of record
case DataType: TDataType of
dtInteger:
(IntegerValue: Integer);
dtCardinal:
(CardinalValue: Cardinal);
....
end;
然后你会创建一个像这样的节点类型:
type
TNode = record
Name: string;
Value: TValue; // or TMyValue
end;
最后,您的链接列表只是 TSimpleLinkedList<TNode>
,您就完成了。
在我看来,为了保持一致性,在这里使用通用容器很重要。这样做可以让您将容器和元素的各个方面分开。
我想创建一个列表,其中每个元素都必须有 3 个字段:KeyType、KeyName、Value。 Value
字段的类型应为:String、Cardinal、Integer、Byte、Boolean... 取决于 KeyType
的值。我需要它来制作类似 windows 的注册表。有可能吗?
有两种选择。
您可以使用具有变体类型的常规 record/class,例如:
type
TDataType = (dtBoolean, dtString, ....);
PNode = ^TNode;
TNode = record
Prev, Next: PNode;
Keyname: string;
DataType: TDataType;
Data: variant; //or TValue
end;
或使用变体记录
TNode = record
Prev, next: PNode;
DataType: TDataType;
Keyname: string;
Datastring:string;
case DataType of
dtCardinal: (datacardinal: Cardinal);
dtBoolean: (databoolean: boolean);
....
end;
请注意,接口和字符串等托管类型不能包含在记录的变体部分中,因此您必须在此之前将它们放在普通部分中。
无法在链表中捕获注册表
请注意注册表是一棵树,您需要一棵树而不是链表,这意味着您需要 3 个链接:root, left, right
.
而且您需要使用树结构。任何树都可以映射到二叉树,因此您只需要 3 个(如果您省略根节点,则为 2 个)。
TDictionary<string, TNode>
也可以。 在那种情况下,TNode 不包括 Prev/next 成员,因为字典会处理这个问题。
我会使用现成的通用链表。我确定 Spring 有一些,但是如果您不想承担所有需要的依赖项,您可以使用 Chris Rolliston 的简单链表:https://code.google.com/p/ccr-exif/source/browse/blogstuff/CCR.SimpleLinkedList.pas?r=34
然后你只需要决定负载的类型。使用变体类型,例如 TValue
或 Variant
,尽管后者会限制您使用 Windows。或者您可以制作自己的定制变体类型:
type
TMyValue = record
StringValue: string; // managed type must be outside variant part of record
case DataType: TDataType of
dtInteger:
(IntegerValue: Integer);
dtCardinal:
(CardinalValue: Cardinal);
....
end;
然后你会创建一个像这样的节点类型:
type
TNode = record
Name: string;
Value: TValue; // or TMyValue
end;
最后,您的链接列表只是 TSimpleLinkedList<TNode>
,您就完成了。
在我看来,为了保持一致性,在这里使用通用容器很重要。这样做可以让您将容器和元素的各个方面分开。