Дерево, с неверным обходом - PascalABC.NET
Формулировка задачи:
В общем, есть программа, в которую я добавил доп. функцию "обхода в ширину" и она работает неверно.
Эта процедура выдает элементы не по уровням, а просто в порядке, в каком изначально дано дерево. Как исправить? Всем добра
(код прилагаю ниже)
Решение задачи: «Дерево, с неверным обходом»
textual
Листинг программы
// uses crt;
const
n = 10;
type
PTree = ^TTree;
TTree = record
num: integer;
LEFT, RIGHT: PTree;
end;
tarr = array[0.. n - 1] of PTree;
var
a: array[1..n] of integer;
i, z, v, max, x: integer;
predkor, Hkor, kor: Ptree;
////вывод дерева на экран////
procedure print(TREE: Ptree; n: integer);
var
q: integer;
begin
if TREE <> nil then //пока элемент не равен nil
begin//выводим кол-во пробелов, равное уровню
for q := 1 to n do
write('*'); //Выводим ключ
writeln(TREE^.num); //повторяем для левого и правого
print(TREE^.LEFT, n + 1);
print(TREE^.RIGHT, n + 1);
end;
end;
////вставка////
procedure insert(var TREE: Ptree; x: integer);
var
CUR, TNEW: PTree;
begin
////////Текущему - начальный/////////
CUR := TREE;
//////// Если список пустой///////
if CUR = nil then
begin
new(TNEW);
TNEW^.num := x;
TNEW^.LEFT := nil;
TNEW^.RIGHT := nil;
//Присвоить начальному - текущий
Hkor := TNEW;
end
//Если списой не пустой
else
begin
//Если текущий элемент больше введенного
new(TNEW);
TNEW^.num := x;
TNEW^.RIGHT := nil;
TNEW^.LEFT := nil;
if CUR^.num > x
then
/////////Если слева нет элемента///////////
if CUR^.LEFT = nil
then
////////поставить элемент слева//////
begin
TREE^.LEFT := TNEW;
end
////////Если есть элемент, то перескочить на него//////
else begin CUR := CUR^.LEFT; insert(cur, x); end
else
///////////то же с правым////////////
if CUR^.RIGHT = nil
then
begin
TREE^.RIGHT := TNEW;
end
else begin CUR := CUR^.RIGHT; insert(cur, x); end;
end;
end;
////Очистка дерева////
procedure clear(var tree: ptree) ;
var
cur: ptree;
begin
cur := tree;
if cur <> nil then
begin
clear(cur^.LEFT);
clear(cur^.RIGHT);
dispose(cur);
end;
tree := nil;
end;
////Обход дерева по уровням////
procedure PrintByLevel(level: integer;
var items: tarr; count: integer);
var
i, new_count: integer;
begin
if count <> 0 then begin
writeln('level = ', level);
new_count := 0;
for i := 0 to pred(count) do
begin
write(items[i]^.num:4);
if items[i]^.left <> nil then begin
inc(new_count); items[count + new_count - 1] := items[i]^.left;
end;
if items[i]^.right <> nil then begin
inc(new_count); items[count + new_count - 1] := items[i]^.right;
end;
end;
writeln;
for i := 0 to Pred(new_count) do
items[i] := items[count + i];
PrintByLevel(level + 1, items, new_count);
end;
end;
/////меню////
procedure menu(v: integer);
var
arr: tarr;
begin
case (v) of
1: begin writeln('Введите ключ');read(z); insert(Hkor, z); end;
2: begin if Hkor <> nil then print(Hkor, 0) else writeln('Дерево пусто'); end;
3: begin clear(Hkor); end;
4:
begin
writeln('');
arr[0] := HKor;
PrintByLevel(0, arr, 1);
end;
0: v := 0;
end;
Writeln;
writeln(' <<<<<<<<<<<<<<<<< Меню:>>>>>>>>>>>>>>>>>>>');
writeln(' -----Добавление элемента в дерево-------- : 1');
writeln(' --------------Печать дерева-------------- : 2');
writeln(' ----- -------Очистка дерева ------------- : 3');
writeln(' ------Обход дерева в порядке уровней----- : 4');
writeln(' ------------------Выход ----------------- : 0');
Writeln;
end;
////Начало программы////
begin
a[1] := 7;
a[2] := 5;
a[3] := 9;
a[4] := 3;
a[5] := 1;
a[6] := 10;
a[7] := 6;
a[8] := 8;
a[9] := 4;
a[10] := 2;
Hkor := nil;
for i := 1 to n do
begin
insert(Hkor, a[i]);
end;
v := 1; writeln(' <<<<<<<<<<<<<<<<< Меню:>>>>>>>>>>>>>>>>>>>');
writeln(' -----Добавление элемента в дерево-------- : 1');
writeln(' --------------Печать дерева-------------- : 2');
writeln(' ----- -------Очистка дерева ------------- : 3');
writeln(' ------Обход дерева в порядке уровней----- : 4');
writeln(' ------------------Выход ----------------- : 0');
Writeln;
while v <> 0 do
begin
readln(v);
menu(v);
Writeln;
end;
end.
Объяснение кода листинга программы
- Начнем с объявления переменных и типов данных. У нас есть следующие переменные:
- n (константа, обозначающая количество элементов в дереве)
- PTree (тип данных, представляющий узел дерева)
- TTree (тип данных, представляющий дерево)
- tarr (массив, используемый для обхода дерева по уровням)
- a (массив, содержащий ключи для добавления в дерево)
- i, z, v, max, x (переменные, используемые в процедуре вставки и обхода дерева)
- predkor, Hkor, kor (переменные, используемые в обходе дерева)
- Далее идут процедуры:
- print (вывод дерева на экран)
- insert (вставка элемента в дерево)
- clear (очистка дерева)
- PrintByLevel (обход дерева по уровням)
- menu (основная программа, обрабатывающая пользовательский ввод)
- В основной программе создается дерево, заполняется массив a, инициализируется переменная Hkor как корневой узел дерева. Затем выполняется цикл, позволяющий пользователю взаимодействовать с программой через меню.
- В меню пользователю предлагаются следующие опции:
- 1: Ввести ключ и добавить его в дерево
- 2: Печать дерева
- 3: Очистка дерева
- 4: Обход дерева по уровням
- 0: Выход из программы
- Процедура insert отвечает за вставку элемента в дерево. Она рекурсивно обходит дерево, ища место для вставки нового элемента. Если дерево пустое, новый элемент становится корнем. Если элемент больше текущего, он вставляется в правую поддерево. Если элемент меньше текущего, он вставляется в левое поддерево. Если элемент равен текущему, ничего не происходит.
- Процедура clear используется для очистки дерева. Она рекурсивно обходит дерево, очищая каждый узел, и затем освобождает память, выделенную под дерево.
- Процедура PrintByLevel используется для обхода дерева по уровням. Она принимает уровень, массив для хранения узлов и счетчик количества элементов. Она рекурсивно обходит дерево, печатая каждый узел и его ключ.
- Процедура menu обрабатывает пользовательский ввод и вызывает соответствующие процедуры в зависимости от выбранной опции.
- В начале программы создается дерево, заполняется массив a и выполняется цикл, позволяющий пользователю взаимодействовать с программой через меню.