Форум: "Базы";
Текущий архив: 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.006 c