什么数据结构最适合VirtualStringTree?
我想每个曾经使用Delphi的VirtualStringTree的人都会同意这是一个很好的控制。 这是一个“虚拟”控制(你的数据必须保存在其他地方),所以我在想什么数据结构最适合这样的任务? IMO认为数据结构必须支持层次结构,它必须快速且易于扩展。 最简单的实现方法是使用记录,这就是大多数可以找到的文档所暗示的。 但是如果你需要做一些快速查找,计算总数等呢? 你使用什么数据结构与VirtualStringTree一起使用?
编辑1 :我正在使用德尔福2010年。
好的,我会试着提供一些关于我的要求的更多细节。 数据大小可以是非常可变的,从1到数千个项目。 每个项目可以保存多个字符串,整数值。 我需要随机访问,我的数据在应用程序生命周期中可能会改变很多次。 良好的表现是非常理想的。 我还需要保存和重新加载数据。
编辑2 :有1个答案,所以我会尝试评论我的意见。 谢谢,Dorin为你的答案,但我不认为你的结构非常方便。 1)它不涉及层次结构。 2)为每个节点分开TStringList或TList并不是非常有效的IMO。 通过这个实现,我只能查找当前节点的数据,但不能在整个树中进行有效搜索。
我认为这个数据结构必须像一棵树。 它必须有能够添加子项的节点。 然后我可以在OnInitNode事件中获取节点数据,检查我的节点是否有一些子节点,如果是,则设置ivsHasChildren标志,然后在OnInitChildren事件中设置正确的子节点数。 后来在OnGetText事件中,我可以从我的节点结构中获取所需的数据,并根据列索引将其设置为CellText。 我的想法是有一个单独的数据结构,并且无需使用VirtualStringTree即可完成所有需要的操作。 希望有人得到我的观点:)。
编辑3 :我发现了非常有趣的JclTrees单元,一见钟情可以用来实现我正在寻找的东西。 它属于JCL库。 缺乏体面的文档使其很难快速调查其功能。 当我有更多的时间时,我可能会更深入地看待它。
好的,因为给出的答案没有解决我的问题,我写了自己的树数据结构,模仿TVirtualStringTree并处理我在问题中提到的所有问题。 现在我可以选择只使用我的数据结构,并且其中的所有更改都会自动更新VirtualStringTree。 我想我会在稍后的某个地方上传源代码,并在这里发布链接。 感谢所有的答案。
编辑:我已经上传到谷歌代码:svTrees。 有一个演示程序展示了它的工作原理。
你还没有指定你的Delphi版本,所以:
我建议使用记录(我不确定在哪个版本的Delphi中他们添加了记录方法,我从D7移到了D2010),因此您可以使用如下记录:
type
TMyRecordWithMethods = record
function GetMeAResult: Integer;
procedure DoSomething(const AInParam: Integer; var AOutParam: Integer);
end;
如果你的Delphi版本不支持记录方法,并且你真的需要节点的方法,那么你将不得不使用对象来实现这一点,也看看泛型。
由于您只需要保存几千项,我建议使用泛型(不需要重新创建IMHO)即
uses ..., Generics.Collections;
type
TMyNode = class(TObject)// you can leave this out if you like
MyIntList: TList<Integer>; // you can do lookups, you have to implement your own saving/loading methods
MyStringList: TStringList or TList<string>; // you can do lookups in both cases, use TStringList for save/load of data
end;
现在我假设你想从虚拟树中存储所有项目并在稍后加载它们,你可以通过定义你自己的文件结构
type
TMyFileHeader = record
CountItems: Integer; // number of items in the tree
...
end;
const
szMyFileHeader = SizeOf(TMyFileHeader);
type
TMyItemEntry = record
CountInt: Integer; // number of integer values
...
end;
const
szMyItemEntry = SizeOf(TMyItemEntry);
现在您需要实现加载并保存,我建议使用TFileStream进行保存和加载 - 非常简单,
伪代码,对不起,没有时间部分代码: -
a)保存内容:
将项目数保存在TMyFileHeader变量中并将其写入文件
对于树中的每个项目,保存整数列表,保存字符串列表
b)加载内容:
读取文件头 - 以便知道需要从文件中读取多少项
做一个索引:= 0到计数-1从文件读取项目
注意:您可以将每个项目的字符串列表直接保存到文件流中的当前位置,但直接通过以下方式保存它将是明智之举:
FileStream.WriteBuffer(PChar(AStringList.Text)^, Length(AStringList.Text) * SizeOf(Char));
我希望这有助于,代码的实际执行取决于你,玩得开心!
您可以使用TXMLDocument。
如果你想更多地控制你放入的内容,我建议你创建一个描述你想要的结构的xsd,并使用XML数据绑定向导生成你可以使用的Delphi代码。
这个模式
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:complexType name="itemType">
<xs:sequence>
<xs:element name="id" type="xs:int"/>
<xs:element name="name" type="xs:string"/>
<xs:element name="itemlist" type="itemlistType" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="itemlistType">
<xs:sequence>
<xs:element name="item" type="itemType" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element name="itemlist" type="itemlistType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
会给你这些接口在delphi中使用
IXMLRoot = interface(IXMLNode)
['{16C6C960-58B7-400C-9E46-7ACC7BEF276F}']
{ Property Accessors }
function Get_Itemlist: IXMLItemlistType;
{ Methods & Properties }
property Itemlist: IXMLItemlistType read Get_Itemlist;
end;
{ IXMLItemlistType }
IXMLItemlistType = interface(IXMLNodeCollection)
['{59F80BAC-887E-48DF-8288-95276BF9DCE7}']
{ Property Accessors }
function Get_Item(Index: Integer): IXMLItemType;
{ Methods & Properties }
function Add: IXMLItemType;
function Insert(const Index: Integer): IXMLItemType;
property Item[Index: Integer]: IXMLItemType read Get_Item; default;
end;
{ IXMLItemType }
IXMLItemType = interface(IXMLNode)
['{1218DD35-C3EF-40E6-831A-1A4AA0782C36}']
{ Property Accessors }
function Get_Id: Integer;
function Get_Name: WideString;
function Get_Itemlist: IXMLItemlistType;
procedure Set_Id(Value: Integer);
procedure Set_Name(Value: WideString);
{ Methods & Properties }
property Id: Integer read Get_Id write Set_Id;
property Name: WideString read Get_Name write Set_Name;
property Itemlist: IXMLItemlistType read Get_Itemlist;
end;
链接地址: http://www.djcxy.com/p/35035.html
上一篇: What data structure is best suited for VirtualStringTree?
下一篇: Implementing a hierarchical data structure in a database