Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Faltfromoss
0 / 0 / 0
Регистрация: 28.03.2014
Сообщений: 32
#1

Разобраться с рекурсивной функцией обхода бинарного дерева - C++

11.07.2014, 21:21. Просмотров 479. Ответов 4
Метки нет (Все метки)

Люди, помогите разобраться с рекурсивной функцией обхода бинарного дерева. Бьюсь головой об стену, не могу понять как она работает.

вот метод класса Tree для обхода дерева:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void Tree::Print(Subscriber * Node)
{
   if(Node != 0)
   {
      Print(Node->left);
            cout  << Node->FIO;
    (strlen (Node->FIO)<24)?cout<<"\t\t": cout<<"\t";
            cout<< Node->YearOfBirth<<"\t"
                << Node->Town<<"\t"
                << Node->Number<<"\t"
                << endl << endl;
      Print(Node->right);
   }
}
Из всего пройденного мною материала на данный момент - рекурсия - пока самое темное для меня место в ООП. Вышеприведенная функция написана не мной, я так полагаю она является неким шаблоном, в который я добавил свои значения которые нужно выводить, но я не могу вникнуть как она работает в принципе.
Мне нужно к простому выводу данных всего дерева добавить нумерацию списка, но как это сделать в рекурсивной функции не могу понять. Собственно непонимание работы самой рекурсии и приводит к тому, что не знаю как сделать нумерацию.
Если в цикле там все понятно:
C++
1
2
for (int i = 1; i<n; i++)
    cout<<i<<"...."<<endl;
то в рекурсии так не канает.
Решил поэкспериментировать, добавил в класс Tree счетчик Counter, который считает кол-во созданных объектов и попытался его использовать в таком контексте:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void Tree::Print(Subscriber * Node)
{
   if(Node != 0)
   {
      Counter--;
      Print(Node->left);
            cout  <<"   "<<++Counter<<". "<<Node->FIO;
    (strlen (Node->FIO)<24)?cout<<"\t\t": cout<<"\t";
            cout<< Node->YearOfBirth<<"\t"
                << Node->Town<<"\t"
                << Node->Number<<"\t"
                << endl << endl;
      Print(Node->right);
   }
}
Руководствовался домыслами, что пока Print () будет себя вызывать внутри (до момента Node == 0), то счетчик с n-го кол-ва объектов обнулится, а потом при возврате значений из стека в обратном порядке будет увеличиваться на единицу и будет, то, чего я добиваюсь, но при создании не скольких объектов и выводе их на экран все абоненты нумеруются одним и тем же номером:
"2. айлалэ....
2. айнана...."
В общем непонимание того, что ты пишешь или с чем работаешь - это печально
Вот, собственно просьба, просветите неуча как реализовать нумерацию и как вообще понять рекурсию :/
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
11.07.2014, 21:21
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Разобраться с рекурсивной функцией обхода бинарного дерева (C++):

Написать шаблон бинарного дерева с функцией распечатки дерева - C++
Не понимаю, что от меня хотят. Дано такое задание: Написать шаблон бинарного дерева с функцией распечатки дерева *(+(d,e),c) в виде...

Пронумеровать вершины бинарного дерева в соответствии с порядком концевого обхода - C++
Здравствуйте!!!! Помогите пожалуйста решить задачу. Построить бинарное дерево поиска для заданного множества целых чисел и занумеровать...

Разобраться с левосторонним обходом бинарного дерева - C++
Здравствуйте,помогите подробно разобраться как происходит левосторонний обход дерева на примере Код: void TREE::ObhodLeft (node **w) ...

Запись бинарного дерева в файл и восстановление из него этого дерева - C++
Задача такая: есть бинарное дерево. Каждый элемент дерева содержит 3 указателя - 1 указатель на структуру с данными, 2 и 3й указатель на...

Создание бинарного дерева из бинарного файла - C++
struct Bin { string name; string city; int players; int score; }; void ReadFromBin(Point*&amp; Tree) { Bin q;

Построение бинарного дерева на основе не бинарного - C++
В лабораторной работе есть такое задание: Создайте процедуру построения бинарного дерева на основе не бинарного. Объясните как вообще...

4
olper
24 / 24 / 11
Регистрация: 02.12.2013
Сообщений: 75
11.07.2014, 22:32 #2
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void Print(Subscriber * Node)
{
   if(Node != 0)
   {
      Print(Node->left);           
      Print(Node->right);
   }
 
    static int counter;
 
    cout<<counter;
    counter++;
 
    cout  << Node->FIO;
        (strlen (Node->FIO)<24)?cout<<"\t\t": cout<<"\t";
        cout<< Node->YearOfBirth<<"\t"
        << Node->Town<<"\t"
        << Node->Number<<"\t"
        << endl << endl;
    return;
}
Добавлено через 18 минут
чего-то проглядел
C++
1
2
3
4
5
6
7
if(Node != 0)
    {
        Print(Node->left);           
        Print(Node->right);
    }
    else
        return;
Добавлено через 29 минут
смысл в том,что у тебя есть обработчик(Print()) данных для любого "нода". Мы его и вызываем для корневого узла. А у корневого узла есть еще список потомков(идентичных по структуре(!) предку). Почему бы не вызвать для каждого потомка "обработчик данных для любого "нода"? И почему бы этот вызов не зашить в "обработчик для любого нода"? (Print() внутри Print()) А когда оказываешься в потомке, то оказывается и у него есть потомки почему бы не вызвать мега обработчик и для них, к тому же в нем (обработчике) уже зашит хитрый механизм обработки потомков... И так "гоняешься за хвостом", пока не дойдешь до критерия, когда надо вызывать return
C++
1
(if(Node != 0))
, а не Print(). Например потомок-то нулевой и у него не то что своих потомков нет, самого то его нет.

А до того как вызвать return, надо что-нибудь сделать с данными узла. Или что нибудь сделать до обхода потомков, но обязательно до return.

Главное в рекурсии что бы стек не лопнул... А то каждый вызов пихает свои параметры и все без return-а ...
0
Renji
2113 / 1472 / 346
Регистрация: 05.06.2014
Сообщений: 4,269
12.07.2014, 03:13 #3
void Tree::Print(Subscriber * Node)
Автор функции - идиот и не знает о this.
Мне нужно к простому выводу данных всего дерева добавить нумерацию списка, но как это сделать в рекурсивной функции не могу понять.
C++
1
2
3
4
5
6
7
8
9
10
int Subscriber::Print(int count=0)
{
    if(!this)
        return count;
    count=left->print(count);
    ++count;
    //сюда вставляется распечатка содержимого узла
    count=right->print(count);
    return count;
}
0
Faltfromoss
0 / 0 / 0
Регистрация: 28.03.2014
Сообщений: 32
12.07.2014, 07:16  [ТС] #4
Цитата Сообщение от Renji Посмотреть сообщение
void Tree::Print(Subscriber * Node)
Автор функции - идиот и не знает о this.
А при чем здесь this, если Print() - это метод класса Tree, а Subscriber * Node - это указатель на структуру с данными, которая является узлом этого дерева. И задача функции выводить не обязательно все дерево, а лишь его часть (ветку), начиная от указанного узла (переданного в функцию Print ()).

И, соответственно этот код:
C++
1
2
3
4
5
6
7
8
9
10
int Subscriber::Print(int count=0)
{
    if(!this)
        return count;
    count=left->print(count);
    ++count;
    //сюда вставляется распечатка содержимого узла
    count=right->print(count);
    return count;
}
немного некорректен в моем случае. В Subscribe нет никаких методов. В ней есть данные и указатели *Parent, *Left, *Right. Всё. А все методы реализованы в классе Tree, который в качестве свойства содержит указатель на корень дерева и от которого все эти методы и пляшут.

to -> olper

Я логику работы вроде бы как и понимаю, не могу понять как отрабатывает код в процессе исполнения. Попробовал отладчиком пошагово отследить, запутался в край :/
0
Renji
2113 / 1472 / 346
Регистрация: 05.06.2014
Сообщений: 4,269
12.07.2014, 11:57 #5
В Subscribe нет никаких методов.
Ну так пусть будут. Почему метод работает исключительно с данными Subscribe, но лежит в Tree? "Завистливые функции" - дурной тон.
Я логику работы вроде бы как и понимаю, не могу понять как отрабатывает код в процессе исполнения.
При вызове функции (без разницы Print или еще какой) - пихает локальные переменные Print в стек, туда же кидает адрес кода идущего следом за вызовом функции. После этого передает управление в начало вызванной функции.
При выполнении return - восстанавливает локальные переменные из стека, оттуда-же извлекает данные о том, куда должен передать управление return.
Итого, Node для каждого вызова Print свой собственный, с Node из предыдущих вызовов никак не связанный.

При слишком большой глубине вызова стек неожиданно кончается и программа падает. Но обычно под стек выделяется хотя бы мегабайт, поэтому переполнить его, это надо сильно постараться.
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
12.07.2014, 11:57
Привет! Вот еще темы с ответами:

Программа с рекурсивной функцией - C++
Друзья, помогите пожалуйста написать вот такую программу в Dev с++ Сколькими способами можно отобрать команду в составе 5 человек из 8...

программа с рекурсивной функцией - C++
написать программу на языке с++ решить задачу не используя операторы цикла написать программу с рекурсивной функцией вычисляющей

Написать программу с рекурсивной функцией - C++
Написать программу с рекурсивной функцией, вычисляющей: http://i065.***********/1212/09/1befc1906d10.png Добавлено через 14 часов 36...

Создать структуру с рекурсивной функцией - C++
Создать структуру в которой ввод и вывод информации будет осуществлятся с помощью рекурсивной функции


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru