Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.60/124: Рейтинг темы: голосов - 124, средняя оценка - 4.60
 Аватар для _Eldar_
45 / 30 / 11
Регистрация: 31.10.2009
Сообщений: 200

"Рекурсивная функция" (Обход бинарного дерева)

08.03.2010, 10:40. Показов 26343. Ответов 31
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Привет всем, встретился с такой рекурсивной ф-ей, которая обходит бинарное дерево и выводит его на экран. Не могу понять как она работает
C++
1
2
3
4
5
6
7
8
void print_tree(Node *p, int level){
    if(p){
        print_tree(p->left, level + 1);     // вывод левого поддерева
        for(int i = 0; i < level; i++) cout << "   ";
        cout << p->d << endl;               // вывод корня поддерева
        print_tree(p->right, level + 1);    // вывод левого поддерева
    }
}
первый параметр это указатель на элемент дерева, а второй - уровень на катором находиться узел.
Объясните пожалуйста принцип работы такой функции. Заранее благодарен )

Добавлено через 1 минуту
вот сама структура:
C++
1
2
3
4
5
struct Node{
    int d;
    Node *left;
    Node *right;
};
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
08.03.2010, 10:40
Ответы с готовыми решениями:

Обход бинарного дерева
Прошу Вас, помогите школьнику, незнающему деревья, завтра срочно надо сдать работу, я никак не могу реализовать... 1. В заданном...

Обход бинарного дерева С++
Нужна помощь! Просмотрел много источников, но так и не нашёл своего ответа...Суть задачи состоит в том что, мне нужно при обходе...

Обход Бинарного дерева
Задача: написать функцию, помощью которой можно получить n-тый элемент бинарного дерева по возрастанию. в узлах хранятся целые числа. ...

31
1261 / 799 / 108
Регистрация: 16.09.2009
Сообщений: 2,010
08.03.2010, 10:41
Пойми сначала рекурсию, а потом и с функцией разберешься.
1
 Аватар для _Eldar_
45 / 30 / 11
Регистрация: 31.10.2009
Сообщений: 200
09.03.2010, 12:46  [ТС]
Рекурсивная функция, это функция которая вызыват саму себя

Добавлено через 3 часа 47 минут
Люди, добрые, помjгите разобраться

Добавлено через 22 часа 10 минут
Вот весь код
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <iostream>
#include <windows.h>
#include <conio.h>
 
using namespace std;
 
struct Node{
    int d;
    Node *left;
    Node *right;
};
Node *first(int d);
Node *search_insert(Node *root, int d);
void print_tree(Node *root, int l);
//----------------------------------
int main(){
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
 
    int b[] = {10, 25, 20, 6, 21, 8, 1, 30};
    Node *root = first(b[0]);
    for(int i = 1; i < 8; i++) search_insert(root, b[i]);
    cout << "+" << root->d << "\n\n"; 
    print_tree(root, 0);
    _getch();
    return 0;
}
//----------------------------------
Node *first(int d){
    Node *pv = new Node; 
    pv->d = d;
    pv->left = 0;
    pv->right = 0;
    return pv;
}
//-----------------------------------
Node *search_insert(Node *root, int d){
    Node *pv = root, *prev;
    bool found = false;
    while(pv && !found){
        prev = pv;
        if( d == pv->d) found = true;
        else if(d < pv->d) pv = pv->left;
        else pv = pv->right;
    }
    if(found) return pv;
 
    Node *pnew = new Node;
    pnew->d = d;
    pnew->left = 0;
    pnew->right = 0;
    if(d < prev->d)
        prev->left = pnew;
    else
        prev->right = pnew;
 
    return pnew;
}
//----------------------------------------
void print_tree(Node *p, int level){
    if(p){
        print_tree(p->left, level + 1);     // вывод левого поддерева
        for(int i = 0; i < level; i++) cout << "   ";
        cout << p->d << endl;               // вывод корня поддерева
        print_tree(p->right, level + 1);    // вывод левого поддерева
    }
}
вот результат программы
1
6
8
10
20
25 21
30

Вот как я понимаю как работает функция print_tree:
вызовы:
1) print_tree(10, 0); (лев. часть)
2) print_tree(6, 1); (лев. часть)
3)print_tree (1, 2); (лев. часть)
4)print_tree(нет левого поддерева, 3) (лев. часть)
вывод "1"
5) print_tree (нет правого поддерева, 3); (лев. часть)

все дальше не понятно как выводиться остальная часть поддерева

Добавлено через 5 минут
небольшая поправка:
5) print_tree (нет правого поддерева, 3); (прав. часть)
0
Заблокирован
09.03.2010, 13:01
Тоже интересует данный вопрос присоединяюсь к автору темы
0
Фрилансер
 Аватар для Black Fregat
3709 / 2083 / 567
Регистрация: 31.05.2009
Сообщений: 6,683
09.03.2010, 13:05
Уважаемый, в чем именно надо разобраться? Весь смысл рекурсии ясен из самой программы - сначала напечатаем левое поддерево, потом корень, потом правое поддерево. А если неясен сам процесс - неужели трудн натыкать печатей и получить протокол:
нажмите, чтобы увидеть
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
8a34f4, Уровень: 0 - Вход
8a34f4, Уровень: 0 - Печать левого поддерева
8a3524, Уровень: 1 - Вход
8a3524, Уровень: 1 - Печать левого поддерева
8a3554, Уровень: 2 - Вход
8a3554, Уровень: 2 - Печать левого поддерева
0, Уровень: 3 - Вход
0, Уровень: 3- Пусто, конец рекурсии
0, Уровень: 3- Выход
8a3554, Уровень: 2 - Печать корня
      1
8a3554, Уровень: 2 - Печать правого поддерева
0, Уровень: 3 - Вход
0, Уровень: 3- Пусто, конец рекурсии
0, Уровень: 3- Выход
8a3554, Уровень: 2- Выход
8a3524, Уровень: 1 - Печать корня
   6
8a3524, Уровень: 1 - Печать правого поддерева
8a3544, Уровень: 2 - Вход
8a3544, Уровень: 2 - Печать левого поддерева
0, Уровень: 3 - Вход
0, Уровень: 3- Пусто, конец рекурсии
0, Уровень: 3- Выход
8a3544, Уровень: 2 - Печать корня
      8
8a3544, Уровень: 2 - Печать правого поддерева
0, Уровень: 3 - Вход
0, Уровень: 3- Пусто, конец рекурсии
0, Уровень: 3- Выход
8a3544, Уровень: 2- Выход
8a3524, Уровень: 1- Выход
8a34f4, Уровень: 0 - Печать корня
10
8a34f4, Уровень: 0 - Печать правого поддерева
8a3504, Уровень: 1 - Вход
8a3504, Уровень: 1 - Печать левого поддерева
8a3514, Уровень: 2 - Вход
8a3514, Уровень: 2 - Печать левого поддерева
0, Уровень: 3 - Вход
0, Уровень: 3- Пусто, конец рекурсии
0, Уровень: 3- Выход
8a3514, Уровень: 2 - Печать корня
      20
8a3514, Уровень: 2 - Печать правого поддерева
8a3534, Уровень: 3 - Вход
8a3534, Уровень: 3 - Печать левого поддерева
0, Уровень: 4 - Вход
0, Уровень: 4- Пусто, конец рекурсии
0, Уровень: 4- Выход
8a3534, Уровень: 3 - Печать корня
         21
8a3534, Уровень: 3 - Печать правого поддерева
0, Уровень: 4 - Вход
0, Уровень: 4- Пусто, конец рекурсии
0, Уровень: 4- Выход
8a3534, Уровень: 3- Выход
8a3514, Уровень: 2- Выход
8a3504, Уровень: 1 - Печать корня
   25
8a3504, Уровень: 1 - Печать правого поддерева
8a3564, Уровень: 2 - Вход
8a3564, Уровень: 2 - Печать левого поддерева
0, Уровень: 3 - Вход
0, Уровень: 3- Пусто, конец рекурсии
0, Уровень: 3- Выход
8a3564, Уровень: 2 - Печать корня
      30
8a3564, Уровень: 2 - Печать правого поддерева
0, Уровень: 3 - Вход
0, Уровень: 3- Пусто, конец рекурсии
0, Уровень: 3- Выход
8a3564, Уровень: 2- Выход
8a3504, Уровень: 1- Выход
8a34f4, Уровень: 0- Выход
2
 Аватар для kuroiryuu
328 / 312 / 68
Регистрация: 05.11.2009
Сообщений: 712
09.03.2010, 13:12
а лучше преобразуйте функцию print_tree
C++
1
2
3
4
5
6
7
8
9
10
void print_tree(Node *p, int level)
{
        if(p){
                for(int i = 0; i < level; i++) cout << "--";
                cout << "Level: " << level << "; Element = "p->d << endl; // вывод корня поддерева
 
                print_tree(p->left, level + 1);         // вывод левого поддерева
                print_tree(p->right, level + 1);        // вывод левого поддерева
        }
}
1
 Аватар для _Eldar_
45 / 30 / 11
Регистрация: 31.10.2009
Сообщений: 200
09.03.2010, 13:19  [ТС]
для чего вообще использовать рекурсию мне не понятно , помоему кроме запутанного, но короткого кода никаких преимуществ
0
 Аватар для kuroiryuu
328 / 312 / 68
Регистрация: 05.11.2009
Сообщений: 712
09.03.2010, 13:31
Цитата Сообщение от _Eldar_ Посмотреть сообщение
для чего вообще использовать рекурсию мне не понятно , помоему кроме запутанного, но короткого кода никаких преимуществ
а вы представьте, что вам необходимо вычислить что-нибудь в зависимости от разных условий, но при этом входные данные следующего расчёта это результат предыдущего, а принцип самого расчёта общий, и циклами это реализовать не получается...
1
 Аватар для _Eldar_
45 / 30 / 11
Регистрация: 31.10.2009
Сообщений: 200
09.03.2010, 13:34  [ТС]
kuroiryuu, можно конкретную задачку? помоему для любого рекурсивного алгоритма можно создать его нерекурсивный аналог
0
Фрилансер
 Аватар для Black Fregat
3709 / 2083 / 567
Регистрация: 31.05.2009
Сообщений: 6,683
09.03.2010, 13:43
Цитата Сообщение от _Eldar_ Посмотреть сообщение
по-моему для любого рекурсивного алгоритма можно создать его нерекурсивный аналог
Скажите, неужели рекурсию в том же обходе дерева настолько сложно понять, что Вы готовы программировать обход этого же дерева без рекурсии? Вам понадобится на каждом шаге помнить, вверх по дереву мы идем или вниз, хранить путь от вершины дерева.. На мой взгляд, сложность программы возрастет на порядок.
1
 Аватар для _Eldar_
45 / 30 / 11
Регистрация: 31.10.2009
Сообщений: 200
09.03.2010, 14:02  [ТС]
не знаю, может быть с опытом будет проще понимать рекурсию, у нее все равно есть главный недосток - все параметры функции при каждом вызове копируются в стек, к-ый может переполниться
0
 Аватар для kuroiryuu
328 / 312 / 68
Регистрация: 05.11.2009
Сообщений: 712
09.03.2010, 14:14
Цитата Сообщение от _Eldar_ Посмотреть сообщение
kuroiryuu, можно конкретную задачку? помоему для любого рекурсивного алгоритма можно создать его нерекурсивный аналог
например, попробуйте вывести на экран все папки, которые есть на заданном диске, включая вложенные (файлы не обязательно), но без использования рекурсии
а потом тоже самое, но с рекурсией
1
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
 Аватар для easybudda
12843 / 7592 / 1766
Регистрация: 25.07.2009
Сообщений: 13,973
09.03.2010, 18:20
_Eldar_, обошлось без рекурсии, но вроде и дерево создаётся, и печатается... Короче вот:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include <iostream>
#include <cstdlib>
 
class Node {
public:
    Node() : _left(NULL), _right(NULL), _val(0) {}
    Node(int v) : _left(NULL), _right(NULL), _val(v) {}
    Node(int v, Node *n) {
        if ( v < n->val() ){
            while ( n->val() > v && n->left() != NULL )
                n = n->left();       
        }
        else if ( v > n->val() ){
            while ( n->val() < v && n->right() != NULL)
                n = n->right();
        }
        if ( v == n->val() ){
            std::cerr << "Doubling value (" << v << ")!" << std::endl;
            exit(1);
        }
        else if ( v < n->val() ){
            _right = n;
            _left = n->left();
            n->left(this);
            if ( _left )
                _left->right(this);
        }
        else {
            _left = n;
            _right = n->right();
            n->right(this);
            if ( _right )
                _right->left(this);
        }
        _val = v;
    }
    int val() const { return _val; }
    void val(int v) { _val = v; }
    Node *left() const { return _left; }
    void left(Node *n) { _left = n; }
    Node *right() const { return _right; }
    void right(Node *n) { _right = n; }
    Node *first() const {
        const Node *f = this;
        while ( f->left() != NULL )
            f = f->left();
        return (Node*)f;
    }
    Node *last() const {
        const Node *l = this;
        while ( l->right() != NULL )
            l = l->right();
        return (Node*)l;
    }
private:
    Node *_left;
    Node *_right;
    int _val;
};
 
void printTree(Node *n){
    n = n->first();
    while ( n ){
        std::cout << n->val() << ' ';
        n = n->right();
    }
}
 
void killTree(Node *n){
    Node *t;
    n = n->first();
    while ( n ){
        t = n->right();
        delete n;
        n = t;
    }
}
 
int main(){
    const int values = 10;
    int arr[values] = { 2, 1, 3, 6, 4, 9, 7, 5, 0, 8 }, i;
    Node *n = new Node(arr[0]);
    for ( i = 1; i < values; ++i ){
        n = new Node(arr[i], n);
    }
 
    printTree(n);
    killTree(n);
    std::cout << std::endl;
    return 0;
}
1
 Аватар для _Eldar_
45 / 30 / 11
Регистрация: 31.10.2009
Сообщений: 200
10.03.2010, 00:57  [ТС]
Спасибо всем отозвавшимся))
kuroiryuu, я пока такую задачу точно не решу, я только консольные приложения пишу, да я понимаю что запись будет короче с рекурсией, с примером сталкивался (быстрая сортировка массива), я имел в виду что любой рекурсивный алгоритм можно преписать нерекурсивным.
easybudda, спасибо, но до изучения классов я еще не дошел
0
Фрилансер
 Аватар для Black Fregat
3709 / 2083 / 567
Регистрация: 31.05.2009
Сообщений: 6,683
10.03.2010, 08:21
На мой взгляд, Вы делаете определенную подмену понятий. Вы всё время делаете упор на то, что рекурсивный код получается более короткий. Но бывает такая краткость, которая только запутывает. На мой взгляд, тут наоборот, рекурсивный код получается более логичный и понятный.
1
 Аватар для kuroiryuu
328 / 312 / 68
Регистрация: 05.11.2009
Сообщений: 712
10.03.2010, 09:37
Цитата Сообщение от Black Fregat Посмотреть сообщение
рекурсивный код получается более логичный и понятный.
согласен с этим, не надо придумывать велосипед, для решения задач.
там где уместны циклы используй циклы, а где рекурсии - рекурсии.
0
paladin
 Аватар для Yurii_74
286 / 187 / 7
Регистрация: 25.02.2009
Сообщений: 589
10.03.2010, 10:03
Пример, когда рекурсия не подойдет: нарисуйте какой-нибудь фрактал с глубиной в 10^n. Для определенных n "Stack overflow error" обеспечен.
1
1261 / 799 / 108
Регистрация: 16.09.2009
Сообщений: 2,010
10.03.2010, 11:16
Данный алгоритм, можно организовать и без рекурсии с помощью дополнительной динамической структуры допустим: стек: так как стек позволяет запоминать направления движения по графу.
С рекурсией присутствует стек: так сказать аппаратный(на уровне компилятора),
он то и позволят запоминать шаги, для дальнейшего продвижения по графу.
0
Фрилансер
 Аватар для Black Fregat
3709 / 2083 / 567
Регистрация: 31.05.2009
Сообщений: 6,683
10.03.2010, 11:25
Цитата Сообщение от Yurii_74 Посмотреть сообщение
Пример, когда рекурсия не подойдет: нарисуйте какой-нибудь фрактал с глубиной в 10^n. Для определенных n "Stack overflow error" обеспечен.
Извините, но не могу согласиться.

Во-первых, Вы путаете отвлечённое логическое понятие рекурсии и вполне определенную форму реализации этой рекурсии. Соответственно, рекурсию как форму записи алгоритма и рекурсию как способ выполнения. Вполне можно представить себе компилятор, убирающий лишние стековые итерации. Вы, вероятно, слышали термин "хвостовая рекурсия", возникший как раз вокруг этой проблематики?

Во-вторых, что нам мешает сделать стек поглубже, а стековых переменных - поменьше? Пару гигов на стек - и золотой ключик у нас в кармане. А когда вычисления подходят к границе ресурсов, тут уж поневоле приходится усложнять алгоритмы. Это не только с рекурсией, простая сортировка ведет себя не лучше при возрастании объемов сортируемой информации.
0
1261 / 799 / 108
Регистрация: 16.09.2009
Сообщений: 2,010
10.03.2010, 11:51
Вывод без рекурсии общий принцип: на основе ДСД: стека.
C++
1
2
3
4
5
6
7
8
Stack * top = NULL;
push(&top,r);
while(top){
r = pop(&top);
cout<<r->d;
if(r->right)push(&top,r->right);
if(r->left)push(&top,r->legt);
}
2
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
10.03.2010, 11:51
Помогаю со студенческими работами здесь

Обход бинарного дерева
может есть у кого такой пример или похожий??или часть какая нибудь?

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

НЕрекурсивный обход бинарного дерева
уважаемые программисты! нужно написать алгоритм обхода бинарного дерева без использования рекурсии, а с помощью стека. Проверить на...

Как осуществлять обход бинарного дерева?
Хочу создать клас бинарное дерево, но не знаю чем это дерево я буду проходить, как двигатса от одного узла к дргому.(без создания...

Обход бинарного дерева без рекурсии
нужно написать алгоритм обхода бинарного дерева без использования рекурсии, а с помощью стека. Проверить на дереве int, но в самом коде...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Логарифм записывается как: (x-2)log(x^2+2) - означает логарифм (x^2+2) по основанию (x-2). Унарный минус обозначается как ! */ #include <iostream> #include <stack> #include <cctype>. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru