Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 什么数据结构最适合VirtualStringTree?_Delphi_Data Structures_Virtualtreeview - Fatal编程技术网

Delphi 什么数据结构最适合VirtualStringTree?

Delphi 什么数据结构最适合VirtualStringTree?,delphi,data-structures,virtualtreeview,Delphi,Data Structures,Virtualtreeview,我想所有使用过Delphi的VirtualStringTree的人都会同意这是一个很好的控件。它是一个“虚拟”控件(您的数据必须保存在其他地方),所以我在想什么样的数据结构最适合这样的任务?IMO认为数据结构必须支持层次结构,它必须快速且易于扩展。最简单的实现是使用一个记录,这是可以找到的大多数文档所建议的。但是如果你需要做一些快速查找,计算总数,等等呢?与VirtualStringTree一起使用的是什么数据结构 EDIT1:我正在使用Delphi 2010 好的,我会尽量提供更多关于我的要求

我想所有使用过Delphi的VirtualStringTree的人都会同意这是一个很好的控件。它是一个“虚拟”控件(您的数据必须保存在其他地方),所以我在想什么样的数据结构最适合这样的任务?IMO认为数据结构必须支持层次结构,它必须快速且易于扩展。最简单的实现是使用一个记录,这是可以找到的大多数文档所建议的。但是如果你需要做一些快速查找,计算总数,等等呢?与VirtualStringTree一起使用的是什么数据结构

EDIT1:我正在使用Delphi 2010

好的,我会尽量提供更多关于我的要求的细节。 数据大小可能非常多变,从1到数千项。每个项可以包含多个字符串、整数值。我需要随机访问,在应用程序生命周期内,我的数据可以多次更改。良好的性能是非常可取的。我还需要保存和重新加载数据

EDIT2: 我得到了一个答案,所以我将尝试评论我的观点。多林,谢谢你的回答,但是 我认为你们的结构不太方便。 1) 它不涉及层次结构。 2) 对每个节点使用单独的TStringList或TList对我来说不是很有效。使用这种实现,我只能查找当前节点的数据,但不能有效地在整个树中搜索

我认为这个数据结构一定像一棵树。它必须具有能够添加子节点的节点。然后我就可以在OnInitNode事件中获取节点的数据,检查我的节点是否有一些子节点,如果有,设置ivsHasChildren标志,然后在OnInitChildren事件中设置正确的子节点计数。稍后在OnGetText事件中,我可以从节点结构中获取所需的数据,并根据列索引将其设置为CellText。我的想法是拥有一个单独的数据结构,并使用它执行所有需要的操作,而无需使用VirtualStringTree。希望有人明白我的意思:)


EDIT3:我发现了非常有趣的JclTrees单元,乍一看可以用来实现我所寻找的目标。它属于图书馆。由于缺乏像样的文档,很难快速调查它的功能。当我有更多的时间时,我可能会更深入地研究它

您尚未指定Delphi版本,因此:

我建议使用记录(我不确定他们在哪个版本的Delphi中为记录添加了方法,我从D7迁移到D2010),这样您就可以得到如下结果:

type
  TMyRecordWithMethods = record
    function GetMeAResult: Integer;
    procedure DoSomething(const AInParam: Integer; var AOutParam: Integer);
  end;
如果您的Delphi版本不支持带有方法的记录,并且您确实需要用于节点的方法,那么您必须使用对象来实现这一点,还可以查看泛型

因为你只需要持有几千件物品,所以我建议使用泛型(无需重新发明轮子IMHO)

现在需要实现加载和保存,我建议使用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>


好的,因为给出的答案并没有解决我的问题,所以我编写了自己的树数据结构,它模仿TVirtualStringTree,处理我在问题中提到的所有问题。现在,我可以选择只使用我的数据结构,其中的所有更改将自动更新VirtualStringTree。我想我以后会把源代码上传到某个地方,并在这里发布链接。谢谢你的回答


编辑:我已将源代码上传到谷歌代码:。有一个小演示演示了它是如何工作的。

这并没有解决hierarchy@DavidHeffernan根据他的“实际”需求,他可以做出妥协,如果他需要创建一百万个节点,使用对象将消耗大量内存(现在当然都会消耗到目标系统),但记录消耗的内存会更少,安湖非常欢迎你来给我一个好答案:-P@Dorin我什么也没说。不管它值多少钱,我认为记录是好的。也就是说,对象不再使用任何内存—ToObject没有成员字段。我的观点是,问题是关于层次结构,而不是如何在节点中存储信息。我在问题中提到,记录是一个很好的解决方案,但使用记录并不能解决David所说的一些问题。@David拜托,伙计,别这么防御性:)但是关于“也就是说,对象不再使用任何内存”--为什么会有人使用没有字段的对象?这同样适用于记录,但如果在对象中添加一个整型字段,在记录中添加一个整型字段,当您查看时,您将看到差异。InstanceSize,也就是说,乘以项目(和子项目)的数量,您将得到大量内存浪费+创建和释放过程,这将占用相当多的CPU周期(如果有很多项,请再说一遍)。@Lina您能告诉我们更多有关您希望存储的数据的信息吗?数据有多大?它在您的进程生命周期内如何变化?您需要随机访问吗?性能限制是什么?目前我正在考虑
FileStream.WriteBuffer(PChar(AStringList.Text)^, Length(AStringList.Text) * SizeOf(Char));
<?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>
  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;