IPB

Здравствуйте, гость ( Вход | Регистрация )

2 страниц V   1 2 >  
Reply to this topicStart new topic
> Двоичные деревья в паскале
Palpalich
сообщение 15 Dec 2008, 13:15
Сообщение #1

Newbie
Сообщений: 31
Спасибо сказали: 0 раз




помогите пожалуйста решить задачу на паскале:
Составить программу вычисления суммы всех ключей дерева.
я прогу написал, чтобы она формировала и выводило дерево, а посчитать ключи на могу...
прога:
program derevo;
uses crt;
Type inform = integer; {тип информационного поля}
ss = ^zveno;
zveno = record
key: integer;
inf: inform;
left, right: ss;
end;
Procedure vstavka(var p: ss; k: integer);

Begin
If p = nil then
Begin
New(p); p^.key:=k; p^.left:=nil; p^.right:=nil;
End
Else
If k < p^.key then vstavka(p^.left, k);
If k > p^.key then vstavka(p^.right, k);
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^.key);
Print(p^.left, h + 4);
End


End;
Procedure ch( n, s: integer);
Var i: integer; p: ss; d:integer;
Begin
If p <> nil then begin
for i:=1 to n do
s:=p^.inf+s;
writeln(s);
end;end;
var t:ss;n,c,f,i,y:integer;
begin clrscr;
writeln('vvedite kolichestvo kluchey dereva');
readln(n);
writeln('vvedite kluchi dereva');
for i:=1 to n do
begin
read©;
vstavka(t,c);
end;
print(t,c);
ch(f,n);
readkey; end.
подскажите как подсчитать ключи....
Go to the top of the pageAdd Nick
 
+Quote Post
Монца
сообщение 15 Dec 2008, 14:03
Сообщение #2

good news, everyone!
Сообщений: 918
Спасибо сказали: 93 раза




Надо реализовать какой нить обход дерева.


--------------------
этъя опять
Go to the top of the pageAdd Nick
 
+Quote Post
Palpalich
сообщение 16 Dec 2008, 16:42
Сообщение #3

Newbie
Сообщений: 31
Спасибо сказали: 0 раз




дак я и не знаю как это организовать...
Go to the top of the pageAdd Nick
 
+Quote Post
Tervyn
сообщение 16 Dec 2008, 17:25
Сообщение #4

Immortal
Сообщений: 523
Спасибо сказали: 35 раз




Ты уже сделал обход дерева при выводе ключейsmile.gif Подсчет суммы ведется аналогично. Например так:
Код
function CalcKeySumm(Tree: SS): Integer;
begin
 if Tree = nil then
 begin
   CalcKeySumm := 0;
 end else
 begin
   CalcKeySumm := Tree^.Key + CalcKeySumm(Tree^.Left) + CalcKeySumm(Tree^.Right);
 end;
end;

От того в каком порядке стоят слагаемые обход дерева называется левосторонним, и т.д.


Спасибо сказали:
Go to the top of the pageAdd Nick
 
+Quote Post
Palpalich
сообщение 17 Dec 2008, 13:32
Сообщение #5

Newbie
Сообщений: 31
Спасибо сказали: 0 раз




спасибо огроменное, всё работает!!! слушай, дак это получается рекурсивная функция, правильно? и конечным результатом будет дерево??(Tree: SS)
Go to the top of the pageAdd Nick
 
+Quote Post
Монца
сообщение 17 Dec 2008, 14:34
Сообщение #6

good news, everyone!
Сообщений: 918
Спасибо сказали: 93 раза




Функция рекурсивная, но можно обойтись и без рекурсии.


--------------------
этъя опять
Go to the top of the pageAdd Nick
 
+Quote Post
Palpalich
сообщение 17 Dec 2008, 14:46
Сообщение #7

Newbie
Сообщений: 31
Спасибо сказали: 0 раз




как тогда организовать обход дерева, и что на выходе?
Go to the top of the pageAdd Nick
 
+Quote Post
Dofur
сообщение 17 Dec 2008, 15:13 (Сообщение отредактировал Dofur - 17 Dec 2008, 15:14)
Сообщение #8

Immortal
Сообщений: 1 664
Спасибо сказали: 30 раз




Цитата(Palpalich @ 17 Dec 2008, 13:32)
спасибо  огроменное, всё работает!!! слушай, дак это получается рекурсивная функция, правильно? и конечным результатом будет дерево??(Tree: SS)


Конечным результатом у функции будет целочисленное число - там же указанно

function CalcKeySumm(Tree: SS): Integer;


--------------------
Go to the top of the pageAdd Nick
 
+Quote Post
Palpalich
сообщение 17 Dec 2008, 18:03
Сообщение #9

Newbie
Сообщений: 31
Спасибо сказали: 0 раз




дак (Tree: SS) - это ссылочный тип данных...

Добавлено ([mergetime]1229526216[/mergetime]):
помогите регить ещё одну задачу please:):
Дан текст (в текстовом файле). В дереве, построенном из слов текста определить количество вершин дерева, содержащих слова, являющиеся палиндромами.
Примечание. Тип элемента в узле дерева (String), кроме того, необходимо ввести счетчик числа повторений каждого слова.
Go to the top of the pageAdd Nick
 
+Quote Post
Dofur
сообщение 17 Dec 2008, 18:03
Сообщение #10

Immortal
Сообщений: 1 664
Спасибо сказали: 30 раз




Функция берет дерево - возвращает целое число.Почему результат по твоему должен быть деревом?


--------------------
Go to the top of the pageAdd Nick
 
+Quote Post
Tervyn
сообщение 17 Dec 2008, 19:38 (Сообщение отредактировал Tervyn - 17 Dec 2008, 19:40)
Сообщение #11

Immortal
Сообщений: 523
Спасибо сказали: 35 раз




Цитата(Palpalich @ 17 Dec 2008, 13:32)
спасибо  огроменное, всё работает!!! слушай, дак это получается рекурсивная функция, правильно? и конечным результатом будет дерево??(Tree: SS)

Результатом будет число, ведь функция возвращает число. Параметр функции Tree: SS это дерево чьи ключи надо считать, а сам ключ - целое число. Для дерева вида
2
1 3
обход и резултат будет таким:
при вызове с вершиной 2 сумма 2 + результат рекурсии с вершинами 1 и 3
при вызове с вершиной 1 сумма 3 + результат рекурсии с вершинами из вершины 1. Так как таких вершин нет функция вернут 0
Для вершины 3 аналогично.
В итоге получаем сумму 2 + 1 + 0 + 0 + 3 + 0 + 0
Цитата(Монца @ 17 Dec 2008, 14:34)
Функция рекурсивная, но можно обойтись и без рекурсии.

Цитата(Palpalich @ 17 Dec 2008, 14:46)
как тогда организовать обход дерева, и что на выходе?

Можно, но в данном случае врядли. Обход дерева подразумевает возможность возврата в предыдущую вершину. То есть для примера выше из 2 мы должны просмотреть ветку начинающуюся с 1, вернуться, затем ветку с 3. Возможность возврата добавляется введением ссылку на вершину выше. Тип узла дерева должен выглядить как-то так:
type
PTree = ^TTree;
TTree = record
Info: Integer;
Left, Right: PTree;
Owner: PTree;
end;
Для примера выше для вершины 2 поле Owner = nil, для вершин 1 и 3 - ссылка на вершину 2

Ну а про палиндромы можно сделать например так:
Код
type
 PTree = ^TTree;
 TTree = record
   Info: string;
   Count: Integer;
   Left,
   Right: PTree;
 end;

{ Функция добавления слова в дерево }
{ Если делать эту функцию рекурсивной и не принять мер }
{ то каждый раз при ее вызове строка будет дублироваться }
{ в стеке и произойдет переполнение стека. Хотя те }
{ компиляторы что поумнее передавать будут не строку, а }
{ указатель на строку. И переполнения не будет. Как }
{ BP не помню:( Ниже три варианта реализации этой функции }

{ Вариант добавления слова в дерево без рекурсии }
procedure AddItem(var ATree: PTree; AInfo: string);
 function MakeItem(AInfo: string): PTree;
 var
   P: PTree;
 begin
   P := nil;
   New(P);
   if P <> nil then
   begin
     P^.Info := AInfo;
     P^.Left := nil;
     P^.Right := nil;
     P^.Count := 1;
     P^.Info := AInfo;
   end;
   MakeItem := P;
 end;
var
 P: PTree;
begin
 if ATree = nil then
 begin
   ATree := MakeItem(AInfo);
   Exit;
 end;
 P := ATree;
 while P <> nil do
 begin
   if AInfo = P^.Info then
   begin
     P^.Count := P^.Count + 1;
     Exit;
   end;
   if AInfo < P^.Info then
   begin
     if P^.Left = nil then
     begin
       P^.Left := MakeItem(AInfo);
       Exit;
     end else
     begin
       P := P^.Left;
       Continue;
     end;
   end;
   if AInfo > P^.Info then
   begin
     if P^.Right = nil then
     begin
       P^.Right := MakeItem(AInfo);
       Exit;
     end else
     begin
       P := P^.Right;
       Continue;
     end;
   end;
 end;
end;

{ Вариант добавления слова в дерево с рекурсией }
{ Внешняя функция является как оболочкой для }
{ реальной функции. Реальная же не передает строку, }
{ а пользуется строкой-параметром оболочки. Сколько }
{ бы раз не вызывалась реальная функция строка не }
{ передается и переполнения стека не будет }
procedure AddItem(var ATree: PTree; AInfo: string);
 procedure Add(var ATree: PTree);
 begin
   if ATree = nil then
   begin
     New(ATree);
     if ATree <> nil then
     begin
       ATree^.Info := AInfo;
       ATree^.Count := 1;
       ATree^.Left := nil;
       ATree^.Count := nil;        
     end;
     Exit;
   end;
   if ATree^.Info = AInfo then
   begin
     ATree^.Count := ATree^.Count + 1;
     Exit;
   end;
   if AInfo < ATree^.Info then
     Add(ATree^.Left)
   else
     Add(ATree^.Right);
 end;
begin
 Add(ATree);
end;

{ Вариант добавления слова в дерево с рекурсией }
{ Самый простой:) В списке параметров перед параметром }
{ AInfo ставим var. Тем самым мы гарантируем что }
{ передаваться будет не строка, а указатель на нее }
{ По крайней мере так задумано... }
procedure AddItem(var ATree: PTree; var AInfo: string);
begin
 if ATree = nil then
 begin
   New(ATree);
   if ATree <> nil then
   begin
     ATree^.Info := AInfo;
     ATree^.Count := 1;
     ATree^.Left := nil;
     ATree^.Count := nil;        
   end;
   Exit;
 end;
 if ATree^.Info = AInfo then
 begin
   ATree^.Count := ATree^.Count + 1;
   Exit;
 end;
 if AInfo < ATree^.Info then
   AddItem(ATree^.Left, AInfo)
 else
   AddItem(ATree^.Right, AInfo);
end;

{ Функция проверки является ли слово палиндромом }
{ Палиндром это ведь когда слово читается слева }
{ направо так же как справа налево? }
function IsPalindrom(AWord: string): Boolean;
var
 I: Integer;
begin
 for I := 1 to Length(AWord) div 2 do
   if AWord[i] <> AWord[Length(AWord) - I + 1] then
   begin
     IsPalindrom := False;
     Exit;
   end;
 IsPalindrom := True;
end;

{ Собственно подсчет палиндромов }
function CalcPalindromCount(ATree: Ptree): Integer;
var
 N: Integer;
begin
 if ATree = nil then
 begin
   CalcPalindromCount := 0;
   Exit;
 end;
 if IsPalindrom(ATree^.Info) then
   N := ATree^.Count { если копии палиндромов не считать то N := 1 }
 else
   N := 0;
 CalcPalindromCount := N + CalcPalindromCount(ATree^.Left)
                         + CalcPalindromCount(ATree^.Right);
end;

{ Очистка дерева }
procedure Clear(var ATree: PTree);
begin
 if ATree <> nil then
 begin
   Clear(ATree^.Left);
   Clear(ATree^.Right);
   Delete(ATree);
   ATree := nil;
 end;
end;


Смысл такой - в записи вводим поле для подсчета дублей слов. Это поле меняется при добавлении слова. Рекурсивный вызов функции с параметром строкой потенциально может вызвать ошибку переполнения стека, предложил три варианта решения этой проблемы. Перед началом работы переменную-указатель на дерево надо выставить в nil. После все работы с деревом вызвать Clear с аргументом переменной-указателем на дерево. Количество палиндромов выдает функция CalcPalindromCount:
X := CalcPalindromCount(Tree);
Чтение слов из файла сделай сам - я просто не очень хорошо помню как работают Read, ReadLn при работе с текстовым файла, а Паскаля у меня не стоит (все писал в блокноте)


Спасибо сказали:
Go to the top of the pageAdd Nick
 
+Quote Post
Gloin
сообщение 21 Dec 2008, 13:57
Сообщение #12

thick as a brick
Сообщений: 898
Спасибо сказали: 23 раза




Это где так людей калечат, заставляют на паскале деревья писать?
Go to the top of the pageAdd Nick
 
+Quote Post
Гость_Aнгeл_*
сообщение 21 Dec 2008, 14:03
Сообщение #13







А чем дерево на Паскале хуже деревьев на других языках? И почему калечат?
Go to the top of the pageAdd Nick
 
+Quote Post
Gloin
сообщение 21 Dec 2008, 22:44
Сообщение #14

thick as a brick
Сообщений: 898
Спасибо сказали: 23 раза




Собственно я привык считать паскаль языком для первокурсников, а там только вводят в суть программирования, деревья появляются на втором курсе уже на C/C++, у нас начали со второго, но это лирическое отступление к деревьям отношения не имеющее, мне только интересно: это Вас на первом курсе заставляют писать деревья, или же вы до 2-го паскаль учите, вряд ли тут просят выполнить задание не для ВУЗа.
Ну с технической стороны отличается конечно цель, мне она непонятна, неужели надо написать дерево хоть как-нибудь, это похвально, но зачем?
Go to the top of the pageAdd Nick
 
+Quote Post
gamecreator
сообщение 22 Dec 2008, 22:47
Сообщение #15

Яблочный произвол!
Сообщений: 11 080
Спасибо сказали: 3988 раз




Глоин, оказывается есть другой, нормальный паскаль. Вот про него Ангел и говорит
Go to the top of the pageAdd Nick
 
+Quote Post
gilex
сообщение 26 Dec 2008, 00:37
Сообщение #16

Newbie
Сообщений: 8
Спасибо сказали: 0 раз




ребят пожалуйста помогите решить задачу. очень срочно надо:
- Составить программу, определяющую количество вершин к - того уровня дерева.
говорят что легкая но нихера не получается... заранее благодарен.
Go to the top of the pageAdd Nick
 
+Quote Post
Gloin
сообщение 26 Dec 2008, 15:15
Сообщение #17

thick as a brick
Сообщений: 898
Спасибо сказали: 23 раза




Мне тут за некомпетентность минус влепили, хочется сатисфакции и срача.
Расскажите, пожалуйста, какую глупость я сказал.
Go to the top of the pageAdd Nick
 
+Quote Post
Монца
сообщение 26 Dec 2008, 16:00
Сообщение #18

good news, everyone!
Сообщений: 918
Спасибо сказали: 93 раза




за пост 12.
Написание деревьев на паскале не более сложная задача, чем написание деревьев на C
Что Ангел уже и сказал


--------------------
этъя опять
Go to the top of the pageAdd Nick
 
+Quote Post
Gloin
сообщение 26 Dec 2008, 16:55
Сообщение #19

thick as a brick
Сообщений: 898
Спасибо сказали: 23 раза




Не спорю, я с паскалем во втором семестре завязал, наоборот, говорю, что калечат, раз заставляют писать на этом языке, или я не понимаю задачи, о чем тоже написал.
И Ангел про сложность ничего не писал, удивился только тому что "калечат".
Go to the top of the pageAdd Nick
 
+Quote Post
Гость_Aнгeл_*
сообщение 26 Dec 2008, 17:39
Сообщение #20







На Паскале писать ничуть не сложнее. Наоборот, чётче, стабильнее, яснее. То есть ваш ответ сугубо индивидуален.
Go to the top of the pageAdd Nick
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 



Текстовая версия Сейчас: 1 July 2025 - 00:03
Copyright by Алексей Крючков
Strategy Gamez by GrayMage
Programming by Degtyarev Dmitry
  Яндекс.Метрика