Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.94/18: Рейтинг темы: голосов - 18, средняя оценка - 4.94
2664 / 2239 / 240
Регистрация: 03.07.2012
Сообщений: 8,141
Записей в блоге: 1
1

Простое бинарное дерево

04.11.2015, 12:55. Показов 3590. Ответов 5
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Простое бинарное дерево с int ключом, добавлением, удалением по ключу и выводом на консоль.
Можно использовать при начальном изучении и как основу для расширения.
Вроде как должно работать и в Си (при изменении заголовочных файлов),
поэтому использую printf и не использую ссылок в параметрах (хотя с ними проще).


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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
#include <iostream>
using namespace std; 
 
struct Node //узел дерева
{
   int x;      // ключ, по которому вставляем
   Node *l,*r; // левое и правое поддерево
};
 
// уровень дерева, с 1
int get_Level(Node *Tree) 
{
    int ll,lr;
    if (Tree==NULL) return 0;
    ll=get_Level(Tree->l);
    lr=get_Level(Tree->r);
    return 1+(ll>lr?ll:lr);
 
}
 
// получить подузел с номером строке  row и колонкой col
// переданный узел имеет row=0, col=0 
// если подузла нет, возвращает nil
int get_Node(Node *Tree,int row,int col,int nil) 
{
    Node *p=Tree;
    int i,c;
    c=1;
    // начальная колонка правой части
    for (i=row;--i>0;c<<=1);
    while (row && c) 
    {
        if (col<c) {
            // левая
            p=p->l;
        }
        else {
            // правая
            col=col-c;
            p=p->r;
        }
        if (p==NULL) return nil;
        c>>=1; --row;
    }
    return p->x;
}
// выводит дерево, но нужно конкретно затачивать под данные
// сейчас - вывод 0-9 и символов
void show_Tree(Node *Tree) 
{
    int lvl=get_Level(Tree);
    int z,zz;
    zz=-1; // ключ несуществующего узла
    int c=1;
    int s=1; // сколько пробелов надо вывести перед данными
    for (z=lvl;--z>=0;s<<=1);
    printf("\n");
    for (int i=0;i<lvl;++i) {
        for (int j=0;j<c;++j) {
            int s0=j==0?s/2:s; // первая колонка укороченная
            for (int k=0;++k<s0;) printf(" ");
            z=get_Node(Tree,i,j,zz);
            if (z==zz) printf(" ");
            else if (z>9) printf("%c",z); else printf("%d",z);
        }
        printf("\n");
        s>>=1;
        c<<=1;
    }
}
 
// выводит строку ключей по возрастанию
void show_Keys(Node *Tree) 
{
    if (Tree!=NULL)
    {
       show_Keys(Tree->l); 
       printf(" %d",Tree->x); 
       show_Keys(Tree->r); 
    }
}
 
// добавляет узел в левую  ветку, если ключ < ключа в Tree
// добавляет узел в правую ветку, если ключ > ключа в Tree
// если ключи равны, то узел не добавляется (или добавлется в правую, при небольшом изменении функции)
// В С++ Node **Tree можно заменить на Node *&Tree, а (*Tree) заменить на Tree 
void add_Node(int x,Node **Tree) 
{
    if ((*Tree)==NULL)  
    {
        (*Tree)=new Node; 
        (*Tree)->x=x; 
        (*Tree)->l=(*Tree)->r=NULL; 
        return;
    }
 
    if (x<(*Tree)->x)   
    {
        if ((*Tree)->l) add_Node(x,&(*Tree)->l); // в С++ add_Node(x,Tree->l)
        else 
        {
            (*Tree)->l=new Node;  
            (*Tree)->l->l=(*Tree)->l->r=NULL; 
            (*Tree)->l->x=x; 
        }
    }
   // если заменить > на >=, то можно вставлять одинаковые ключи в правую ветку             
    if (x>(*Tree)->x)  
    {
        if ((*Tree)->r!=NULL) add_Node(x,&(*Tree)->r); // в С++ add_Node(x,Tree->r)
        else 
        {
            (*Tree)->r=new Node; 
            (*Tree)->r->l=(*Tree)->r->r=NULL; 
            (*Tree)->r->x=x;  
        }
    }
}
 
 
// поиск узла по ключу, начиная с узла Tree
Node *find_Node(int x, Node *Tree) 
{
    if (Tree==NULL) return NULL;
    if (x<Tree->x)  return find_Node(x,Tree->l); 
    if (x>Tree->x)  return find_Node(x,Tree->r); 
    return Tree;
}
 
// удаляет подузел, на который указывает Tree 
// В С++ Node **Tree можно заменить на Node *&Tree, а (*Tree) заменить на Tree 
void delete_p(Node **Tree) {
    Node *s;
    Node *p=(*Tree);
    if (p->r==NULL) {
        // только левая ветка
        (*Tree)=p->l;
    }
    else if (p->l==NULL) 
        // только правая ветка
        (*Tree)=p->r;
    else {
        // обе ветки есть, ищем минимум в правой
        if (p->r->l==NULL) {
            // самый первый в ветке - минимальный, меняем 2 ссыылки
            *Tree=p->r;    // минимальный заменяет p в родительском
            (*Tree)->l=p->l; // левый  p => левый минимального
        }
        else {
            for (s=p->r; s->l->l;s=s->l);
            // в s->l минимальный элемент ветки, меняем ссылки
            *Tree=s->l;    // минимальный заменяет p в родительском
            (*Tree)->l=p->l; // левый  p => левый минимального
            s->l=(*Tree)->r; // правый минимального => левый его родителя (где была ссылка на минимальный)
            (*Tree)->r=p->r; // правый p => правый минимального 
        }
    }
    delete p;
    return;
}
 
// удаляет подузел  с ключом (если ключ в самом узле, ничего не делает)
void delete_Node(int x,Node *Tree) 
{
    Node *p,*s;
    if (x<Tree->x)   
    {   p=Tree->l;
        if (p==NULL) return ; 
        if (x!=p->x) return delete_Node(x, p); 
        // удаляем левый подузел
        delete_p(&Tree->l);
    }
    if (x>=Tree->x)   
    {   p=Tree->r;
        if (p==NULL) return ; 
        if (x!=p->x) return delete_Node(x, p); 
        // удаляем правый подузел
        delete_p(&Tree->r);
    }
}
// заполняет дерево начальными значенями
Node* init_Tree() {
    Node *pT=NULL;
    Node **T=&pT;
 // 31 случайный
 //add_Node(16,T); for (int i=0;i<31;++i) add_Node(rand()%30+1,T);
 // 16 элементов
 // add_Node('Z',T); // узел верхнего уровня с максимальным ключом
 
    add_Node(9,T);  add_Node(4,T);add_Node(2,T); add_Node(1,T); add_Node(3,T); add_Node(9,T); add_Node(7,T); add_Node(5,T); add_Node(6,T); add_Node(8,T); 
    add_Node('D',T); add_Node('B',T); add_Node('A',T); add_Node('C',T); add_Node('F',T); add_Node('E',T); add_Node('G',T); add_Node(9,T);
    return pT;
}
 
Node* init2_Tree() {
    Node *pT=NULL;
    Node **T=&pT;
    add_Node(2,T); add_Node(1,T); add_Node(6,T); add_Node(4,T); add_Node(5,T); add_Node(3,T); add_Node(8,T); add_Node(7,T); add_Node(9,T); 
    add_Node(4,T); add_Node(2,T); add_Node(1,T); add_Node(3,T); add_Node(6,T); add_Node(5,T); add_Node(7,T);
    return pT;
}
 
int main()
{
    Node *T=NULL;  
    T=init_Tree();
    printf("Keys="); show_Keys(T); 
    printf("\nLevel=%d",get_Level(T));
    show_Tree(find_Node(4,T));
    delete_Node(9,T);   show_Tree(T);   
    delete_Node(4,T);   show_Tree(T);
    delete_Node(7,T);   show_Tree(T);
    delete_Node(5,T);   show_Tree(T);
    delete_Node(2,T);   show_Tree(T);
    delete_Node(6,T);   show_Tree(T);   
    delete_Node('A',T); show_Tree(T);
    delete_Node('B',T); show_Tree(T);
    delete_Node('C',T); show_Tree(T);
    delete_Node('D',T); show_Tree(T);
    delete_Node('E',T); show_Tree(T);
    return 0;
}
2
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
04.11.2015, 12:55
Ответы с готовыми решениями:

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

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

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

Бинарное дерево
Помогите пожалуйста с программой. Нужно сделать обход, слева и справа(функции get_left и...

5
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,882
04.11.2015, 13:30 2
Нет. В Си нужно переделать больше чем заголовочные файлы. Там и стиль комментариев и явное указание struct и объявление переменных вне цикла надо и еще malloc, а не new....

Короче если кто-то изучает С, а не С++, этот код ему может мозг поломать.

А для новичков С++ выражения да еще и без комментариев не совсем хорошая идея.
return 1+(ll>lr?ll:lr);
c<<=1

Плюс к этому, удаления скопом не хватает. Т.е. не вбивается в голову, что может иметь место утечка.
0
2664 / 2239 / 240
Регистрация: 03.07.2012
Сообщений: 8,141
Записей в блоге: 1
04.11.2015, 13:53  [ТС] 3
Я не знаю - современные компиляторы требуют явного указания struct? Если "да", то можно typedef или define использовать.
C++
1
2
return 1+(ll>lr?ll:lr); // 1+MAX(lt,lr)
 c<<=1; // сдвиг влево на 1 бит, он же умножение на 2
Что тут сложного?
0
4817 / 2278 / 287
Регистрация: 01.03.2013
Сообщений: 5,947
Записей в блоге: 28
04.11.2015, 14:02 4
Все по классике: вот - мужик, а вот - дерево Но подозреваю что должны быть стандартные либы с подобным.
0
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,882
04.11.2015, 14:14 5

Не по теме:

Цитата Сообщение от zer0mail Посмотреть сообщение
Что тут сложного?
для меня ничего. но вангую, что именно это (когда нет комментариев) тупо в ступор может вводить. Ступор, конечно, будет проходить, может и сразу, а может со временем. У всех по разному.



Добавлено через 55 секунд
Цитата Сообщение от zer0mail Посмотреть сообщение
Я не знаю - современные компиляторы требуют явного указания struct?
Я всего-лишь посмотрел в С

Добавлено через 4 минуты
Это раздел С++, так что все пучком. Все же работает
0
2664 / 2239 / 240
Регистрация: 03.07.2012
Сообщений: 8,141
Записей в блоге: 1
04.11.2015, 14:16  [ТС] 6
Цитата Сообщение от daslex Посмотреть сообщение
что именно это (когда нет комментариев) тупо в ступор может вводить. С
Если это будет вводить в ступор, то изучать деревья рановато Я писал не для тупого копирования, а чтобы думали, добавляли, меняли, изучали. Печать дерева и удаление узла - не самые тривиальные задачи для новичков.
Вот еще процедура:

C++
1
2
3
4
5
6
7
// удаление подузлов узла Tree 
void delete_Tree(Node *Tree) 
{
    if(Tree==NULL) return;
    if (Tree->l) {delete_Tree (Tree->l); delete Tree->l; Tree->l=NULL;}
    if (Tree->r) {delete_Tree (Tree->r); delete Tree->r; Tree->r=NULL;}
}
1
04.11.2015, 14:16
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
04.11.2015, 14:16
Помогаю со студенческими работами здесь

Бинарное дерево
Мой код: Patient.h // // Created by User on 26.04.2016. // #ifndef LABA_10_PATIENT_H...

Бинарное дерево
Объясните пжлст почему не работает программа...при вводе файла пишет -842150451 /*Дан адрес P1...

Бинарное дерево
Добрые вечер, есть бинарное дерево struct node { int info; node *l, *r; }; node * tree =...

Бинарное дерево
Добрые вечер, есть дерево struct node { int info; node *l, *r; }; node * tree = NULL; ...


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

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru