Форум: "Основная";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.05.02;
Скачать: [xml.tar.bz2];




Вниз

Tree Walker: Create 


Satirus   (2002-04-19 17:14) [0]

Вопрос к умудрённым опытом в использовании компонента TTreeView.
Предложите оригинальный код для перебора веток дерева снаружи внутрь. То есть, как пройтись сначала по сиблингам корня, потом по их детям, потом по сиблингам детей и т. д., до последнего колена в глубину



Дмитрий Баранов   (2002-04-19 17:44) [1]

В цикле по всем узлам (0..TreeView1.Items.Count-1) строим массив массивов (динамических) указателей (TTreeNode).
Первый индекс - Items[i].Level, второй - порядковый номер узла в массиве.
Вариации на тему - не массивы, а стеки (динамический массив - тормоз).

Выстроили - работаем.



vuk   (2002-04-19 17:45) [2]

Рекурсивно. То есть пишется процедура, поторой на вход подается узел и она сначала проходит по всем его дочерним узлам а потом делает второй проход по ним же и вызывает сама себя, передавая каждый из дочерних узлов в качестве параметра.



vuk   (2002-04-19 17:46) [3]

Рекурсивно. То есть пишется процедура, которой на вход подается узел и она сначала проходит по всем его дочерним узлам а потом делает второй проход по ним же и вызывает сама себя, передавая каждый из дочерних узлов в качестве параметра.



MBo   (2002-04-19 17:48) [4]

если не хранить номера узлов, имеющих деток, то придется обходить все, проверяя level, т.е. сначала с level 0, потом с 1 ,и т.д., пока не будет таких 0.
А можно создавать при первом обходе список, сортированный по level и дальше по нему.



vuk   (2002-04-19 17:55) [5]

А чем рекурсия не устраивает?



Satirus   (2002-04-19 17:58) [6]

Дмитрий Баранов-> можно по подробней? Идея динамического массива у меня возникла сразу... Развейте её, пожалуйста, в виде кода



Дмитрий Баранов   (2002-04-19 18:10) [7]

Вот с удовольствием бы, только времени нет. Динамический массив как он реализован в Delphi я бы применять не стал, а взял бы аналог С++ map. В Delphi придется извращаться -
Type TArrNode = array of TTreeNode;
Type TTree = array of TArrNode;
(с array of array шибко нечитаемый код получается),
а затем везде впихивать SetLength.
Если это не очень срочно, то могу на выходных подумать.



vuk   (2002-04-19 18:12) [8]

Понял свою лажу. Извиняюсь.



Satirus   (2002-04-19 18:17) [9]

vuk-> Меня устраивает рекурсия, но я не знаю, с какой стороны к ней подойти. Можно примерный кусочек кода?
Заранее благодарен



Дмитрий Баранов   (2002-04-19 18:24) [10]

На коленках - рекурсия.

procedure Recurse(const Node: TTreeNode);
var i: integer;
begin
ShowMessage(Node.Text);
if not Node.HasChildren then exit
else
begin
for i:=0 to Node.Count-1 do
begin
Recurse(Node.Item[i]);
end;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var Node: TTreeNode;
begin
Node:=TreeView1.Items[0];
Recurse(Node);
end;



MBo   (2002-04-19 18:25) [11]

procedure TForm1.Button1Click(Sender: TObject);
var sl,sl2:TStringlist;
i,j,k:integer;
begin
sl:=tstringlist.create;
sl2:=tstringlist.create;
for i:=0 to tv1.Items.count-1 do begin
j:=tv1.items[i].level-sl.count+1;
if j>0 then
for k:=1 to j do sl.add("");
sl[tv1.items[i].Level]:=sl[tv1.items[i].Level]+inttostr(i)+" ";
end;
for i:=0 to sl.count-1 do begin
memo1.lines.add("Level "+inttostr(i));
sl2.commatext:=sl[i];
for j:=0 to sl2.count-1 do
memo1.lines.add(tv1.items[strtoint(sl2[j])].text);
end;
sl.free;
sl2.free;
end;



Дмитрий Баранов   (2002-04-19 18:30) [12]

>> MBo © (19.04.02 18:25)
Тоже на коленках :) ?
Меня, например удивляет, почему в Delphi встроеных хэшей и мапов нет :)) StringList - это не выход :)) Это слишком просто и медленно :))



vuk   (2002-04-19 18:32) [13]

Рекурсия не пойдет. Я немного не верно понял задачу. Нормальным решением рекурсия будет только тогда, когда нужен проход в таком порядке: сначала корень, потом его первый дочерний узел, и т.д. в глубь, т.е. каждая ветка проходится до конца перед тем как будет пройдена другая ветка. У Вас же условие другое - перебор должен идти по уровням, а не по веткам.



Satirus   (2002-04-19 18:56) [14]

vuk-> Ну да. Мне надо пройтись по уровням



MBo   (2002-04-19 19:22) [15]

>StringList - это не выход :))
это демонстрация подхода, но вполне рабочий вариант

>Это слишком просто и медленно :))
все зависит от диаметры иглы - количества items



Satirus   (2002-04-19 21:01) [16]

>>vuk Возвращаясь к вопросу использования библиотеки XDOM, хочу спросить Вас, не использовали ли Вы её встроенный TDOMTreeWalker, подобие которого я и пытаюсь создать, но в облегченном варианте. Целевым объектом триволкера является всё тот же XML-file, но вот незадача, не могу его побороть! Может у Вас найдется пару простеньких примерчиков по вытягиванию древа из XML-file?
Буду очень признателен.



vuk   (2002-04-19 21:10) [17]

Дерево-то проще всего вытягивать рекурсивно, а не по уровням. Все достаточно прозрачно получается. В составе XDOM даже пример имеется как это сделать.
имя файла:
\example03\example03main.pas

Метод:
procedure TMainpage.UpdateTreeView(const doc: TdomDocument);



Satirus   (2002-04-19 21:32) [18]

>>vuk Этот пример я разбирал первым делом. Но там один недостаток: ветки названы по типу, а не по имени элемента, к тому же сложно вытянуть атрибуты каждой ветки...



vuk   (2002-04-19 21:38) [19]

Ну и какие проблемы? Переписать создание узлов - и все дела. А как атрибуты вытягивать - я Вам уже писал.



Набережных С.   (2002-04-19 22:43) [20]

Пример с массивом:

type
TArr = array of array of TTreeNode;

procedure Parse(TV: TTreeView; var A: TArr);
var
n,m,k:integer;
begin
m:=0; n:=0;
while n < TV.Items.Count do
with TV.Items[n] do
begin
if Level >= m then
begin
m:=Level + 1;
SetLength(A,m);
end;
k:=Length(A[Level]);
SetLength(A[Level],k+1);
A[level,k]:=TV.Items[n];
Inc(n);
end;
end;

Пример вызова:

var
Arr:TArr;

Parse(TreeView1,Arr);
for n:= 0 to Pred(Length(Arr)) do
begin
for m:=0 to Pred(Length(Arr[n]))do
Memo1.Lines.Add(StringOfChar(" ",Arr[n,m].Level*4)+Arr[n,m].Text);
end;



Satirus   (2002-04-20 19:05) [21]

>>Набережных С. Ваш пример выдает ошибку Undeclared identifier "Items"



Набережных С.   (2002-04-20 19:29) [22]


> Satirus © (20.04.02 19:05)

У меня на D5 не выдает. Возможно, в D6 изменили TTreeView, но тут я помочь не смогу. А ты никаких изменений не вносил? Покажи на всякий случай свой код.



Satirus   (2002-04-20 20:04) [23]

>>Набережных С. Я его отправил Вам на мыло



Набережных С.   (2002-04-20 20:43) [24]

Письмо получил. Дело в том, что строка
Nodes[level,ChildCount]:=TreeView.Items[NodeCount];
стоит внутри блока with и у TTreeNode есть свойство TreeView: TCustomTreeView, а у TCustomTreeView свойство Items не опубликовано. Измени имя параметра TreeView и все будет нормально.




Форум: "Основная";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.05.02;
Скачать: [xml.tar.bz2];




Наверх





Память: 0.76 MB
Время: 0.024 c
1-2627            Satirus               2002-04-19 17:14  2002.05.02  
Tree Walker: Create


1-2509            Olivka                2002-04-20 19:09  2002.05.02  
Получение строки из Ворда


1-2550            mnemonic              2002-04-18 17:33  2002.05.02  
редактор компоненты


1-2603            Лана Розанова         2002-04-19 21:18  2002.05.02  
MediaPlayer


1-2528            Демон                 2002-04-21 14:36  2002.05.02  
Проблема с 6-ой ДЕЛФЁЙ