Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.66/47: Рейтинг темы: голосов - 47, средняя оценка - 4.66
11 / 11 / 3
Регистрация: 06.08.2011
Сообщений: 208
1

Сформировать бинарное дерево поиска и определить максимальную глубину дерева

18.01.2018, 06:39. Показов 9521. Ответов 30
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день всем.
По задаче необходимо сформировать бинарное дерево поиска и определить максимальную глубину дерева.
Перед завершением программы освободить память.
Оно у меня явно не правильно работает
И не пойму как для него функцию удаления элементов написать
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
#include <iostream>
#include <conio.h>
 
using namespace std;
//Наша структура
struct node
{
    int info; //Информационное поле
    node *l, *r;//Левая и Правая часть дерева
};
 
node * tree=NULL; //Объявляем переменную, тип которой структура Дерево
 
/*ФУНКЦИЯ ЗАПИСИ ЭЛЕМЕНТА В БИНАРНОЕ ДЕРЕВО*/
void push(int a,node **t)
{
    if ((*t)==NULL) //Если дерева не существует
    {
        (*t)=new node; //Выделяем память
        (*t)->info=a; //Кладем в выделенное место аргумент a
        (*t)->l=(*t)->r=NULL; //Очищаем память для следующего роста
        return; //Заложили семечко, выходим
    }
       //Дерево есть
        if (a>(*t)->info) push(a,&(*t)->r); //Если аргумент а больше чем текущий элемент, кладем его вправо
        else push(a,&(*t)->l); //Иначе кладем его влево
}
 
/*ФУНКЦИЯ УДАЛЕНИЯ ЭЛЕМЕНТОВ ДЕРЕВA*/
void delete_node(){
    if (t==NULL) return; //Если дерево пустое, то удалять нечего, выходим
    else //Иначе
    { //найти максимальный элемент
               
    }
}
/*ФУНКЦИЯ ОТОБРАЖЕНИЯ ДЕРЕВА НА ЭКРАНЕ*/
void print (node *t,int u)
{
    if (t==NULL) return; //Если дерево пустое, то отображать нечего, выходим
    else //Иначе
    {
    print(t->l,++u);//С помощью рекурсивного посещаем левое поддерево
    for (int i=0;i<u;++i) cout<<"|";
    cout<<t->info<<endl; //И показываем элемент
    u--;
    }
    print(t->r,++u); //С помощью рекурсии посещаем правое поддерево
}
 
/*Функция поиска максимального элемента*/
int getMaxDepth(node* tree, int depth) {
if (tree == NULL)
return depth;
return max(getMaxDepth(tree->l, depth + 1), getMaxDepth(tree->r, depth + 1));
}
 
int main(int argc, char *argv[])
{
    int n; //Количество элементов
    int s; //Число, передаваемое в дерево
    cout<<"Vvod kol-vo elementov ";
    cin>>n; //Вводим количество элементов
 
    for (int i=0;i<n;++i)
    {
    cout<<"Enter Digit:";
    cin>>s; //Считываем элемент за элементом
 
    push(s,&tree); //И каждый кладем в дерево
    }
    cout<<"Node\n";
    print(tree,0);
    cout << "Max = "<<getMaxDepth(tree, 0);
    getch();
    return 0;
}
Выводит
Сформировать бинарное дерево поиска и определить максимальную глубину дерева
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
18.01.2018, 06:39
Ответы с готовыми решениями:

Бинарное дерево поиска (определить максимальную глубину)
Всем привет! Делаю лабу, написал основу, но не могу понять, как сделать последний пункт задания,...

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

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

Рекурсия: определить, помещена ли строка в бинарное дерево поиска
Помогите пожалуйста исправить ошибку. Задание:&quot;Разработать рекурсивную функцию, которая определяет,...

30
11 / 11 / 3
Регистрация: 06.08.2011
Сообщений: 208
18.01.2018, 17:14  [ТС] 21
Author24 — интернет-сервис помощи студентам
Я еще пока не до конца понимаю, может дальше придет понимание.. Ну да) будем считать что функция добавления у нас есть.))

Добавлено через 9 минут
Будем считать что дерево у нас есть, теперь хочется его увидеть во очию.


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    BinaryTree binaryTree;
    for(int i =0; i<5; i++){
        binaryTree.Insert(i, ( rand() % 10));
    }
 
    binaryTree.Print();
 
///////////////////////////////////
 
    void Print(){
        if(root->value != NULL)
        cout << root->value;  // Здесь должна быть обработка для вывода на консоль... (ВИДИМО) :)
 
        else cout << "Not Tree";
    }
Добавлено через 7 минут
Нет не считаем, поскольку не понимаю как по этой функции будет происходить переход в право | лево
C++
1
2
3
4
5
6
7
8
9
10
11
    void Insert(std::size_t k, int v)
     {
         if(root == nullptr)
         {
             root = new Node(); //Выделили память
             root->key = k;     //индекс
             root->value = v;   //значение
 
             return;
         }
    }
Ну правильно, это я туплю.. Мы ж ее еще не дописали. У нас только корень.
0
"C with Classes"
1646 / 1403 / 523
Регистрация: 16.08.2014
Сообщений: 5,877
Записей в блоге: 1
18.01.2018, 17:24 22
Ирина197708, вот рабочий вариант с добавлением
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
#include <cstddef>
#include <limits>
 
class BinaryTree
{
private:
    struct Node
    {
        Node* left;
        Node* right;
 
        std::size_t key;
        int value;
 
        Node(Node* l = nullptr, Node* r = nullptr) :
            left(l), right(r)
        {
            // ...
        }
 
        void Find(std::size_t k)
        {
            
        }
        void Insert(std::size_t k, int v)
        {
            if(k > key)
            {
                if (right) right->Insert(k, v);
                else
                {
                    right = new Node();
                    right->key = k;
                    right->value = v;
                }
 
            }
            else if (k < key)
            {
                if (left) left->Insert(k, v);
                else
                {
                    left = new Node();
                    left->key = k;
                    left->value = v;
                }
            }
            else
            {
                key = k;
                value = v;
            }
        }
    };
 
    Node* root;
 
public:
    BinaryTree() : root(nullptr) {}
 
    int Find(std::size_t k)
    {
        // Пока не решил что делать если элемент не найден
        if (root == nullptr)
            return -1; 
 
        // ...
 
        return 0;
    }
    void Insert(std::size_t k, int v)
    {
        if(root == nullptr)
        {
            root = new Node();
            root->key = k;
            root->value = v;
 
            return;
        }
 
        root->Insert(k, v);
    }
    void Remove(std::size_t k)
    {
        // ...
    }
};
1
11 / 11 / 3
Регистрация: 06.08.2011
Сообщений: 208
18.01.2018, 17:29  [ТС] 23
Что то у меня пошло не так...
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    void Insert(std::size_t k, int v)
     {
         if(root == nullptr)
         {
             root = new Node(); //Выделили память
             root->key = k;     //индекс
             root->value = v;   //значение
 
             return;
 
         }
         if(k > root->value){
             root->key = k++; root->right = v; }  ошибка: invalid conversion from 'int' to 'BinaryTree::Node*' [-fpermissive]
           }
                                           
    }
Добавлено через 4 минуты
А почему у тебя 2 Insert? Так можно было?
0
"C with Classes"
1646 / 1403 / 523
Регистрация: 16.08.2014
Сообщений: 5,877
Записей в блоге: 1
18.01.2018, 22:26 24
Ирина197708, BinaryTree это обертка над Node root

Добавлено через 1 минуту
рекурсивным методам типа Insert нужен this указатель на Node

Добавлено через 4 часа 16 минут
Ирина197708, только что дописал метод Find, покажи свои наработки?
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
#include <cstddef>
#include <limits>
 
class BinaryTree
{
private:
    struct Node
    {
        Node* left;
        Node* right;
 
        std::size_t key;
        int value;
 
        Node(Node* l = nullptr, Node* r = nullptr) :
            left(l), right(r)
        {
            // ...
        }
 
        int Find(std::size_t k)
        {
            if (k > key)
            {
                if (right) return right->Find(k);
                else return -1;
            }
            else if (k < key)
            {
                if (left) return left->Find(k);
                else return -1;
            }
            else
            {
                return value;
            }
        }
        void Insert(std::size_t k, int v)
        {
            if(k > key)
            {
                if (right) right->Insert(k, v);
                else
                {
                    right = new Node();
                    right->key = k;
                    right->value = v;
                }
 
            }
            else if (k < key)
            {
                if (left) left->Insert(k, v);
                else
                {
                    left = new Node();
                    left->key = k;
                    left->value = v;
                }
            }
            else
            {
                key = k;
                value = v;
            }
        }
    };
 
    Node* root;
 
public:
    BinaryTree() : root(nullptr) {}
 
    int Find(std::size_t k)
    {
        // Пока не решил что делать если элемент не найден
        if (root == nullptr)
            return -1; 
 
        return root->Find(k);
    }
    void Insert(std::size_t k, int v)
    {
        if(root == nullptr)
        {
            root = new Node();
            root->key = k;
            root->value = v;
 
            return;
        }
 
        root->Insert(k, v);
    }
    void Remove(std::size_t k)
    {
        // ...
    }
};
0
11 / 11 / 3
Регистрация: 06.08.2011
Сообщений: 208
19.01.2018, 04:52  [ТС] 25
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
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <malloc.h>
#include <Windows.h>
#include <math.h>
 
using namespace std;
 
 
typedef struct binarytree
{
    int Data; //поле данных
    binarytree * Left; //указатель на левого потомка
    binarytree * Right; //указатель на правого потомка
} BinaryTree;
 
 
//вставка вершины в бинарное дерево
void Insert_Node_BinaryTree(BinaryTree** Node,int Data) {
    BinaryTree* New_Node = (BinaryTree*)
    malloc(sizeof(BinaryTree));
    New_Node->Data = Data;
    New_Node->Left = NULL;
    New_Node->Right = NULL;
    BinaryTree** ptr = Node;//вспомогательный указатель
while (*ptr != NULL)
    if (Data < (*ptr)->Data) ptr = &((*ptr)->Left);
else ptr = &((*ptr)->Right);
*ptr = New_Node;
}
 
//создание бинарного дерева
void Create(BinaryTree** p, int x)
{
if(!(*p))//если указатель на корень дерева не равен NULL
{
BinaryTree* pnew = (BinaryTree*)
    malloc(sizeof(BinaryTree));// выделяем память
    pnew->Data = x;//заносим значение
    pnew->Left = pnew->Right = NULL;
    *p = pnew;
}
 
else
{
    if((*p)->Data> x)
    Create(&((*p)->Left), x);
else
    Create(&((*p)->Right), x);
    }
}
 
/*Вывод двоичного дерева на экран*/
void Vyvod (BinaryTree **p,int l)
{
int i;
if (*p!=NULL)
{
    Vyvod (&((*p)->Right),l+1);
for (i=0; i<l; i++)
    printf(" ");
    printf("%d\n",(*p)->Data);
    Vyvod (&((*p)->Left),l+1);
    }
}
 
//удаление вершины из бинарного дерева
void Delete_Node_BinaryTree(BinaryTree** Node,int Data){
    if ( (*Node) != NULL ){
        if ((*Node)->Data == Data){
        BinaryTree* ptr = (*Node);
    if ( (*Node)->Left == NULL && (*Node)->Right == NULL)
    (*Node) = NULL;
    else if ((*Node)->Left == NULL) (*Node) = ptr->Right;
    else if ((*Node)->Right == NULL) (*Node) = ptr->Left;
else {
(*Node) = ptr->Right;
BinaryTree ** ptr1;
ptr1 = Node;
while (*ptr1 != NULL)
    ptr1 = &((*ptr1)->Left);
    (*ptr1) = ptr->Left;
}
free(ptr);
    Delete_Node_BinaryTree(Node,Data);
}
else {
    Delete_Node_BinaryTree(&((*Node)->Left),Data);
    Delete_Node_BinaryTree(&((*Node)->Right),Data);
        }
    }
}
 
 
bool empty_tree(BinaryTree * Node) //Проверяем пустое ли дерево
{
    if(Node==NULL) return true;
    else return false;
}
//прямой обход бинарного дерева
void PreOrder_BinaryTree(BinaryTree* Node){
    if (Node != NULL) {
        printf ("%3ld",Node->Data);
    PreOrder_BinaryTree(Node->Left);
    PreOrder_BinaryTree(Node->Right);
    }
}
 
 
/* Выводим максимальную глубину дерева */
/*максимальная глубина бинарного дерева
 *  - это количество нод на самом длинном пути от корневой ноды до самой дальней листовой ноды.*/
int maxDepth(BinaryTree* Node) {
  if (Node==NULL) {
    return(0);
  }
  else {
    // compute the depth of each subtree
    int lDepth = maxDepth(Node->Left);
    int rDepth = maxDepth(Node->Right);
    // use the larger one
    if (lDepth > rDepth) return(lDepth+1);
    else return(rDepth+1);
  }
}
 
 
//освобождение памяти, выделенной под бинарное дерево
/*С помощью функции Delete_BinaryTree(Root) программа рекурсивно выполняет очистку памяти, занимаемой деревом, используя
функцию освобождения памяти free. После прохождения по всем элементам дерева программа возвращает указателю на корень дерева
Root значение NULL, таким образом стирая и сам указатель на это дерево.*/
 
BinaryTree* Delete_BinaryTree(BinaryTree* Node){
if (Node != NULL) //Пока дерево не пусто
{
    Delete_BinaryTree(Node->Left); //проходимся по левой ветви
    Delete_BinaryTree(Node->Right); //проходимся по правой
    free(Node); //Удаляем указатель на дерево
}
return NULL;
}
int main()
{
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
    cout << "Binarnoe derevo:\n" << endl;
 
    int i,n,temp;
    BinaryTree * Root;
    Root=NULL;
    printf("Enter Kol-vo \t"); scanf("%d",&n);
    for(i=0;i<n;i++)
    {
        scanf("%d",&temp);
        Create(&Root,temp);
    }
    Vyvod(&Root,0);
 
 
    printf("Max Hight dereva %d", maxDepth(Root));
    //Удаляем дерево
        Root=Delete_BinaryTree(Root);
        if(empty_tree(Root))
            printf("\nMemory delete!\n");
        getch();
    return 0;
}
1
"C with Classes"
1646 / 1403 / 523
Регистрация: 16.08.2014
Сообщений: 5,877
Записей в блоге: 1
19.01.2018, 08:42 26
Ирина197708, можно вопрос? зачем ты здесь применяешь двойную косвенность в аргументе, т.е. передаешь в функцию указатель на указатель?
C++
1
void Insert_Node_BinaryTree(BinaryTree** Node,int Data);
Добавлено через 16 минут
и опять же придерживаешься стиля си.

Добавлено через 16 минут
хотя я сам так раньше делал.
0
11 / 11 / 3
Регистрация: 06.08.2011
Сообщений: 208
19.01.2018, 11:05  [ТС] 27
Давай не сейчас))) Сейчас времени думать нет, нужно срочно результат выдать

Добавлено через 22 минуты
printf("\nglubina node\n");
int l = CountLeft(Root, 0);
int r = CountRight(Root, 0);
if (l > r){ printf("\nleft node max.\n"); printf("%d", l); }
else if (r > l){ printf("\nright node max.\n");
printf("%d", r);
}

В итоге не правильно выдает...
0
2848 / 1997 / 986
Регистрация: 21.12.2010
Сообщений: 3,705
Записей в блоге: 10
19.01.2018, 18:24 28
удаление узла (надо тестить)
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
#include <iostream>
#include <conio.h>
#include <algorithm>
 
using namespace std;
 
//Наша структура
struct node
{
    int info; //Информационное поле
    node *l, *r;//Левая и Правая часть дерева
};
 
/*ФУНКЦИЯ ЗАПИСИ ЭЛЕМЕНТА В БИНАРНОЕ ДЕРЕВО, все элементы уникальны */
void push(int num, node*& t)
{
    if (t == NULL) //Если дерева не существует
    {
        t = new node; //Выделяем память
        t->info = num; //Кладем в выделенное место аргумент a
        t->l = t->r = NULL; //Очищаем память для следующего роста
    }
    else if (num > t->info)
    {
         push(num, t->r); //Если аргумент а больше чем текущий элемент, кладем его вправо
    }
    else if(num < t->info)
    {
        push(num, t->l); //Иначе кладем его влево
    }
}
 
// поиск родителя для num
node* find_parent(node* tree, int const num)
{
    node* parent = NULL;
    while (tree)
    {
        if (num < tree->info)
        {
            parent = tree;
            tree = tree->l;
        }
        else if (num > tree->info)
        {
            parent = tree;
            tree = tree->r;
        }
        else
        {
            break;
        }
    }
    if (!tree)
    {
        parent = NULL;
    }
 
    return parent;
}
 
/*ФУНКЦИЯ УДАЛЕНИЯ ЭЛЕМЕНТА ДЕРЕВA*/
void delete_node(node*& t, int num) 
{
    if (t)
    {
        node* tree = t;
        // ищем родителя для num
        node* parent = find_parent(tree, num);
        // если родитель найден то tree выставляем на потомка которого нужно удалить
        if (parent)
        {
            if (parent->l && parent->l->info == num)
            {
                tree = parent->l;
            }
            else
            {
                tree = parent->r;
            }
        }
 
        if (tree->info == num || parent)
        {
            if (NULL == tree->l && NULL == tree->r) // у удаляемого узла нет потомков
            {
                if (parent)
                {
                    parent->l == tree ? parent->l = NULL : parent->r = NULL;
                }
                else // корневой узел без потомков
                {
                    t = NULL;
                }
                delete tree;
                tree = NULL;
            }
            else if (NULL == tree->l) // у удаляемого узла нет l 
            {
                node* tmp = tree->r;
                std::iter_swap(tree, tree->r);
                delete tmp;
                tmp = NULL;
            }
            else if (NULL == tree->r) // у удаляемого узла нет r
            {
                node* tmp = tree->l;
                std::iter_swap(tree, tree->l);
                delete tmp;
                tmp = NULL;
            }
            else // у удаляемого узла есть l и r
            {
                if (NULL == tree->r->l)
                {
                    node* tmp = tree->r;
                    tree->info = tree->r->info;
                    tree->r = tree->r->r;
                    delete tmp;
                    tmp = NULL;
                }
                else
                {
                    node* tmp = tree->r;
                    while (tmp->l->l)
                    {
                        tmp = tmp->l;
                    }
                    tree->info = tmp->l->info;
                    if (NULL == tmp->l->r)
                    {
                        delete tmp->l;
                        tmp->l = NULL;
                    }
                    else
                    {
                        node* t1 = tmp->l->r;
                        std::iter_swap(tmp->l, tmp->l->r);
                        delete t1;
                        t1 = NULL;
                    }
                }
            }
        }
    }
}
 
/*ФУНКЦИЯ ОТОБРАЖЕНИЯ ДЕРЕВА НА ЭКРАНЕ*/
void print(node *t, int u = 0)
{
    if (t)
    {
        print(t->r, u + 1);//С помощью рекурсивного посещаем левое поддерево
        for (int i = 0; i < u; ++i)
        {
            cout << "|";
        }
        cout << t->info << endl; //И показываем элемент
        print(t->l, u + 1); //С помощью рекурсии посещаем правое поддерево
    }
}
 
/*Функция поиска глубины*/
int depth(node* tree) 
{
    int ret = 0;
    if (tree) 
    {
        int lDepth = depth(tree->l);
        int rDepth = depth(tree->r);
        ret = std::max(lDepth + 1, rDepth + 1);
    }
    return ret;
}
 
int main()
{
    node * tree = NULL; //Объявляем переменную, тип которой структура Дерево
    int n; //Количество элементов
    int s; //Число, передаваемое в дерево
    cout << "Vvod kol-vo elementov ";
    cin >> n; //Вводим количество элементов
 
    for (int i = 0; i < n; ++i)
    {
        cout << "Enter Number:";
        cin >> s; //Считываем элемент за элементом
 
        push(s, tree); //И каждый кладем в дерево
    }
    cout << "Tree\n";
    {
        print(tree);
        cout << endl;
    }
    
    //cout << "\ndepth = " << depth(tree);
 
    delete_node(tree, 5);
    {
        print(tree);
        cout << endl;
    }
    push(10, tree);
    push(17, tree);
    {
        print(tree);
        cout << endl;
    }
    
    
    _getch();
    return 0;
}
0
2848 / 1997 / 986
Регистрация: 21.12.2010
Сообщений: 3,705
Записей в блоге: 10
22.01.2018, 11:30 29
удалено
0
"C with Classes"
1646 / 1403 / 523
Регистрация: 16.08.2014
Сообщений: 5,877
Записей в блоге: 1
23.01.2018, 06:23 30
igorrr37, что удалено?

Добавлено через 18 часов 22 минуты
Ирина197708,
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
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
/***************************************************************************
Я пока тебе так отправлю, потом надо будет дописать блок else в методе 
Remove, ну и еще пару коментов, а и еще нужно из всего этого сделать
шаблон, что бы структура хранила даные разных типов.
****************************************************************************/
 
#include <cstddef>
 
class BinaryTree
{
public:
    // Тип для исключения, если узел не найден
    struct NoElement {};
 
    // Тип для узла дерева
    struct Node
    {
        // Указатель на предка узла
        Node* parent;
 
        // Указатель на левого потомка узла
        Node* left;
        // Указатель на правого потомка узла
        Node* right;
 
        // Значение узла
        int value;
        // Ключ узла
        size_t key;
 
        /*Конструктор по умолчанию, все указатели в структуре nullptr.
          в полях value и key мусор*/
        Node() : left{nullptr}, right{nullptr}, parent{nullptr}
        {
            // ...
        }
 
        // Рекурсивный метод поиска узла по ключу
        int Find(size_t k) const
        {
            /*Если k > key поверяем указатель на правого потомка,
              если right != nullptr рекурсивно вызываем Find для
              правого потомка, если right == nullptr бросаем
              исключение NoElement*/
            if (k > key)
            {
                if (right) return right->Find(k);
                else throw NoElement();
            }
            /*Если k < key поверяем указатель на левого потомка,
              если left != nullptr рекурсивно вызываем Find для
              левого потомка, если left == nullptr бросаем
              исключение NoElement*/
            else if (k < key)
            {
                if (left) return left->Find(k);
                else throw NoElement();
            }
            // Если k == key возвращаем value
            else
            {
                return value;
            }
        }
        // Рекурсивный метод вставки значения v по ключу k
        void Insert(size_t k, int v)
        {
            /*Если k > key поверяем указатель на правого потомка,
              если right != nullptr рекурсивно вызываем Insert для
              правого потомка, если right == nullptr создаем нового
              потомка и присваеваем его полям новые значения*/
            if(k > key)
            {
                if (right) right->Insert(k, v);
                else
                {
                    right = new Node();
                    right->key = k;
                    right->value = v;
                    right->parent = this;
                }
 
            }
            /*Если k < key поверяем указатель на левого потомка,
              если left != nullptr рекурсивно вызываем Insert для
              левого потомка, если left == nullptr создаем нового
              потомка и присваеваем его полям новые значения*/
            else if (k < key)
            {
                if (left) left->Insert(k, v);
                else
                {
                    left = new Node();
                    left->key = k;
                    left->value = v;
                    left->parent = this;
                }
            }
            // Если k == key присваеваем его полям новые значения
            else
            {
                key = k;
                value = v;
            }
        }
        // Рекурсивный метод удаления узла по ключу
        void Remove(std::size_t k)
        {
            /*Если k > key поверяем указатель на правого потомка,
              если right != nullptr рекурсивно вызываем Remove для
              правого потомка, если right == nullptr бросаем
              исключение NoElement*/
            if (k > key)
            {
                if (right) return right->Remove(k);
                else throw NoElement();
            }
            /*Если k < key поверяем указатель на левого потомка,
              если left != nullptr рекурсивно вызываем Remove для
              левого потомка, если left == nullptr бросаем
              исключение NoElement*/
            else if (k < key)
            {
                if (left) return left->Remove(k);
                else throw NoElement();
            }
            // Если k == key расмотрим четыре варианта
            else
            {
                // Если нет ни правого ни левого потомка
                if (!left && !right)
                {
                    /* Проверяем является ли узел левым потомком родителя,
                       если да то обнуляем указатель родител на левого
                       потомка */
                    if (IsLeft() )
                        parent->left = nullptr;
                    /* В противном случае обнуляем указатель родителя на
                       правого потомка */
                    else
                        parent->right = nullptr;
 
                    // Удаляем узел
                    delete this;
                }
                // Если есть левый потомок, но нет правого
                else if (left && !right)
                {
                    /* Проверяем является ли узел левым потомком родителя,
                       если да то присваиваем родителю в левый узел
                       указатель на левый узел текущего узла */
                    if (IsLeft() )
                        parent->left = left;
                    else
                        parent->right = left;
 
                    left->parent = parent;
                    // Удаляем узел
                    delete this;
                }
                else if (!left && right)
                {
                    if (IsRight() )
                        parent->right = right;
                    else
                        parent->left = right;
 
                    right->parent = parent;
                    // Удаляем узел
                    delete this;
                }
                else
                {
                    // тут пока хз...)))
                }
            }
        }
 
        // Проверка является ли узел левым поддеревом
        bool IsLeft()
        {
            return parent->left && parent->left->key == key;
        }
        // Проверка является ли узел правым поддеревом
        bool IsRight()
        {
            return parent->right && parent->right->key == key;
        }
        
        // Глубина левого поддерева
        size_t CountLeft(size_t count)
        {
            if (left) return left->CountLeft(++count);
            else return count;
        }
        // Глубина правого поддерева
        size_t CountRight(size_t count)
        {
            if (right) return right->CountRight(++count);
            else return count;
        }
    };
 
    // Корневой узел дерева
    Node* root;
 
public:
    // По умолчанию конструктор (этим вроде как все сказанно)
    BinaryTree() : root(nullptr) {}
 
    // Интерфейс для связи с Node (далее все методы тоже самое...)
    int Find(std::size_t k)
    {
        if (root == nullptr)
            throw NoElement();
 
        return root->Find(k);
    }
    void Insert(std::size_t k, int v)
    {
        if(root == nullptr)
        {
            root = new Node();
            root->key = k;
            root->value = v;
 
            return;
        }
 
        root->Insert(k, v);
    }
    void Remove(std::size_t k)
    {
        if(root == nullptr)
            throw NoElement();
 
        root->Remove(k);
    }
 
    size_t CountLeft(size_t count = 0)
    {
        return root->CountLeft(count);
    }
    size_t CountRight(size_t count = 0)
    {
        return root->CountRight(count);
    }
};
 
int main(int argv, char* argc[] )
{
    BinaryTree binaryTree;
 
    binaryTree.Insert(15, 15 * 2);
    binaryTree.Insert(14, 14 * 2);
    binaryTree.Insert(13, 13 * 2);
    binaryTree.Insert(12, 12 * 2);
    binaryTree.Insert(18, 18 * 2);
    binaryTree.Insert(17, 17 * 2);
 
    size_t left = binaryTree.CountLeft();
    size_t right = binaryTree.CountRight();
 
    int value = binaryTree.Find(18);
    binaryTree.Remove(18);
 
    return 0;
}
0
"C with Classes"
1646 / 1403 / 523
Регистрация: 16.08.2014
Сообщений: 5,877
Записей в блоге: 1
05.02.2018, 08:05 31
вроде работает, кому интересно.
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
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
/***************************************************************************
/Binary search tree/ Copyright (c) by P.S. Gennadevich. All rights reserved.
 V 0.1                                                           30.01.2018.
****************************************************************************/
 
#include <iostream>
 
template<typename TKey, typename TValue> class BinaryTree
{
public:
    // Тип для исключения, если узел не найден
    struct NoElement {};
 
    // Тип для узла дерева
    struct Node
    {
        // Указатель на предка узла
        Node* parent;
 
        // Указатель на левого потомка узла
        Node* left;
        // Указатель на правого потомка узла
        Node* right;
 
        // Ключ узла
        TKey key;
        // Значение узла
        TValue value;
 
        /* Указатель на BinaryTree, служит для обнуления указателя
           BinaryTree::root */
        BinaryTree* pProprietor;
 
        /* Конструктор */
        Node(
                TKey k = 0,
                TValue v = 0,
                Node* l = nullptr,
                Node* r = nullptr,
                Node* p = nullptr,
                BinaryTree* pP = nullptr
            ) :
                key{k},
                value{v},
                left{l},
                right{r},
                parent{p},
                pProprietor{pP}
        {
            std::cout << "Node::Node"
                << std::endl;
        }
        // Деструктор
        ~Node()
        {
            std::cout << "Node::~Node key: "
                << key << std::endl;
        }
 
        // Рекурсивное уничтожение дерева
        void Destroy()
        {
            if (left) left->Destroy();
            if (right) right->Destroy();
 
            delete this;
        }
 
        // Рекурсивный метод поиска узла по ключу
        int Find(TKey k) const
        {
            /* Если k > key поверяем указатель на правого потомка,
               если right != nullptr рекурсивно вызываем Find для
               правого потомка, если right == nullptr бросаем
               исключение NoElement */
            if (k > key)
            {
                if (right) return right->Find(k);
                else throw NoElement();
            }
            /* Если k < key поверяем указатель на левого потомка,
               если left != nullptr рекурсивно вызываем Find для
               левого потомка, если left == nullptr бросаем
               исключение NoElement */
            else if (k < key)
            {
                if (left) return left->Find(k);
                else throw NoElement();
            }
            // Если k == key возвращаем value
            else
            {
                return value;
            }
        }
        // Рекурсивный метод вставки значения v по ключу k
        void Insert(TKey k, TValue v)
        {
            /* Если k > key поверяем указатель на правого потомка,
               если right != nullptr рекурсивно вызываем Insert для
               правого потомка, если right == nullptr создаем нового
               потомка и присваеваем его полям новые значения */
            if(k > key)
            {
                if (right) right->Insert(k, v);
                else
                    right = new Node(k, v, nullptr, nullptr,
                        this, pProprietor);
            }
            /* Если k < key поверяем указатель на левого потомка,
               если left != nullptr рекурсивно вызываем Insert для
               левого потомка, если left == nullptr создаем нового
               потомка и присваеваем его полям новые значения */
            else if (k < key)
            {
                if (left) left->Insert(k, v);
                else
                {
                    left = new Node(k, v, nullptr, nullptr,
                        this, pProprietor);
                }
            }
            // Если k == key присваеваем его полям новые значения
            else
            {
                key = k;
                value = v;
            }
        }
        // Рекурсивный метод удаления узла по ключу
        void Remove(TKey k)
        {
            /* Если k > key поверяем указатель на правого потомка,
               если right != nullptr рекурсивно вызываем Remove для
               правого потомка, если right == nullptr бросаем
               исключение NoElement */
            if (k > key)
            {
                if (right) return right->Remove(k);
                else throw NoElement();
            }
            /* Если k < key поверяем указатель на левого потомка,
               если left != nullptr рекурсивно вызываем Remove для
               левого потомка, если left == nullptr бросаем
               исключение NoElement */
            else if (k < key)
            {
                if (left) return left->Remove(k);
                else throw NoElement();
            }
            // Если k == key рассматривается четыре варианта
            else
            {
                // Если нет ни правого ни левого потомка
                if (!left && !right)
                {
                    if (IsRoot() )
                        pProprietor->root = nullptr;
 
                    else if (IsLeftHeir() )
                        parent->left = nullptr;
 
                    else if (IsRightHeir() )
                        parent->right = nullptr;
 
                }
                // Если есть левый потомок, но нет правого
                else if (left && !right)
                {
                    if (IsRoot() )
                        pProprietor->root = left;
 
                    else if (IsLeftHeir() )
                        parent->left = left;
 
                    else if (IsRightHeir() )
                        parent->right = left;
 
                    left->parent = parent;
                }
                // Если есть правый потомок но нет левого
                else if (!left && right)
                {
                    if (IsRoot() )
                        pProprietor->root = right;
 
                    else if (IsLeftHeir() )
                        parent->left = right;
 
                    else if (IsRightHeir() )
                        parent->right = right;
 
                    right->parent = parent;
                }
                // Если есть оба потомка
                else
                {
                    // Если у правого потомка нет левого узла
                    if (!right->left)
                    {
                        right->parent = parent;
                        right->left = left;
                        left->parent = right;
 
                        if (IsRoot() )
                            pProprietor->root = right;
                    }
                    // Если у правого потомка есть левый узел
                    else
                    {
                        Node* lastLeft = right;
                        while (lastLeft->left)
                            lastLeft = lastLeft->left;
 
                        lastLeft->parent->left = nullptr;
 
                        lastLeft->left = left;
                        lastLeft->right = right;
                        lastLeft->parent = parent;
 
                        if (IsRoot() )
                            pProprietor->root = lastLeft;
                    }
                }
 
                // Удалить текущий узел
                delete this;
            }
        }
 
        // Проверка является ли узел левым потомком
        bool IsLeftHeir()
        {
            return parent->left && parent->left->key == key;
        }
        // Проверка является ли узел правым потомком
        bool IsRightHeir()
        {
            return parent->right && parent->right->key == key;
        }
        // Проверка является ли узел корнем
        bool IsRoot()
        {
            return !parent;
        }
    };
 
    // Указатель на корневой узел дерева
    Node* root;
 
public:
    // Конструктор по умолчанию root = nullptr
    BinaryTree() : root{nullptr}
    {
        // ...
    }
    // Деструктор
    ~BinaryTree()
    {
        root->Destroy();
    }
 
    // Интерфейс Find для связи с Node
    int Find(TKey k)
    {
        if (root == nullptr)
            throw NoElement();
 
        return root->Find(k);
    }
    // Интерфейс Insert для связи с Node
    void Insert(TKey k, TValue v)
    {
        if(root == nullptr)
        {
            root = new Node(k, v, nullptr, nullptr,
                nullptr, this);
 
            return;
        }
 
        root->Insert(k, v);
    }
    // Интерфейс Remove для связи с Node
    void Remove(TKey k)
    {
        if(root == nullptr)
            throw NoElement();
 
        root->Remove(k);
    }
};
 
#include <cstddef>
#include <string>
 
int main(int argv, char* argc[] )
{
    BinaryTree<std::size_t, int>* p1 = new BinaryTree<std::size_t, int>();
 
    p1->Insert(10, 10 * 2);
    p1->Insert(20, 20 * 2);
    p1->Insert(30, 30 * 2);
    p1->Insert(19, 19 * 2);
    p1->Insert(18, 18 * 2);
    p1->Insert(17, 17 * 2);
    p1->Insert(16, 16 * 2);
 
    p1->Insert(9, 9 * 2);
 
    p1->Remove(9);
 
    delete p1;
 
    BinaryTree<std::string, double>* p2 = new BinaryTree<std::string, double>();
 
    p2->Insert("One", 1.1);
    p2->Insert("Two", 2.2);
    p2->Insert("Three", 3.3);
    p2->Insert("Four", 4.4);
    p2->Insert("Five", 5.5);
    p2->Insert("Six", 6.6);
    p2->Insert("Seven", 7.7);
 
    p2->Insert("Eight", 8.8);
 
    p2->Remove("Eight");
 
    delete p2;
 
    return 0;
}
0
05.02.2018, 08:05
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
05.02.2018, 08:05
Помогаю со студенческими работами здесь

Преобразовать идеальное бинарное дерево в бинарное дерево поиска
Всем привет, я создал идельное бинарное дерево и написал к нему функции. Как мне теперь можно...

Найти максимальную глубину дерева
#include &quot;stdafx.h&quot; #include &lt;iostream&gt; using std::cout; using std::cin; using std::endl; ...

Найти максимальную глубину дерева
найти максимальную глубину дерева

Найти максимальную и минимальную глубину дерева
1)вести дерево с клавиатуры 2)определить max глубину дерева 3)определить min глубину дерева


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

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