Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.93/15: Рейтинг темы: голосов - 15, средняя оценка - 4.93
0 / 0 / 0
Регистрация: 05.03.2018
Сообщений: 4

Копирование и объединение бинарных деревьев

10.05.2019, 10:31. Показов 2964. Ответов 5

Студворк — интернет-сервис помощи студентам
Всем здравствуйте, в университете на лабораторной работе дали задачу объединить 2 бинарных дерева. Алгоритм их объединения выполняется следующим образом: Сначала создаем оба дерева, затем делаем копию первого и вставляем в него узлы второго дерева. Я смог написать копирование и объединение, но они работают некорректно. В прикрепленном скриншоте видно что копия выводится с артефактами, а объединения не происходит. Просьба знающих людей помочь с решением проблемы. Всем добра и легкой компиляции)
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
#include <iostream>
using namespace std;
 
struct Node                         //Звено дерева
{
   int x;                           //То, что записываем в дерево
   Node *l,*r;                      //Это указатели на новые звенья
};
 
void show(Node *&Tree)              //Функция обхода
{
    if (Tree != NULL)               //Пока не встретится пустое звено
    {
       show(Tree->l);               //Рекурсивная функция для вывода левого поддерева
       cout << Tree->x << '\t';               //Отображаем корень дерева
       show(Tree->r);               //Рекурсивная функци для вывода правого поддерева
    }
}
 
/*Добавили очистку памяти*/
void del(Node *&Tree){
   if (Tree != NULL)                //Пока не встретится пустое звено
    {
       del(Tree->l);                //Рекурсивная функция прохода по левому поддереву
       del(Tree->r);                //Рекурсивная функци для прохода по правому поддереву
       delete Tree;                 //Убиваем конечный элемент дерева
       Tree = NULL;                 //Может и не обязательно, но плохого не будет
    }
 
}
 
void add_node(int x,Node *&MyTree) //Фукция добавления звена в дерево
{
    if (NULL == MyTree)             //То, о чем я в самом начале писал. Если дерева нет, то ложим семечко
    {
        MyTree = new Node;          //Выделяем память под звено дерева
        MyTree->x = x;              //Записываем данные в звено
        MyTree->l = MyTree->r = NULL; //Подзвенья инициализируем пустотой во избежание ошибок
    }
 
                   if (x < MyTree->x)   //Если нововведенный элемент x меньше чем элемент x из семечка дерева, уходим влево
                      {
                          if (MyTree->l != NULL) add_node(x, MyTree->l); //При помощи рекурсии заталкиваем элемент на свободный участок
                          else          //Если элемент получил свой участок, то
                          {
                              MyTree->l = new Node;                 //Выделяем память левому подзвену. Именно подзвену, а не просто звену
                              MyTree->l->l = MyTree->l->r = NULL;   //У левого подзвена будут свои левое и правое подзвенья, инициализируем их пустотой
                              MyTree->l->x = x;                     //Записываем в левое подзвено записываемый элемент
                          }
                      }
 
                    if (x > MyTree->x)              //Если нововведенный элемент x больше чем элемент x из семечка дерева, уходим вправо
                      {
                          if (MyTree->r != NULL) add_node(x, MyTree->r); //При помощи рекурсии заталкиваем элемент на свободный участок
                          else              //Если элемент получил свой участок, то
                          {
                              MyTree->r = new Node;                 //Выделяем память правому подзвену. Именно подзвену, а не просто звену
                              MyTree->r->l = MyTree->r->r = NULL;   //У правого подзвена будут свои левое и правое подзвенья, инициализируем их пустотой
                              MyTree->r->x = x;                     //Записываем в правое подзвено записываемый элемент
                          }
                      }
}
 
Node *unite(Node *copy, Node *root2)// Объединение деревьев
{
   if (copy==0)
   {
       printf("первое ноль \n");
      show(root2);//Если первое дерево пустое, то выводим второе
     
      return root2;
      exit(1);//Выход
   }
   if (root2==0)
   {
      printf("второе ноль\n");
      show(copy);//Если второе дерево пустое, то выводим первое
 
      
       return copy;
      exit(1);//Выход
   }
   if (copy!=NULL)//Если первое не пустое, то
   {
      root2=unite(copy->r, root2);//Объединяем со вторым
      copy->r=root2;
      
      show(copy);
      return copy;
   }
   else
   {
      copy=unite(copy, root2->l);//Иначе объединяем с первым
      root2->l=copy;
      show(root2);
return root2;
   }
}
 
Node *CopyTree(Node *Tree)
{
   if (Tree==0)
      return 0 ;
   
 
   Node *copy = new Node;
   copy->x=Tree->x;
   copy->l=CopyTree(Tree->l);
   copy->r=CopyTree(Tree->r);
   
   
show(copy);
return copy;
}
 
int main()
{
   /*Node *Tree = NULL;                   //Создаю указатель, тип которого = звено дерева и инициализирую его пустотой
      for (int i=5; i>0; i--) add_node(i,Tree);       //Это я забивал 5-4-3-2-1, а вывод сами увидите
      show(Tree);                        //Вывод на экран дерева. или просто обход дерева
      cout << '\n';
      del(Tree);                        //Чистка памяти! Распилили дерево
 
      for (int i=20; i>5; i--) add_node(i,Tree);        //На месте спиленного дерева можно растить новое
      show(Tree);                       //Смотрим, что выросло
      del(Tree);                        //Когда дерево уже не нужно, зачищаем память
*/
      FILE *input1; //Бинарный файл в котором задано первое дерево
   FILE *input2; //Бинарный файл в котором задано второе дерево
   Node *root1=0 ;//Первое дерево
   Node *root2=0;//Второе дерево
   Node *copy=0;
   int n=4,m=3;
   int s[5];
   int a[4];
 
   input1=fopen("input1.bin", "r");//открытие и считывание информации с бинарного файла
   for (int i=0; i<=n; i++)
   {
      fscanf(input1, "%d ", &s[i]);//получение информации о  звеньях первого дерева
   }
   fclose(input1);
   printf("Дерево номер 1 \n");
   for (int i = 0; s[i]; i++)
   {
      add_node(s[i], root1);//Заполняем первое дерево значениями
   }
 
  show(root1);//Вывод первого дерева
     printf(" \n ");
   printf(" копия \n ");
    CopyTree(root1);
  // del(root1);
   show(copy);
   // 
 
   input2=fopen("input2.bin", "r");//открытие и считывание информации с бинарного файла
 
   for (int j=0; j<=m; j++)
   {
      fscanf(input2, "%d ", &a[j]);//получение информации о звеньях второго дерева
   }
   fclose(input2);
   printf("\n");
   printf("Дерево номер 2 \n");
   for (int j = 0;j<=m; j++)
   {
      add_node(a[j], root2);//Заполняем второе дерево значениями
   }
show(root2);
    printf(" \n ");
   printf(" копия \n ");
   // CopyTree(root2);
   del(root2);
    printf(" \n ");
   unite(copy, root2);//Объединяем деревья
  
   return 0;
   }
Миниатюры
Копирование и объединение бинарных деревьев  
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
10.05.2019, 10:31
Ответы с готовыми решениями:

Объединение 2-х бинарных деревьев в одно
Необходима функция объединения 2-х бинарных сбалансированных деревьев в одно.

Слияние бинарных деревьев
Слияние - это функция выбора элемента из двух Берем два дерева; функцию, которая выбирает один элемент из двух T fun(T x1, Tx2); ...

Класс бинарных деревьев. Наследование
Доброго времени суток! Имеется задание написать абстрактный класс бинарного дерева и класс рациональных чисел. От них отнаследовать классы...

5
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
10.05.2019, 11:04
Цитата Сообщение от Chedening Посмотреть сообщение
Я смог написать копирование и объединение, но они работают некорректно.
Это означает, что не смог

Допустим, что add_noode у тебя реализован правильно (я не стал разбираться).
Тогда -
Копирование дерева это обход дерева и добавление, add_node, его элементов в пустое дерево
Объединение - обход и добавление в непустое дерево

Т.е. тебе нужно только реализовать только CopyTree, чтобы она обходила входное дерево (что у тебя хуже-бедно реализовано) и вызывала add_node для выходного
C++
1
2
3
4
5
6
7
8
void CopyTree(const Node *SrcTree, Node *&DstTree);
 
Node *tree1 = LoadTree(......);
Node *tree2 = LoadTree(......);
 
Node *tree3 = nullptr;
CopyTree(tree1, tree3); //Копируем первое дерево
CopyTree(tree2, tree3); //Объединяем со вторым
0
0 / 0 / 0
Регистрация: 05.03.2018
Сообщений: 4
10.05.2019, 11:16  [ТС]
Спасибо за ответ, как я понимаю LoadTree - это функция обхода дерева?
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
10.05.2019, 11:22
Цитата Сообщение от Chedening Посмотреть сообщение
как я понимаю LoadTree - это функция обхода дерева?
Нет это загрузка дерева из файда. У тебя:
C++
1
2
3
4
5
6
7
8
9
10
11
   input1=fopen("input1.bin", "r");//открытие и считывание информации с бинарного файла
   for (int i=0; i<=n; i++)
   {
      fscanf(input1, "%d ", &s[i]);//получение информации о  звеньях первого дерева
   }
   fclose(input1);
   printf("Дерево номер 1 \n");
   for (int i = 0; s[i]; i++)
   {
      add_node(s[i], root1);//Заполняем первое дерево значениями
   }
Обход дерева это CopyTree
0
0 / 0 / 0
Регистрация: 05.03.2018
Сообщений: 4
10.05.2019, 11:50  [ТС]
Хорошо, тогда еще один вопрос:const Node *SrcTree, Node *&DstTree, что это означает?
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
10.05.2019, 12:26
Параметры функции CopyTree. SrcTree откуда копировать, DstTree - куда
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
10.05.2019, 12:26
Помогаю со студенческими работами здесь

Нужен совет по алгоритмам, обход бинарных деревьев
Всем привет! Вопрос может показаться немного глупым но все же: есть тема курсача &quot;Обход бинарных деревьев методом перебора&quot; ...

Создать функции ввода/вывод для бинарных деревьев
Не могу создать функции ввода/вывод для бинаных деревьев. очень срочно нужно! скажите где ошибка... Вот текст: #include ...

Объединение двух бинарных файлов
Как сделать программу которая считывает числа (упорядоченные по возрастанию) из двух бинарных файлов f и g, и сливает их в один...

Сравнение бинарных деревьев
Здравствуйте, уважаемое сообщество. Необходима ваша помощь! Положим у нас есть 2 бинарных дерева. Нужно сравнить их: 1)вернуть...

Реализация бинарных деревьев в компьютере
Реализовать добавление в дерево в начало, середину и конец, а так же реализовать удаление из дерева данных добавлений.


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

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Новые блоги и статьи
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка. Рецензия / Мнение/ Перевод https:/ / **********/ gallery/ thinkpad-x220-tablet-porn-gzoEAjs . . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru