我的数据形如下,不用显示,只是在后台处理,
curPolTree|----Fields1
      |---Strings1
      |---Strings2....
      .........
|----Fields2于是我想到用树结构来操作,想借用vcl中的TTreeNodes对象,但是不成功。主要有如下问题:
1、PolData := TTreeNodes.create(nil);//这里创建时必须传入他的owner值,这个值//必须是TreeView的父类,由于我没有他的父类,就写入nil
2、PolData.Add(nil,tmpStr);//由于是要创建根结点,所以这里要写入nil。但在这里就运行出错。我跟踪vcl源码发现如下代码:
  if Node = nil then
    Result := Owner.CreateNode
  else
    Result := Node;
也就是说,如果你在加入节点时传入的父节点为nil,那么由它的所有者自动创建一个Node。但是,我在创建PolData时是没有指定Owner的,这时它去访问它的Owner,就出现内存非法访问。如果我在创建PolData时,指定Owner为某TreeView,那么这个poldata中的数据就与那个TreeView中的一样了,那还不如直接用一个TreeView,只是把它的Visable设为false就行了。但用一个TreeView会有不少的内存开支,并且我并不需要显示这些数据。我说的这么详细,是因为我花了一些时间来解决这个问题,有别于那些没有丁点钻研精神的CSDNer。所以希望能得到大家的帮助。请问:还没有没有其它比较好用的、可靠的Tree数据结构可以用?

解决方案 »

  1.   

    我也曾有过你这种想法,但后来还是自己写了一个处理Nodes的东东,
    其实也不难。
    定义一个节点类,几个属性,几个操作方法即可:)
      

  2.   

    同意 dancedog(猪熔鸡)  ^^!
    不过你的名字有点.............
      

  3.   

    to:dancedog(猪熔鸡) 
    想法不错,不过一是对XML不熟悉,二是如果用xml,会代来额外的内存开销,我的数据处理要求实时、长期的运行,没有试过怕有问题。
    xml我先看看再说。xml格式的数据将来是一定要支持的。to:hfyun(逮住就问)
    当然了,实在不行就不能偷懒了,只能自己写了。不过,我觉得在Delphi下面也应该像C++一样,有现成的Tree数据结构可以用,如SGI看上版体的STL和Boost库。并不是说,正是有了这些现成的东东,把程序员搞的越来越懒了,而在在一定的条件下,自己写一个这样的库嚎时、效率不一定高。所以才出些下策。希望大家再能提供点线索。
      

  4.   

    type
      TMap = Record
        fIndex: Integer;
        fName: String;
        fCode: string;
        fType: Integer;
        fDate: TDate;
        fFileType:String;
        FileName: string;
        fRe: string;
      end;{***************************************************************
     * 方 法 名  : TfrmMap.AddRootNode
     * 编写目的   :
     * 作    者  : 黄仁光
     * 参    数  : MapType:Integer
     * 结    果  : TTreeNode
     * 编写日期   :2002年12月18日
     ****************************************************************}
    function TfrmMap.AddRootNode(MapType:Integer):TTreeNode;
    var
      RootNode:TTreeNode;
    begin
      treImage.Items.Clear;
      case MapType of
        0://单位方位图
          begin
            RootNode := treImage.Items.Add(nil,'单位方位图');
          end;
        1://建筑平面图
          begin
            RootNode := treImage.Items.Add(nil,'建筑平面图');
          end;
        2://建筑立面图
          begin
            RootNode := treImage.Items.Add(nil,'建筑立面图');
          end;
        3://楼层平面图
          begin
            RootNode := treImage.Items.Add(nil,'楼层平面图');
          end;
        4://消防部署图
          begin
            RootNode := treImage.Items.Add(nil,'消防部署图');
          end;
        5://最佳路径图
          begin
            RootNode := treImage.Items.Add(nil,'最佳路径图');
          end;
      end;
      Result := RootNode;
    end;{***************************************************************
     * 方 法 名  : TfrmMap.AddChildNode
     * 编写目的   :
     * 作    者  : 黄仁光
     * 参    数  : RootNode:TTreeNode;fIndex:Integer;fCode,fName:String;FileName:String
     * 结    果  : None
     * 编写日期   :2002年12月18日
     ****************************************************************}
    procedure TfrmMap.AddChildNode(RootNode:TTreeNode;fIndex:Integer;fCode,fName:String;fType:Integer;FileName:String);
    var
      ChildNode:TTreeNode;
      pMapChild:PMapNode;
    begin
      new(pMapChild);
      pMapChild^.fIndex := fIndex;
      pMapChild^.fCode := fCode;
      pMapChild^.fName := fName;
      pMapChild^.fType := fType;
      pMapChild^.FileName := FileName;
      ChildNode := treImage.Items.AddChildObject(RootNode,fCode,pMapChild);
    end;procedure TfrmMap.treImageClick(Sender: TObject);
    var
      SelectNode:TTreeNode;
      pMapChild:PMapNode;
      fIndex:Integer;
      FileName:String;
    begin
      try
        new(pMapChild);
        SelectNode := treImage.Selected;
        SelectNode.Expanded := true;
        try
          if SelectNode.Level = 1 then
          begin
            Screen.Cursor := crHourGlass;
            pMapChild := PMapNode(SelectNode.Data);        MapEntryMode := 1;//如果选择树里面的图片,说明图片表是编辑
            FileName := pMapChild^.FileName;
            MapFileName := FileName;
            MapIndex := pMapChild^.fIndex;
            MapCode := pMapChild^.fCode; /////////////////////
            p_PicType := pMapChild.fType;//取得图片的类型        if FileName <> OldFileName then
            begin
              fIndex := pMapChild^.fIndex;
              ShowMapRS(fIndex);
              oldFileName := FileName;
            end;
          end;
        except
          Screen.Cursor := crDefault;
          Exit;
        end;
      finally
        Screen.Cursor := crDefault;
      end;
    end;
      

  5.   

    同意楼上的,用起Node.data属性来,我就是这样用的。它是一个指针,可以为某一节点存很多数据!
      

  6.   

    用Node.Data来处理,灵活性更大,是一个指针,保存什么都很方便。
    注意在删除Node时一定要释放占用的内存。
      

  7.   

    huangrenguang(湖) 的代码有一些值得商讨的地方:1、ChildNode := treImage.Items.AddChildObject(RootNode,fCode,pMapChild);
    这里的treImage说穿了还是一个TreeView(如果不是请你说明是什么),还是离不开我在前面说了不用的TreeView。我就是只想用TreeNodes来保存数据,不用任何TreeView。(treImage.Items其实就是TreeNodes)2、你的代码中临时对像的问题:(比较严重)
    procedure TfrmMap.AddChildNodeFileName:String);
    var
      ChildNode:TTreeNode;
      pMapChild:PMapNode;
    begin
      new(pMapChild);      
    //这里生成了一个生存周期只在这个procedure内有效的pMapChild,你用这个
    //临时的指针保存了数据(加一个节点),离开了这个作用域,对象自动被释放
    //Node.Data保存的只是一个被释放掉的指针。有问题啊??
      pMapChild^.fIndex := fIndex;
    ......
    end;
    单纯的向树里加Node和Data我还是会的,请各位看清我的问题再作答。我是想问还有没有现成的数据结构可以用?另外,看了一下午的xml,有点意思了,我的程序中将来是要支持xml的,不如现在就以xml为基础,把原来的data转成xml再处理,这样以后就是单一的数据接口。(越想越爽!)