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

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

10.05.2019, 10:31. Показов 3001. Ответов 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
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера 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. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru