0 / 0 / 0
Регистрация: 21.09.2017
Сообщений: 7
1

Бинарное дерево на C++

03.04.2019, 14:09. Показов 1173. Ответов 1
Метки нет (Все метки)

Доброго времени суток. Выношу себе мозг с реализацией этого дерева уже несколько дней. Прошу помощи.

Задание:

Реализовать BST (Binary Search Tree).

Дерево должно быть шаблонизировано - нужно продемонстрировать работу на хотя бы значениях int, double, string.

Нужно реализовать операции добавления элемента и поиска элемента.

Нужно реализовать автоматическую балансировку.
Для демонстрации ее работы в пустое дерево добавляем последовательно значения от 0 до 30 и выводим дерево в консоль/svg.
Глубина каждой ветки не должна быть больше 5.

Вывод дерева в консоль/svg

Свой код я прикрепляю к теме. Помогите, пожалуйста, добить это.

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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#include <iostream>
 
 
 
 
using namespace std;
 
 
class btree {
 
    struct node {
        int value;
        unsigned char height;
        node *left;
        node *right;
        node(int v) { value = v; left = right = 0; height = 1;}
    }; /// структура для представления узлов дерева
 
    node* rotateright(node* y){
        node* x = y->left;
        y->left = x->right;
        x->right = y;
        fixheight(y);
        fixheight(x);
        return x;
    } /// правый поворот вокруг y
 
    node* rotateleft(node* x){
        node* y = x->right;
        x->right = y->left;
        y->left = x;
        fixheight(x);
        fixheight(y);
        return y;
    } /// левый поворот вокруг x
 
    node* balance(node* leaf){
        fixheight(leaf);
        if( balancefactor(leaf)==2 )
        {
            if( balancefactor(leaf->right) < 0 )
                leaf->right = rotateright(leaf->right);
            return rotateleft(leaf);
        }
        if( balancefactor(leaf)==-2 )
        {
            if( balancefactor(leaf->left) > 0  )
                leaf->left = rotateleft(leaf->left);
            return rotateright(leaf);
        }
        return leaf;
    } /// Балансировка узла
 
    node *root;
 
    node* clear_tree(node *leaf){
        if (leaf != nullptr) {
            clear_tree(leaf->left);
            clear_tree(leaf->right);
            delete leaf;
        }
    } /// Очистка дерева
 
    node* insert(node* leaf, int x){
        if( !leaf ) return new node(x);
        if( x<leaf->value )
            leaf->left = insert(leaf->left,x);
        else
            leaf->right = insert(leaf->right,x);
        return balance(leaf);
    }/// Вставка значений
 
    node* search(int key, node *leaf){
        if (leaf != nullptr) {
            if (key == leaf->value) {
                cout << "There is" << " " << key << endl;
                return leaf;
 
            }
            if (key < leaf->value) {
                return search(key, leaf->left);
            } else {
                return search(key, leaf->right);
            }
        } else {
            cout << "There is no" << " " << key << endl;
            return nullptr;
        }
    } /// Поиск значений
 
    unsigned char height(node* leaf){
        return static_cast<unsigned char>(leaf ? leaf->height : 0);
    }
 
    int balancefactor(node* leaf){
        return height(leaf->right)-height(leaf->left);
    }
 
    void fixheight(node* leaf){
        unsigned char hl = height(leaf->left);
        unsigned char hr = height(leaf->right);
        leaf->height = static_cast<unsigned char>((hl > hr ? hl : hr) + 1);
    }
 
    void inorder_print(node* leaf) {
        if (leaf == nullptr)
            return;
        inorder_print(leaf->left);
        cout << leaf->value << " ";
        inorder_print(leaf->right);
 
    }
 
    void preorder_print(node* leaf) {
        if (leaf != nullptr) {
            cout << leaf->value << " ";
            inorder_print(leaf->left);
            inorder_print(leaf->right);
        }
        else
            cout << "There is no trees" << endl;
    }
 
public:
    btree(){
        root= nullptr;
    }
 
    ~btree(){
        root=clear_tree(root);
    }
 
    void insert(int key) {
        root=insert(root, key);
        }
 
    void preorder_print() {
        preorder_print(root);
        cout << "\n";
    }
 
    void inorder_print() {
        inorder_print(root);
        cout << endl;
    }
 
    void search(int key) {
        root = search(key, root);
    }
 
    int Height(node* leaf){
        int left, right;
 
        if(leaf == nullptr)
            return 0;
        left = Height(leaf->left);
        right = Height(leaf->right);
        if(left > right)
            return left+1;
        else
            return right+1;}
 
    void clear_tree() {
        clear_tree(root);
    }
 
};
 
 
int main(){
 
  btree t;
    for (int i = 0; i <= 30; ++i) {
        t.insert(i);
    }
  t.inorder_print();
  t.preorder_print();
 t.search(16);
 t.search(55);
 t.search(5);
 
 
 t.clear_tree();
 t.preorder_print();
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
03.04.2019, 14:09
Ответы с готовыми решениями:

Исходное бинарное дерево превратить в бинарное дерево поиска, при этом сохранив его структуру
Помогите, не могу понять!( Нужно исходное бинарное дерево превратить в бинарное дерево поиска, при...

Бинарное дерево. Удалить из дерева часть вершин так, чтобы оставшееся дерево стало пирамидой
Дано бинарное дерево. Удалить из дерева часть вершин так, чтобы оставшееся дерево стало пирамидой.

Бинарное дерево
Здравствуйте, нужно помощь в написании программы. Условие: Каждая вершина бинарного дерева...

Бинарное дерево
Только начал изучать тему &quot;деревья&quot;. Подскажите в чем ошибка)#include &lt;iostream&gt; using namespace...

1
33 / 22 / 12
Регистрация: 13.09.2017
Сообщений: 74
04.04.2019, 00:15 2
При реализации прямого обхода, у вас, вместо рекурсивного вызова этой же функции, вызывается функция симметричного обхода:

C++
1
2
3
4
5
6
7
8
9
10
void preorder_print(node* leaf) {
        if (leaf != nullptr) 
       {
            cout << leaf->value << " ";
            inorder_print(leaf->left); // имелось ввиду preorder_print ?
            inorder_print(leaf->right); // имелось ввиду preorder_print ?
        }
        else
            cout << "There is no trees" << endl;
    }
Еще момент:
C++
1
2
3
4
5
6
7
8
9
void preorder_print(node* leaf) {
        if (leaf != nullptr) {
            cout << leaf->value << " ";
            inorder_print(leaf->left);
            inorder_print(leaf->right);
        }
        else
            cout << "There is no trees" << endl;
    }
Непонятно, зачем выводить сообщение "*There is no trees". Дело в том, что каждый раз когда функция доходит до конца ветки, leaf становится nullptr. Однако это не означает то, что работа функции preorder_print окончательно завершиться. Это будет означать, что она напечатает вам эту ерунду, потом из стека вызовов будет использована следующая функция, которая дальше пойдет по другой ветке, и так будет повторяться до тех пор, пока не будут пройдены все ветки. Уберите этот блок кода вообще, и все нормально будет выводиться)

C++
1
2
else
            cout << "There is no trees" << endl;
Ну или найдите ему адекватные альтернативы.

Проблема с поиском уже не так проста) Дело в том, что указателю root, после выполнения функции поиска, каждый раз присваивается адрес искомого узла. Когда вы вызовете функцию поиска для ключа 55, этого ключа найдено не будет, и указателю на корень дерева будет присвоен nullptr.

Затем вы попытаетесь найти элемент с ключом 5, и получите следующее:
C++
1
2
3
4
void search(int key)
{
        root = search(key, root); // но здесь уже root = nullptr
}
Так как root = nullptr, то при заходе в функцию поиска по дереву, вас сразу же из него выкинет:

C++
1
2
3
4
5
6
7
8
9
if (leaf != nullptr)
{
... // тут должен был быть поиск
}
else
{
      cout << "There is no" << " " << key << endl;
      return nullptr; // но мы попали сюда
}
Если вам необходимо вернуть указатель на узел, вы не должны возвращать его в указатель корня дерева. Введите для этого отдельный указатель:

C++
1
2
3
4
5
node* searchElement;
void search(int key)
{
    searchElement = search(key, root); // ok: получили указатель на искомый узел, но при этом корень дерева остался неизменным
}
Так все будет работать)
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
04.04.2019, 00:15
Помогаю со студенческими работами здесь

Бинарное дерево
Доброго времени суток. Ребят, я не спец, требуется решить такую задачу: Написать нерекурсивную...

Бинарное дерево
Здравствуйте дорогие форумчане. Помогите, пожалуйста, реализовать бинарное дерево поиска, а так же...

C++, Бинарное дерево
Привет. Можете помочь с заданием. Прочитал кучу теорию по бинарным деревьям. Сел делать вообще не...

Бинарное дерево
Здавствуйте, не работает удаление элемента в бинарном девере поиска. Задание: Задание: Описать...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru