Консультация № 183102
09.05.2011, 01:10
55.50 руб.
0 8 1
Здравствуйте! У меня возникли сложности с таким вопросом:
Построить бинарное дерево поиска целочисленного типа данных. Выполнить обход дерева сверху вниз (корень - левое поддерево – правое поддерево). При обходе подсчитать:
- количество вершин, имеющих хотя бы одну ненулевую связь;
- количество вершин, имеющих две ненулевые связи;
- количество вершин, имеющих не более одной ненулевой связи.


среда программирования Turbo Pascal

Приложение:
Частично задание уже выполнено, не могу только разобраться с подсчетом вершин, ниже привожу листинг, хорошо если бы вы просто дополнили его и разъяснили что к чему (прокомментировали )

Program derevo;
Uses Crt;

Type inform = Integer;
ss = ^zveno;
zveno = Record
key: Integer;
inf: Inform;
left, right: ss;
End;

Var t:ss;
n,nn,c,i,k: Integer;


{----формирование дерева----}

Procedure Vstavka (Var p: ss; x: Integer);
Begin
If p = Nil Then
Begin
New (p);
p^.inf:=x;
p^.key:=1;
p^.left:=Nil;
p^.right:=Nil;
End;
If x<p^.inf Then Begin Vstavka (p^.left,x); End;
If x>p^.inf Then Begin Vstavka (p^.right,x); End;
End;

{----вывод дерева----}

Procedure Print (Var p: ss; h: Integer);
Var i: Integer;
Begin
If p <> Nil Then
Begin
Print(p^.right,h+4);
For i:=1 To h Do Write (' ');
Writeln (p^.inf);
Print (p^.left,h+4);
End;
End;


Procedure obxod();

{??????????????????????????????}


Begin ClrScr;
Writeln ('Vvedite koli4estvo elementov dereva: ');
Readln (n);
For i:=1 To n Do
Begin
Writeln('Vvedite o4erednoj element');
Read (c);
Vstavka (t,c);
End;
Print (t,c);

Readkey;
End.

Обсуждение

давно
Профессионал
304622
583
09.05.2011, 17:48
общий
это ответ
Здравствуйте, lexmod!

Дописанная программа ниже. Одно замечание: имеющийся алгоритм процедуры Vstavka рассчитан на строго различные значения. Введённое повторяющееся значение игнорируется, не включается в дерево. Поскольку я не знаю, предусмотрено ли это постановкой задачи, то исправлять не стал.

Код:

Program derevo;
Uses Crt;

{ Варианты запуска обхода с подсчетом:
1 - количество вершин, имеющих хотя бы одну ненулевую связь;
2 - количество вершин, имеющих две ненулевые связи;
3 - количество вершин, имеющих не более одной ненулевой связи.
}
Const NeMensheOdnoj=1;
Dve=2;
NeBolsheOdnoj=3;

Type inform = Integer;
ss = ^zveno;
zveno = Record
key: Integer;
inf: Inform;
left, right: ss;
End;

Var t:ss;
n,nn,c,i,k: Integer;


{----формирование дерева----}

Procedure Vstavka (Var p: ss; x: Integer);
Begin
If p = Nil Then
Begin
New (p);
p^.inf:=x;
p^.key:=1;
p^.left:=Nil;
p^.right:=Nil;
End;
If x<p^.inf Then Begin Vstavka (p^.left,x); End;
If x>p^.inf Then Begin Vstavka (p^.right,x); End;
End;

{----вывод дерева----}

Procedure Print (Var p: ss; h: Integer);
Var i: Integer;
Begin
If p <> Nil Then
Begin
Print(p^.right,h+4);
For i:=1 To h Do Write (' ');
Writeln (p^.inf);
Print (p^.left,h+4);
End;
End;

{ Рекурсивная функция, деалющая подсчёт для текущего дерева }
Function Count(p: ss; v: integer):integer;
Begin
{ Нет элемента -- результата ноль }
IF p = Nil Then Count:=0
Else Begin
{ Рассматриваются варианты вызова функции с соответствующими условием }
{ Первый вариант -- либо left, либо right не равны Nil }
If ((v = NeMensheOdnoj) and ((p^.left <> Nil) or (p^.right <> Nil)))
or
{ Второй вариант -- и left, и right не равны Nil }
((v = Dve) and ((p^.left <> Nil) and (p^.right <> Nil)))
or
{ Третий вариант -- либо left, либо right равны Nil }
((v = NeBolsheOdnoj) and ((p^.left = Nil) or (p^.right = Nil)))
{ Какой-то из вариантов сработал => ставим 1
и добавляем результаты рекурсивных вызовов левой и правой ветви }
Then Count:=1 + Count(p^.left,v) + Count(p^.right,v)
{ Иначе берём 0 и добавляем рекурсивные вызовы }
else Count:=0 + Count(p^.left,v) + Count(p^.right,v)
End;

End;

{----обход дерева----}


Begin ClrScr;
Writeln ('Vvedite koli4estvo elementov dereva: ');
Readln (n);
randomize;
For i:=1 To n Do
Begin
Writeln('Vvedite o4erednoj element');
Read (c);
Vstavka (t,c);
End;
{ Тут было Print (t,с); -- это ошибка }
Print (t,0);

Writeln('Koli4estvo vershin c >= 1 nenulevoj svjazi: ',Count(t,NeMensheOdnoj));
Writeln('Koli4estvo vershin c 2 nenulevymi svjazjami: ',Count(t,Dve));
Writeln('Koli4estvo vershin c <= 1 nenulevoj svjazi: ',Count(t,NeBolsheOdnoj));

Readkey;
End.


Приложение:
х
5
все четко и предельно ясно, спасибо!
Неизвестный
09.05.2011, 18:41
общий
Спасибо!
>> имеющийся алгоритм процедуры Vstavka рассчитан на строго различные значения.
я не взял это во нимание, есть ли возможность без глобальных изменений это поправить?
давно
Профессионал
304622
583
09.05.2011, 22:05
общий
>> имеющийся алгоритм процедуры Vstavka рассчитан на строго различные значения.
я не взял это во нимание, есть ли возможность без глобальных изменений это поправить?


Ну, как сказать, "глобальные" они или нет? Структура там неверна. Короче, во первых, рекурсивные вызовы сейчас никак не связаны с условием p = Nil, а они должны вызываться только если элемент существует, т.е. p <> Nil. Значит, они должны быть под else. Во вторых, два условия, под которыми находятся рекурсивные вызовы, не являются альтернативными -- x>=p^.inf не подпадает ни под одно из них. Поэтому повторяющиеся значения и пропадают.

(Забавно, что эти две ошибки компенсируют друг друга, предохраняя, кажется, от зацикливания.)

В общем, получается вот что:
Код:

Procedure Vstavka (Var p: ss; x: Integer);
Begin
If p = Nil Then
Begin
New (p);
p^.inf:=x;
p^.key:=1;
p^.left:=Nil;
p^.right:=Nil;
End
else begin
If x<p^.inf Then Begin Vstavka (p^.left,x); End;
If x>=p^.inf Then Begin Vstavka (p^.right,x); End;
end;
End;
давно
Профессор
230118
3054
04.09.2011, 03:49
общий
Полей key всегда равно 1, тогда зачем оно нужно?
давно
Профессионал
304622
583
07.09.2011, 13:54
общий
07.09.2011, 13:54
Адресаты:
Это было в исходном коде -- вероятно, закладка на будущее. У преподавателй бывают разные подходы. Один подход -- это такой минимализм: излагать материал и требовать решения точно на уровне текущей задачи. Такие преподаватели хотят и ученика приучать к экономии кода и т.п. При этом приходится часто спотыкаться на мелочах, отвлекаться -- теряется темп учебного процесса. И для слабых учеников это особенно трудно.
Другой -- это оговаривать и закладывать всякие элементы заранее и требовать их использования, хотя бы и бессмысленного (до поры до времени). Здесь есть опасность, что ученик может вспомогательные, технические детали и приёмы вопринять как обязательное требование, потерять смысл кода. Кроме того, такие излишества бывают от иллюзий в головах самих преподавателей -- тех, кто в своё время неправильно выучился.
давно
Профессионал
304622
583
07.09.2011, 14:00
общий
Адресаты:
от иллюзий в головах самих преподавателей -- тех, кто в своё время неправильно выучился.


До 30% моих первокурсников приходят из школы с неправильным алгоритмом пузырьковой сортировки в голове.
давно
Профессор
230118
3054
07.09.2011, 14:07
общий
Адресаты:
Ну они его же знают. А я и в универе не учила.
А можете объяснить алгоритм сортировки слиянием?
давно
Профессионал
304622
583
07.09.2011, 15:03
общий
Адресаты:
А можете объяснить алгоритм сортировки слиянием?


Где-нибудь через неделю. Болею.
Форма ответа