![]() |
|
|
#1
|
|||
|
|||
|
Всем здравствуйте, проходим тринарные деревья, а литературы по ним катастрофически мало, может кто-нибудь накидать литературы, где есть описание этой темы, примеры работы с такими деревьями, и подобное. И есть задача по В-дереву его нужно в В+ переделать и нужно чтобы вся информация была в листьях,а в узлах ключи...и листья в стек связать, и что бы был вывод дерева, ввод листьев и удаление листьев. Есть код
препод говорит, что у меня ошибка ,хотя все работает в принципе, помогите найти пожалуйста. |
|
#2
|
|||
|
|||
|
Код:
program another;
{$APPTYPE CONSOLE}
uses
SysUtils,
Windows;
//константы
const MAX=9999;
Help='Б-деревом (B-Tree) называется дерево, устроенное следующим образом:'+#13#10+
' 1) Каждая вершина содержит поля, в которых хранятся: количество n ключей,'#13#10+
' содержащихся в ней, сами ключи в неубывающем порядке и булевское значе-'#13#10+
' ние, истинное, когда вершина является листом. Внутренние вершины кроме'#13#10+
' того содержат n+1 указателей на её детей. У листьев детей нет, так что'#13#10+
' эти поля для них не определены.'#13#10+
' 2) Ключи, очевидно, служат границами, разделяющими значения ключей в под-'#13#10+
' деревьях.'#13#10+
' 3) Все листья находятся на одной глубине, называемой высотой дерева.'#13#10+
' 4) Число ключей, хранящихся в одной вершине, ограничено и сверху, и снизу.'#13#10+
' Границы задаются единым для всего дерева числом T>2, которое называется'#13#10+
' минимальной степенью (minimum degree) Б-дерева. При этом каждая вершина,'#13#10+
' кроме корня,содержит не менее T-1 и не более 2T-1 ключей. Соответственно,'#13#10+
' каждая вершина, кроме корня, имеет от T до 2T детей. Вершину, имеющую '#13#10+
' ровно 2T детей, назовем полной (full).'#13#10+
#13#10+
' В простейшем случае T=2, тогда у каждой внутренней вершины 2, 3 '#13#10+
' ребенка, и мы получаем так называемое 2-3-дерево (2-3-4 tree).'#13#10;
//--------------
//типы
type
TTree=^TTreeElem;
TTreeList=record
key:integer;
kid:TTree;
end;
TTreeElem=record
count:integer;
isLeave:boolean;
keys:array of TTreeList;
end;
//----------------------
//глобальные переменные
var Degree:integer=2; //минимальная степень Б-дерева по-умолчанию
Root:TTree=nil; //корень
//---------------------------------------------------------------------------
//------------------------------блок подпрограмм-----------------------------
procedure writex(x:string); //вывод русской строки
var z:string;
begin
setlength(z,length(x));
CharToOem(PChar(x),PChar(z));
write(z);
end;
procedure writelnx(x:string); //вывод русской строки и переход на новую
var z:string;
begin
setlength(z,length(x));
CharToOem(PChar(x),PChar(z));
writeln(z);
end;
function Search(x:integer; Tree:TTree; var index:integer):TTree;
var i:integer; //поиск в дереве
F:boolean;
begin
result:=nil;
F:=false;
i:=Tree^.Count-1;
while (x<Tree^.keys[i].Key) and (not F) do
begin
if Tree^.keys[i].Kid<>nil then
if ((i>0) and (x>Tree^.keys[i-1].Key)) or (i=0) then //рекурсивный заход
result:=Search(x,Tree^.keys[i].Kid,index); //только при необходимости
if (result<>nil) then
F:=true
else i:=i-1;
end;
if not F then
begin
if i>-1 then
if x=Tree^.keys[i].Key then begin result:=Tree; index:=i; end;
end;
end;
function InsertKey(x:integer;T:TTree):TTree;forward;
//вставка поддерева в дерево (при удалении)
procedure InsertTree(Tree:TTree; var ToTree:TTree);
var i:integer;
begin
if Tree<>nil then
begin
i:=Tree^.Count-1;
while(i>=0)do
begin
if Tree^.keys[i].Key<MAX then
begin
ToTree:=InsertKey(Tree^.keys[i].Key,ToTree);
end;
if Tree^.keys[i].Kid<>nil then InsertTree(Tree^.keys[i].Kid,ToTree);
i:=i-1;
end;
end;
end;
function TerminateTree(Tree:TTree):TTree; //уничтожение дерева
var i:integer;
begin
result:=nil;
if Tree<>nil then
begin
i:=Tree^.Count-1;
while(i>=0)do
begin
if Tree^.keys[i].kid<>nil then Tree^.keys[i].kid:=TerminateTree(Tree^.keys[i].kid);
i:=i-1;
end;
Setlength(Tree^.keys,0);
FreeMem(Tree,sizeof(TTreeElem));
Tree:=nil;
result:=Tree;
end;
end;
function Parent(Rt,T:TTree;var ind:integer):TTree;forward; //опережающее
//определение
//поиска родителя
function DeleteFromTree(x:integer;Tree:TTree;var R:boolean):TTree;
var i,j:integer; //удаление элемента, R -флаг реорганизации дерева
ST:TTree; //если удален элемент полностью - это
begin //приводит к нарушению уровневой структуры, нужна
result:=Tree; //перестройка всего дерева
R:=false;
if Tree<>nil then
begin
i:=Tree^.Count-1; //рекурсивно ищем элемент
while(i>=0)and(Tree<>nil)do
begin
if Tree^.keys[i].kid<>nil then
Tree^.keys[i].kid:=DeleteFromTree(x,Tree^.keys[i].kid,R);
if x=Tree^.keys[i].Key then
BEGIN //нашли удаляемый
if Tree^.isLeave then //это лист
begin
if Tree^.Count>1 then //есть много элементов
begin
for j:=i to Tree^.Count-2 do //сжимаем
Tree^.keys[j]:=Tree^.keys[j+1];
Tree^.Count:=Tree^.Count-1;
SetLength(Tree^.keys,Tree^.Count);
end
else //это лист и в нем мы удаляем последний - реорганизация
begin
Tree^.keys[i].key:=MAX;
R:=true;
end;
end
else
if Tree^.Count>2 then //это не лист, но в нем есть много элементов
begin
ST:=Tree^.keys[i].Kid; //массив имеет более 1 элемента
for j:=i to Tree^.Count-2 do //сжимаем
Tree^.keys[j]:=Tree^.keys[j+1];
Tree^.Count:=Tree^.Count-1;
SetLength(Tree^.keys,Tree^.Count);
if ST<>nil then //есть потомок и если текущий (на месте удаленного)
begin //не имеет потомков - прицепляем, иначе - перестраиваем текущую вершину -->
if Tree^.keys[i].kid=nil then Tree^.keys[i].kid:=ST
else
InsertTree(ST,Tree) // --> добавлением в нее всех потомков удаленного
end;
end
else //удаляем элемент полностью - реорганизация
begin
Tree^.keys[i].key:=MAX;
R:=True;
end;
i:=0;
result:=Tree;
END;
i:=i-1;
end;
end;
end;
function Parent(Rt,T:TTree;var ind:integer):TTree; //поиск родителя
var i:integer;
begin
i:=0;
result:=nil;
while (Rt^.keys[i].kid<>T) and (i<Rt^.count) and (Rt<>T) do
begin
if Rt^.keys[i].kid<>nil then result:=Parent(Rt^.keys[i].kid,T,ind);
if result<>nil then break;
inc(i);
end;
if i<Rt^.count then
if (Rt^.keys[i].kid=T) then begin result:=Rt;ind:=i;end;
end;
function Split(T:TTree):TTree; //разделение вершины (рекурсивное)
var T1,T2,T3:TTree;
var i,j,m,d,k:integer;
begin
new(T2);
T2^.count:=Degree-1;
SetLength(T2^.keys,T2^.count);
T2^.isLeave:=true;
for i:=0 to Degree-2 do
begin
T2^.keys[i]:=T^.keys[i];
if T^.keys[i].kid<>nil then T2^.isLeave:=false;
end;
new(T3);
T3^.count:=T^.count-Degree;
SetLength(T3^.keys,T3^.count);
T3^.isLeave:=true;
for i:=Degree to T^.count-1 do
begin
T3^.keys[i-Degree]:=T^.keys[i];
if T^.keys[i].kid<>nil then T3^.isLeave:=false;
end;
m:=Degree-1;
if T^.keys[m].kid<>nil then
begin
T2^.count:=T2^.count+1;
SetLength(T2^.keys,T2^.count);
T2^.keys[T2^.count-1].kid:=T^.keys[m].kid;
T2^.keys[T2^.count-1].key:=MAX;
end;
j:=T^.keys[m].key;
T1:=Parent(Root,T,i);
if T1<>nil then
begin
if T1^.keys[T1^.count-1].key=MAX then D:=2*Degree else
D:=2*Degree-2;
if T1^.count>=D then
T1:=Split(T1)
else
begin
i:=0;
while (j>T1^.keys[i].key)and(i<T1^.count) do inc(i);
if i<=T1^.count then //insert to middle or start
begin
T1^.Count:=T1^.count+1;
SetLength(T1^.keys,T1^.count);
for k:=T1^.count-1 downto i+1 do
T1^.keys[k]:=T1^.keys[k-1];
T1^.keys[i].key:=j;
T1^.keys[i].kid:=T2;
T1^.keys[i+1].kid:=T3;
T1^.isLeave:=false;
end
end
end
else
begin
SetLength(T^.keys,2);
T^.count:=2;
T^.isLeave:=false;
T^.keys[0].key:=j;
T^.keys[0].kid:=T2;
T^.keys[1].kid:=T3;
T^.keys[1].key:=MAX;
end;
result:=T;
end; |
|
#3
|
|||
|
|||
|
Код:
function InsertKey(x:integer;T:TTree):TTree;
var i,j,D:integer;
begin
if T=nil then
begin
new(T);
T^.count:=1;
T^.isLeave:=true;
SetLength(T^.keys,1);
T^.keys[0].key:=x;
T^.keys[0].kid:=nil;
Root:=T;
end
else
begin
if T^.keys[T^.count-1].key=MAX then
D:=2*Degree
else
D:=2*Degree-2;
if T^.count>D then
begin
T:= Split(T);
result:=InsertKey(x,Root)
end
else
begin
i:=0;
while (x>T^.keys[i].key)and(i<T^.count) do inc(i);
if x<>T^.keys[i].key then
begin
if i<T^.count then //insert to middle or start
begin
if (T^.keys[i].kid<>nil)then
result:=InsertKey(x,T^.keys[i].kid)
else
begin
T^.Count:=T^.count+1;
SetLength(T^.keys,T^.count);
for j:=T^.count-1 downto i+1 do
T^.keys[j]:=T^.keys[j-1];
T^.keys[i].key:=x;
T^.keys[i].kid:=nil;
end;
end
else //insert to end
if i=T^.count then
begin
T^.count:=T^.count+1;
SetLength(T^.keys,T^.count);
T^.keys[i].key:=x;
T^.keys[i].kid:=nil;
end;
end;
end;
end;
result:=T;
end;
procedure PrintTree(Tree:TTree;Pos:integer); //вывод дерева ПКЛ обходом
var i,j:integer;
begin
if Tree<>nil then
begin
i:=Tree^.Count-1;
while(i>=0)do
begin
if Tree^.keys[i].key<MAX then
begin
for j:=1 to Pos do write(' ');
writeln(Tree^.keys[i].key);
end;
if Tree^.keys[i].kid<>nil then PrintTree(Tree^.keys[i].kid,Pos+5);
i:=i-1;
end;
end;
end;
procedure Reorganize(var Tree:TTree); //перестроение дерева
var s:array of integer;
i:integer;
procedure ReBuildTree(Tree:TTree); //построение нового на основе
var i:integer; //старого без удаляемого
begin
if Tree<>nil then
begin
i:=Tree^.Count-1;
while(i>=0)do
begin
if Tree^.keys[i].key<MAX then
begin
setlength(s,length(s)+1);
s[length(s)-1]:=Tree^.keys[i].key;
end;
write('.');
sleep(10);
if Tree^.keys[i].kid<>nil then ReBuildTree(Tree^.keys[i].kid);
i:=i-1;
end;
end;
end;//get tree
begin
writeln;
writex('Производим реорганизацию дерева...');
setlength(s,0);
ReBuildTree(Tree);
writeln;
Tree:=TerminateTree(Tree);
for i:=0 to length(s)-1 do
Tree:=InsertKey(s[i],Tree);
writeln;
writelnx('Дерево реорганизовано!');
writeln;
end;
var M1,M2:byte;
i,j,MaxG,k,c,n:integer;
R:boolean; //флаг реорганизации при удалении
S:TTree; //для поиска
begin
// writeln(' ----------- ');
writelnx('| Б-деревья |');
// writeln(' ----------- ');
writeln;
repeat
writelnx('Выберите пункт меню:');
//writeln('^^^^^^^^^^^^^^^^^^^^');
writelnx(' 1) Создание Б-дерева');
writelnx(' 2) Просмотр дерева');
//writelnx(' 3) Поиск в Б-дереве');
writelnx(' 4) Изменение дерева');
//writelnx(' 5) Выход (0-помощь)');
write(' : ');
readln(M1);
case M1 of
0:begin
writelnx(Help);
writelnx('Нажмите <Enter>...');
readln;
end;
1:begin
repeat
writeln;
writelnx('Создание Б-дерева:');
writelnx(' 1) Случайными числами');
writelnx(' 2) Ввод элементов вручную');
writex(' 3) Изменить степень (текущая T=');writeln(Degree,')');
// writelnx(' 4) Возврат');
write(' : ');
readln(M2);
if (M2>0) and (M2<4) then Root:=TerminateTree(Root);
case M2 of
1:begin
writex('Введите желаемое количество элементов (узлов) Б-дерева:');
readln(MaxG);
// writex('Процесс создания отследить (1-да, 2-нет)? ');
// readln(j);
j:=2;
randomize;n:=0;
for i:=1 to MaxG do
begin
c:=random(1000);
if (j=1) then begin writex('Подаем >>> ');writeln(c); end;
if Root<>nil then
begin
if Search(c,Root,k)=nil then
Root:=InsertKey(c,Root)
else
begin
if j=1 then writelnx('Такое значение уже пристутствует в дереве!')
else n:=n+1
end
end
else Root:=InsertKey(c,Root);
if (j=1) then
begin
writex('нажмите ввод...');readln;
writelnx('Б - ДЕРЕВО');
PrintTree(Root,3);
// writelnx('---------------------------------------------------');
end;
end;
if j<>1 then writelnx('Повторилось '+IntToStr(n)+' значений');
writelnx('Дерево готово.');
end;
2:begin
writelnx('Вводите числа одно за одним через пробел или <Enter>.');
writelnx('По окончании - введите -1');
read(j);
while (j<>-1) do
begin
if Root=nil then Root:=InsertKey(j,Root) else
if Search(j,Root,c)=nil then
Root:=InsertKey(j,Root)
else
writelnx('Есть уже такое значение');
writelnx('Б - ДЕРЕВО');
PrintTree(Root,3);
//writelnx('---------------------------------------------------');
read(j);
end;
writelnx('Дерево готово');
end;
3:begin
writelnx('Изменение минимальной степени дерева:');
writex('Введите новое значение(текущее T=');write(Degree,'): ');
readln(Degree);
end;
end;
until M2<>3;
end;
2:if Root=nil then writelnx('>>>>>>>>>>>>>>>>> Дерево не создано!') else
begin
writelnx('-------------------Б - ДЕРЕВО----------------------');
PrintTree(Root,3);
//writelnx('---------------------------------------------------');
end;
3:if Root=nil then writelnx('>>>>>>>>>>>>>>>>> Дерево не создано!') else begin
writex('Введите искомое значение: ');readln(j);
S:=Search(j,Root,i);
if S<>nil then
begin
writelnx('Элемент найден!');
writex('Значение: ');writeln(S^.keys[i].key);
if S^.keys[i].kid<>nil then
begin
writelnx('Потомки:');
PrintTree(S^.keys[i].kid,3);
end else
writelnx('Потомков нет у данного элемента');
end else writelnx('Нет такого значения!');
end;
4:if Root=nil then writelnx('>>>>>>>>>>>>>>>>> Дерево не создано!') else begin
repeat
writelnx('Выберите пункт меню:');
writelnx('1) Вставка');
writelnx('2) Удаление');
writelnx('3) Возврат');
write(' : ');
readln(j);
case j of
1:begin
writelnx('Вводите ключи(числа менее '+IntToStr(MAX)+') (-1 - завершить ввод):');
readln(k);
while(k<>-1)do
begin
if Root=nil then Root:=InsertKey(k,Root) else
if Search(k,Root,c)=nil then
Root:=InsertKey(k,Root)
else writelnx('Есть уже такое значение');
writeln;
writelnx('-------------------Б - ДЕРЕВО----------------------');
PrintTree(Root,3);
writelnx('---------------------------------------------------');
writelnx('Еще? (-1 - конец)');
readln(k);
end;
j:=3;
end;
2:
begin
writex('Введите значение для удаления: ');
readln(k);
S:=Search(k,Root,i);
if S<>nil then
begin
Root:=DeleteFromTree(k,Root,R);
if R then
Reorganize(Root);
writeln;
writelnx('-------------------Б - ДЕРЕВО----------------------');
PrintTree(Root,3);
writelnx('---------------------------------------------------');
writelnx('Элемент успешно удален!');
end
else writelnx('Элемент не найден!');
j:=3;
end;
end;//case
until j=3;
end;
end;
until M1=5;
Root:=TerminateTree(Root);
end. |
|
#4
|
|||
|
|||
|
Это все код задачи, которую я решал.
|