Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2002.08.19;
Скачать: [xml.tar.bz2];

Вниз

Построение (прохождение) все ветвей дерева   Найти похожие ветки 

 
MikeFW   (2002-07-30 10:27) [0]

Уважаемые Мастера,
подскажите, пожалуйста, как мне построить (пройти) все ветви дерева.
Описание: у меня все дерево храниться в одной таблице базы данных (индекс узла - Id, название узла, родитель).

но при таком коде как написано ниже я могу пройти только одну ветку, так как запрос Query1 меняется на более глубоких уровнях.

Подскажите, как мне исправить данный код или какой другой алгоритм использовать для прохождения всего дерева, не хранить же все прошлые запросы в массиве?

// я вызываю построение дерева

procedure TForm1.Button1Click(Sender: TObject);
begin
ExpandLevelTemp(TreeView1.Selected);
end;

// построение всей ветки

Procedure TForm1.ExpandLevelTemp( Node : TTreeNode);
Var ID , i : Integer;
TreeNode : TTreeNode;
D: PItemRec;
Begin
// если стоим на "корневом" узле без "родителей"
IF Node = nil Then ID:=0
Else ID:=PItemRec(Node.Data)^.Id;

// ищем "детей" для текущего узла
Query1.Close;
Query1.ParamByName("ParentID").AsInteger:=ID;
Query1.Open;

// Проходим всех "детей"
For i:=1 To Query1.RecordCount Do
Begin
New(D);
D^.Id := Query1.FieldByName("RUBRICID").AsInteger;

TreeNode:=TreeView1.Items.AddChildObject(Node ,
Query1.FieldByName("RUBRICNAME").AsString,
D);

ShowMessage(Query1.FieldByName("RUBRICNAME").AsString);

// отбираем "детей" для будущего узла
Query2.Close;
qQuery2.ParamByName("ParentID").AsInteger:=q.FieldByName("RUBRICID").AsInteger;
Query2.Open;

// если есть "дети" то идем дальше
if Query2.RecordCount > 0 then
ExpandLevelTemp(TreeNode);

Query1.Next;
End;
End;


 
fnatali   (2002-07-30 11:03) [1]

Зачем строить все ветки дерева сразу?
www.delphikingdom.com/helloworld/dbtreeview.htm#2


 
MikeFW   (2002-07-30 11:20) [2]

Мне необходимо все строить сразу так как надо выводить в файл всю структуру сразу:
т.е.
читаю корневой узел - пишу заголовок 1
читаю его подуровень - пишу раздел 1
читаю еще на уровень вниз - пишу строку 1 в разде 1
...
пишу строку N в раздел 1
дальше буресь за раздел 2 ...
дальше берусь за заголовок 2 ...

вот для этого мне надо проходить все дерево


 
MikeFW   (2002-07-30 11:21) [3]

я думаю, что без привлечения к этой операции TreeView алгоритм будет работать быстрее, но как его построить по одному только Query1 (все уровни в одной таблице)?


 
wdr   (2002-07-30 12:13) [4]

В данном случае требуется написать рекурсивный запрос,
если конечно MSSQL поддерживает оного. В InterBase такой запрос работает без проблем и довольно быстро.


 
MikeFW   (2002-07-30 12:19) [5]

Если вам не трудно, то приведите, пожалуйста, пример такого рекурсивного запроса, похожего на необходимый мне запрос.


 
fnatali   (2002-07-30 12:30) [6]

См. в архиве где-то 25.05.2002 начало обсуждения было
Выборка из дерева [MSSQL]
там и алгоритмы разные приводились, сейчас заново всё это разводить просто лень...



 
3JIA9I CyKA   (2002-07-30 12:33) [7]

Если надо сразу всё дерево выстраивать, то лучше залить всё себе в проге рекурсить.
Мне так кааца


 
Jee   (2002-07-30 12:47) [8]

Как раз недавно я такую же проблему решал. Народ прав - здесь не обойтись без рекурсии. Иные алгоритмы неоптимальны. Если хочешь, я тебе по почте скину файлец, правда на билдере. Коли С++ знаешь, то мигом поймешь что к чему. Или могу тут привести код, выбирай пока, а я щас найду.


 
MikeFW   (2002-07-30 12:57) [9]

Спасибо, скинь пожалуйста код на форум...


 
Jee   (2002-07-30 13:00) [10]

Таблички делал адошные.
Вызов построения дерева:
----------
void __fastcall TTreeForm::FormShow(TObject *Sender)
{
TTreeNode * Root;
TreeView->Items->Clear();
NodeID = new int[DM->Tree->RecordCount];
Root = TreeView->Items->AddObjectFirst(NULL, "Дерево решений \"" + DM->TreesTreeName->Value + "\"", NULL);

TreeOut(Root, 0, MainForm->ResultID);
TreeView->FullExpand();
}
//---------------------------------------------------------------// вывод дерева на экран
//---------------------------------------------------------------bool __fastcall TTreeForm::TreeOut(TTreeNode* ParentNode, int ParentID, int Result)
{
TTreeNode* CurNode;
bool result = false; // нет подчиненных
DM->TreeBuilding = true;
// выберем только те, у которых ParentID соответствует заданному
DM->Tree->Filter = "ParentID = " + IntToStr(ParentID);
DM->Tree->Filtered = true;
// создание массива с кодами ID выбранных записей
if (DM->Tree->RecordCount > 0){
int count = DM->Tree->RecordCount;
NodeIV* a = new NodeIV[count];
DM->Tree->First();
for(int i = 0; i<count; i++, DM->Tree->Next()){
a[i].ID = DM->TreeID->Value;
a[i].IsLeaf = DM->TreeLeaf->Value;
}
// проход по массиву и рекурсивное построение дерева
for (int i = 0; i<count; i++){
// построим название узла
AnsiString NodeString = NodeNameBuilding(a[i].ID, a[i].IsLeaf);
CurNode = TreeView->Items->AddChildObject(ParentNode, NodeString, NodeID);
*(NodeID++) = a[i].ID;
TreeOut(CurNode, a[i].ID, Result);
}
delete[] a;
result = true; // были подчиненные узлы
}
DM->TreeBuilding = false;
return result;
}
Ну и структурка наконец
--------------
struct NodeIV
{
int ID;
bool IsLeaf;
};



 
AlexSam   (2002-07-30 15:06) [11]

type
PMyRec = ^TMyRec;
TMyRec = record
group_id : integer;
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
BufNode : array of TTreeNode;
CountNode : integer;
NumNode : integer;
PrGroup_name : string;
PrGroup_id : integer;
PrParent_id : integer;
MyRecPtr: PMyRec;
begin
with IBQuery1 do
begin
Open;

CountNode:=0;
First;
while not EOF do
begin
Inc(CountNode);
Next;
end;
SetLength(BufNode,CountNode+100);

First;
NumNode:=1;
while not EOF do
begin
PrGroup_name:=FieldByName("group_name").AsString;
PrGroup_id:=FieldByName("group_id").AsInteger;
PrParent_id:=FieldByName("group_parent").AsInteger;

BufNode[NumNode]:=TTreeNode.Create(TreeView1.Items);

New(MyRecPtr);
MyRecPtr^.group_id:=BufInt;

If PrParent_id=0 Then
begin
BufNode[NumNode]:=TreeView1.Items.AddObject(nil, PrGroup_name, MyRecPtr);
end
else
begin
BufNode[NumNode]:=TreeView1.Items.AddChildObject(BufNode[PrParent_id], PrGroup_name, MyRecPtr);
end;

Inc(NumNode);

next;
end;
end;
end;


 
LEKSYS   (2002-07-30 16:18) [12]

//создание формы исполнения бюджета
procedure TIsp_form_buidget.FormCreate(Sender: TObject);
Var ItemMain,ItemChild:TTreeNode;
CurItem:TMyItem;
i:Integer;
begin
_kod_podr:=StrToInt(_globalini.ReadString("Settings","Pred",""));//считать код исполнителя по умолчанию из ini файла
RxLabel3.Caption:=IntToStr(_year)+ " год";
RxLabel4.Caption:=IntToStr(_year)+ " год";
ItemsList:=TList.Create; //создать список
RzTreeView1.Items.Clear; //очистить дерево подразделений
RzTreeView2.Items.Clear; //очистить дерево статей бюджета
_node:= RzTreeView1.Items.Add(nil,"Все подразделения");//добавить начальный уровень к дереву подразделений

begin
with Data_module,Query_kod_podr do //запрос для выбора назв. подразделений построение дерева
begin
Data_module.Query_kod_podr.Prepared;//подготовка запроса
Open;
First;
While Not Data_module.Query_kod_podr.Eof do //пока не конец базы данных
begin
RzTreeView1.Items.AddChild(_node,Data_module.Query_kod_podr.FieldByName("podr").AsString); //добавление в дерево названий подр.
Next;
end
end
end;
Data_module.Query_st_buidget.Active:=False; //запрос для выбора статей бюджета
Data_module.Query_st_buidget.Prepared;
Data_module.Query_st_buidget.Active:=True;
Data_module.Query_st_buidget.First;

while not Data_module.Query_st_buidget.Eof do //заполнение дерева данными из базы st_buidget
begin
ItemMain:=nil;
if ItemsList.Count<>0 then
for i:=1 to ItemsList.Count do
begin
CurItem:=ItemsList.Items[i-1];
if CurItem.Item<>nil then
if CurItem.KOD=Data_module.Query_st_buidget.FieldByName("KOD_CHILD").AsInteger then
ItemMain:=CurItem.Item;
end;
ItemChild:=RzTreeView2.Items.AddChild(ItemMain,"");
ItemsList.Add(TMyItem.Create(Data_module.Query_st_buidget.FieldByName("KOD_SB").AsInteger,ItemChild));
ItemChild.Text:=Data_module.Query_st_buidget.FieldByName("NAME_SB").AsString;
Data_module.Query_st_buidget.Next;
end;
end;


 
MikeFW   (2002-07-30 16:51) [13]


для AlexSam

ваш алгоритм будет работать только если дерево построено правильно, т.е. в таблице сперва идет "корневой" уровень, потом второй и так далее, а если все перемешано?

например, берем "корень" [200] - запись и заисываем его в BufNode[10] , а теперь берем его поуровень и что получается, он ссылается на BufNode[200]?



Страницы: 1 вся ветка

Форум: "Базы";
Текущий архив: 2002.08.19;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.49 MB
Время: 0.007 c
1-60555
Peroon
2002-08-07 16:16
2002.08.19
Программная очистка поля изображения


3-60483
Dmitr
2002-07-04 15:05
2002.08.19
messagedlg?


6-60781
Airs
2002-06-07 17:51
2002.08.19
Проблема с передачей сложных данных


3-60523
alexvan
2002-07-30 13:00
2002.08.19
Ошибка при редактировании таблицы.


8-60759
vetall
2002-04-04 10:44
2002.08.19
jpg





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский