首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >什么数据结构最适合VirtualStringTree?

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

Stack Overflow用户
提问于 2011-01-16 20:50:29
回答 3查看 1.7K关注 0票数 7

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

EDIT1:我正在使用Delphi2010。

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

EDIT2:得到了一个答案,所以我会试着评论我的观点。谢谢你的回答,但我认为你的结构不太方便。( 1)它不处理等级问题。2)对每个节点分别使用TStringList或TList是不太有效的。使用此实现,我只能查找当前节点的数据,但不能有效地搜索整个树。

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

EDIT3:我发现了非常有趣的JclTrees单元,乍一看可以用来实现我想要的目标。它属于JCL库。由于缺乏完善的文档,因此很难快速调查它的功能。当我有更多的时间时,我可能会更深入地研究它。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-01-21 07:40:17

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

编辑:我已经将源代码上传到Google代码:svTrees。有一个演示展示了它是如何工作的。

票数 4
EN

Stack Overflow用户

发布于 2011-01-16 21:41:43

您还没有指定Delphi版本,因此:

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

代码语言:javascript
运行
复制
type
  TMyRecordWithMethods = record
    function GetMeAResult: Integer;
    procedure DoSomething(const AInParam: Integer; var AOutParam: Integer);
  end;

如果您的Delphi版本不支持带有方法的记录,并且确实需要节点的方法,那么您必须使用对象来完成这一任务,还可以查看泛型。

由于您只需要保存几千个项目,我建议使用泛型(不需要重新发明轮子IMHO)。

代码语言:javascript
运行
复制
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;

现在假设您希望存储虚拟树中的所有项,并在以后加载它们,您可以通过定义自己的文件结构来做到这一点,即

代码语言:javascript
运行
复制
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从文件中读取项

注意:您可以将字符串列表从每个项直接保存到文件流中的当前位置,但是通过以下方法直接保存它是明智的:

代码语言:javascript
运行
复制
FileStream.WriteBuffer(PChar(AStringList.Text)^, Length(AStringList.Text) * SizeOf(Char));

我希望这有帮助,代码的实际实现取决于你,玩得开心!!

票数 3
EN

Stack Overflow用户

发布于 2011-01-18 10:16:20

您可以使用TXMLDocument。

如果您想要更多地控制您输入的内容,我建议您创建一个xsd,描述您想要的结构,并使用XML数据绑定向导来生成您可以使用的Delphi代码。

这个模式

代码语言:javascript
运行
复制
<?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中使用的这些接口。

代码语言:javascript
运行
复制
  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;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4707959

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档