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

Реализация дерева поиска список сыновей

25.02.2019, 09:48. Показов 13377. Ответов 25
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день.
Нужно создать 2-а дерева поиска и хранить их "списком сыновей". В нужно вставить в А используя обратных обход. И вывести результат - А выводить прямым обходом, а В симметричным. Требуется реализовать начальное формирование деревьев А и В, путем добавления некоторой последовательности значений (узлов) в пустое дерево. После чего требуется реализовать заданную операцию над деревьями без использования каких-либо вспомогательных структур (списков, массивов и т.п.), работая только с узлами деревьев А и В. (Не знаю как можно отказаться от списков, если в них храниться структура дерева).

Что такое "список сыновей" я представляю, все как описано на 2-ой миниатюре, но как это реализовать на С++?
Миниатюры
Реализация дерева поиска список сыновей   Реализация дерева поиска список сыновей  
1
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
25.02.2019, 09:48
Ответы с готовыми решениями:

Реализация дерева поиска
Мне крайне срочно необходимо реализовать дерево поиска на с++(чтобы пользователь сам вводил значения), я и сам конечно пытался сделать это,...

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

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

25
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
25.02.2019, 11:15
Bonttpol, мне известны 2 и 3-деревья поиска. Потому как произвольные n-деревья могут иметь правила а могут быть произвольными. В вашем случае я вижу 3-дерево. Это, если реализовано как 2-дерево с возможностью равенства, должно обходиться рекурсивно, но с проходом центральной ветки до упора. То есть, даже в ноде список не нужен, - достаточно хранить.
Node * left, * central, * right;.
То есть если меньше-> влево, если больше ->вправо и если равно -> по центру и до конца (тут от порождающего узла и до конца развилок уже быть не может). То есть выходы из рекурсии отличаются на один дополнительный случай.
Но если, количество детей произвольно (таки да список), то с трудом представляю себе как это может быть деревом поиска.
Bonttpol, вообще, если вам задают 3-деревья, то респект. Вы должны ориентироваться в 2-деревьях с балансировкой (как AVL BST так и красно-чёрное) лучше многих, кто уже и подзабыл как там и что.
0
4 / 4 / 0
Регистрация: 25.02.2019
Сообщений: 13
25.02.2019, 11:41  [ТС]
Вторая картинка - это просто визуализированный пример того как я понимаю реализацию дерева поиска "списком сыновей". Я даже не уверена верный ли он.
Я не знаю как мне заполнить структуру произвольного дерева и хранить его подобным списком на C++?
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
25.02.2019, 12:36
Цитата Сообщение от Bonttpol Посмотреть сообщение
Вторая картинка - это просто визуализированный пример того как я понимаю реализацию дерева поиска "списком сыновей". Я даже не уверена верный ли он.
Bonttpol, нарисовали красиво и это уже приятно. Однако, дайте-ка условие задания дословно. Понимаете, ваш второй рисунок наводит на мысли о хеш-массиве с реализацией на "цепочках" или как говорят золушки - "корзинках". Это таки структура, сочетающая произвольный доступ (к нужной корзинке) и последовательный (в пределах найденной корзинки). В общем, нужно бы определиться о чём тут речь.

Добавлено через 45 минут
Bonttpol, перечитав условие, я могу предположить, что речь идёт об 2-BST. Под хранением, - возможно, имеется ввиду сохранение данных в файл. Требуется создать 2 экземпляра в которых использовать разные методы обхода (итерации) для операций добавления и вывода в поток (в т.ч. и в файловый).
Если мои предположения верны, то задание запутывающе сформулировано. Последовательность хранения в файле названа списком, в то время как дополнительные списочные структуры (как и любые иные временные накопители) в памяти запрещены. Вы молчите и я пытаюсь догадаться, постарайтесь ответить. Тут главное вам понять задачу.
1
4 / 4 / 0
Регистрация: 25.02.2019
Сообщений: 13
25.02.2019, 12:41  [ТС]
Задание:
Пусть А, В, С – деревья соответствующего типа, узлы которых могут содержать целочисленные значения. Требуется реализовать начальное формирование деревьев А и В, путем добавления некоторой последовательности значений (узлов) в пустое дерево. После чего требуется по варианту реализовать заданную операцию над деревьями без использования каких-либо вспомогательных структур (списков, массивов и т.п.), работая только с узлами деревьев А и В.
Операция А=A ⋃пр B означает,что элементы дерева В будут добавлены в дерево А в прямом порядке обхода дерева В, соответственно А=A ⋃обр B – в обратном, а А=A ⋃сим B – симметричном обходе дерева В.
Мой вариант:
  • тип дерева - дерево двоичного поиска
  • реализация - список сыновей
  • операция - А = А Uобр В
  • вывод дерева на экран - А-прямой; В-симметричный

Подскажите, как можно реализовать "список сыновей" на С++?
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
25.02.2019, 13:19
Вот нашёл ссылочку:
http://bookwu.net/book_algorit... ya-derevev
Вкратце могу сказать, что вижу такое в первые и... грустное оно. Идея ущербна с моей точки зрения, хотя скорее всего я её просто не понимаю. Фактически данная структура позволяет иметь доступ к одним и тем же узлам из нескольких (независимых!) ячеек списка.
Суть в том, что все элементы заносятся в список. Вернее сказать - элементы списка содержащие пару указателей - один (ведущий) на узел дерева и один - на (ведомый) следующий узел. В списке присутствуют все узлы дерева в качестве ведущих . Каждый ведомый узел указывает на следующий нод в уровне следующем по отношению к ведущему в списке. Если таковых у нода дерева нет (лист) то в корневом списке у элемента с ведущим указателем на этот лист ведомый будет равен nullptr, то есть, грубо говоря - ноль. Это обозначено жирной точкой на схеме. То есть каждый ведомый указывает на следующий ведомый в этом же уровне слева-направо (в странах где читают и пишут слева направо) до конца. То есть последний в уровне тоже на ноль указывает.
Bonttpol, глядя на это я могу перефразировать известное:
Чем больше я узнаю математиков, тем больше люблю собак. (шутка, прошу математиков не обижаться. Тем более что все мы тут, включая и меня, грешного, немного того. Математики то есть. ).
1
4 / 4 / 0
Регистрация: 25.02.2019
Сообщений: 13
25.02.2019, 14:18  [ТС]
Получается мне нужно писать структуру дерева. Потом писать список-в-списке, который хранит в перовом списке указатели на этот узел дерева и следующий, а второй список последовательность указателей на потомков?
Миниатюры
Реализация дерева поиска список сыновей  
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
25.02.2019, 14:58
Лучший ответ Сообщение было отмечено Bonttpol как решение

Решение

Цитата Сообщение от Bonttpol Посмотреть сообщение
Получается мне нужно писать структуру дерева. Потом писать список-в-списке, который хранит в перовом списке указатели на этот узел дерева и следующий, а второй список последовательность указателей на потомков?
Не совсем понял это не те слова. Совсем не понял.
Bonttpol, можно использовать ноды вашего дерева. С точки зрения С++ это плохо (тоже мягко сказано), но задание есть задание.
Например (не пишу и не компилирую, поэтому примите как идею)
Вы создаёте std::list<Node> sones;
вставляете корневой нод.
создаёте пару итераторов std::list<Node>::iterator start_level, current_in_next_level;
Инициализируете оба началом списка (сейчас там 1 нод - корневой нод всего дерева)
Потом я бы организовал пару вложенных циклов. Наружный проходит по вставленным в предыдущем внутреннем. Внутренний на каждом вставляет в конец детей (если они есть) нодов полученных в наружном,
По завершении наружного - обновляем итераторы начала и конца (на уже новый вставленный участок) или выходим если кончились элементы в дереве (тут счетчика хватит).
Придётся чуток повозиться.
То есть, для заполнения списка вы используете предыдущий уже вставленный накануне участок. Начальный участок начала всего действа, как я уже сказал, - один нод, - корневой нод дерева.
Вроде красиво, но с моей точки зрения такая структура если её не защитить может принести дереву горе. Любая операция на дереве должна апдейтить список минимум в двух местах...
Для практики - вполне сгодится.

Добавлено через 9 минут
И да. Это будет только список с не заполненными под списками. Назовём его корневым. Потом когда вы его получите придётся идти по нему и к каждому ноду вешать гирлянду следующего от него (как родителя) уровня. Эти ноды не будут копиями нодов дерева так как связаны они линейно и не в том порядке. То есть, каждый такой подсписок - развёрнутый в линию детский уровень нода в списке корневого уровня.
1
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
28.02.2019, 23:24
Лучший ответ Сообщение было отмечено Bonttpol как решение

Решение

Bonttpol, вот дошли руки (шаловливые) до того чтобы написать как бы я сделал. Мотивом стало отсутствие в сети реализации списка сыновей на C++. Я не нашёл, во всяком разе.

Прошу не винить за реализацию дерева (там нет балансировки и всё очень примитивно). Я её нашёл в своих старых файлах и поскольку она что-то живое делает - использована для демонстрации. Если кто захочет переписать красиво - флаг в руки (булев).
Bonttpol, в источнике, что я дал используются т.н. курсоры (указатель-заменители). Попытка это прочесть не увенчалась успехом и я решил сделать по-своему. Вообще, подумав я решил, что использовать сами по себе ноды как переменные это плохо. Нельзя вешать гирлянды разрушая связность самого дерева. То есть, напрашивается указатель указателя на нод. Это трудно читаемо и поскольку список то всё едино придётся использовать (std::list не писать же самому список) то в качестве связующего звена (дополнительного уровня) я решил использовать всё тот же список но на самих указателях Node. То есть корневой - list<list<Node*>> , а внутренние list<Node*> - "гирлянды" уровней каждого нода в корневом списке. В итоге, как я и предлагал, можно заполнять список обращаясь только его уже вставленным элементам.
Пришлось пойти на святотатства вроде реализации конструктора копий для нода (чего не делают никогда), поэтому само дерево прошу не критиковать. Кто захочет - своё напишет.
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
#include <iostream>
#include <list>
using namespace std;
 
template<typename T> 
struct Node
{
T key;
Node *left_;
Node *right_;
Node *parent_;
Node *root_;
Node(const T& key_)
:key(key_), left_(nullptr), right_(nullptr)
{root_=this; parent_=this;}
Node(const T& key_, Node *root)
:key(key_), root_(root), left_(nullptr), right_(nullptr), parent_(nullptr)
{}
 
Node (const Node & rhs)
:key(rhs.key), root_(rhs.root_), left_(rhs.left_), right_(rhs.right_), parent_(rhs.parent_)
{}
 
void insert( Node *x,  Node *z){            // x — корень поддерева, z — вставляемый элемент
    
    while (x != nullptr){
     if (z->key >= x->key)
        if (x->right_ != nullptr)
           x = x->right_;
        else{
           z->parent_ = x;
           x->right_ = z;
           break;
        }
     else if (z->key < x->key)
        if (x->left_ != nullptr)
           x = x->left_;
        else{
           z->parent_ = x;
           x->left_ = z;
           break;
        }
    }
}
void add(Node *x, T key){
 
    if(root_==nullptr){
        root_=new Node(key);
root_->root_=this;
root_->parent_=this; 
    }
else
{
Node *y=new Node(key, root_);
 
insert( x, y );
}
}
void add(T key){
    if(root_==nullptr){ root_=new Node(key);
        root_->root_=this;
root_->parent_=this; 
    }
else{
Node *y=new Node(key, root_);
insert( root_, y );
}
}
void inorderTraversal(Node *x){
    if (x != nullptr){
      inorderTraversal(x->left_);
      cout << x->key<<' ';
      inorderTraversal(x->right_);
    }
}
 
void inorderTraversal(Node *x, list<list<Node *>>& lst){
    if (x != nullptr){
     inorderTraversal(x->left_, lst);      
     list<Node *> lint;
     lint.push_back(x);
     lst.push_back(lint);
     inorderTraversal(x->right_, lst);
    }
}
 
void 
get_next_level_nodes_list( 
    list<list<Node*>>& list_nodes_by_levels, int level=0    
        ){
    list<list<Node*>>::const_iterator it_begin =  list_nodes_by_levels.begin(), it_last =  list_nodes_by_levels.end();
    if(it_last == it_begin){
    cout<<"The tree is empty"<<endl;
    return;
    }
    it_last--;
    list<Node*> list_nodes_next_level;
    list<Node*>::const_iterator it=it_last->begin(), it_fin = it_last->end();
    cout<<level<<'\t';
    for(; it  != it_fin; ++it){
    cout<<(*it)->key<<' ';
    if((*it)->left_)
    list_nodes_next_level.push_back((*it)->left_);
    if((*it)->right_)
    list_nodes_next_level.push_back((*it)->right_);
    }
    cout<<endl;
    if(!list_nodes_next_level.empty()){
    list_nodes_by_levels.push_back(list_nodes_next_level);
    get_next_level_nodes_list( list_nodes_by_levels, ++level); 
    }
}
 
};
int main(int argc, char* argv[])
{
const int sz=7;
 
int a[sz]={2,6,1,3,5,7};
Node<int> *node_root=new Node<int>(4);
 
for(int i=0; i<sz-1; ++i)node_root->add(node_root, a[i] );
cout<<endl;
node_root->inorderTraversal(node_root);
cout<<endl;
cout<<"\nlevels of the tree:\n";
list<Node<int>*> list_nodes_next_level;
list_nodes_next_level.push_back(node_root->root_);
list<list<Node<int>*>> list_nodes_by_levels;
list_nodes_by_levels.push_back(list_nodes_next_level);
node_root->get_next_level_nodes_list(list_nodes_by_levels);
 
//вот ваше задание Bonttpol
typedef list<Node<int>*> level_lists;
 
list<level_lists> sones_list; 
cout<<"\nInorderTraversalNextNode\n";
list<level_lists> root_list;
node_root->inorderTraversal(node_root, root_list);
list<level_lists>::iterator root_list_it_ben = root_list.begin(), 
root_list_it_end = root_list.end();
for(;root_list_it_ben  != root_list_it_end ; ++root_list_it_ben){
Node<int> *nod=(*root_list_it_ben->begin());
cout << nod->key << ' ';
if(nod->left_)root_list_it_ben->push_back(nod->left_);
if(nod->right_)root_list_it_ben->push_back(nod->right_);
}
cout<<"\n\nSones list\n";
root_list_it_ben = root_list.begin();
cout<<endl;
for(;root_list_it_ben  != root_list_it_end ; ++root_list_it_ben){
    level_lists::iterator level_lists_beg=root_list_it_ben->begin(),
        level_lists_end=root_list_it_ben->end();
for(;level_lists_beg  != level_lists_end ; ++level_lists_beg){
Node<int> *nod=*level_lists_beg;
cout << nod->key << ' ';
}
cout<<endl;
}
 
cout<<endl;
system("pause");
return 0;
}
2
4 / 4 / 0
Регистрация: 25.02.2019
Сообщений: 13
01.03.2019, 13:50  [ТС]
Огромное спасибо. Только, почему то компилятор ругается на Ваш код. Мне пока починить не удалось.
Миниатюры
Реализация дерева поиска список сыновей  
0
4 / 4 / 0
Регистрация: 25.02.2019
Сообщений: 13
01.03.2019, 14:48  [ТС]
Цитата Сообщение от IGPIGP Посмотреть сообщение
Node *root_;
А это у Вас указатель на "текущий" узел?
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
01.03.2019, 16:40
Цитата Сообщение от Bonttpol Посмотреть сообщение
А это у Вас указатель на "текущий" узел?
Нет. Это указатель на корень. Вообще нод далеко не аскетичен (перегружен возможно, лишними данными).
Что касается ошибки то я посмотрел и выяснилось что на g++ это не компилится. Я пока не понял почему, но тупо заменил все
list<list<Node*>>::const_iterator
где сообщения о ошибке на auto и всё заработало. Вечером позже гляну, но может кто-то прольёт свет... Самому интересно, что ему не нравится.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
02.03.2019, 00:19
Bonttpol, методом тыка выяснил что можно так:
C++
1
2
3
4
5
6
7
    typedef Node* NodePtr;
    typedef list<NodePtr> NodePtrLst;
    typedef list<NodePtrLst> list_lists;
    typedef typename list_lists::iterator list_lists_it;//почему он без typename не может вывести тип - загадка для меня :D
    list_lists_it it_begin =  list_nodes_by_levels.begin();
    list_lists_it it_last =  list_nodes_by_levels.end();
    //auto it_begin =  list_nodes_by_levels.begin(), it_last =  list_nodes_by_levels.end();//так тоже работает
1
4 / 4 / 0
Регистрация: 25.02.2019
Сообщений: 13
05.03.2019, 09:17  [ТС]
IGPIGP, получается что Вы создаете стандартную структуру дерева, а в "список сыновей" , представленный массивом, записываете указатели на соответствующие узлы?
А можно ли после создания этого списка подчистить память и удаль дерево? Будут указатели после этого работать?
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
05.03.2019, 09:46
Цитата Сообщение от Bonttpol Посмотреть сообщение
IGPIGP, получается что Вы создаете стандартную структуру дерева, а в "список сыновей" , представленный массивом, записываете указатели на соответствующие узлы?
Bonttpol, "стандартная структура" как термин мне не знакома. Однако я рад вашему вопросу. Он обнаруживает хорошую работу вашей мысли.
Bonttpol, я не совсем понял, если честно, что такое
Цитата Сообщение от Bonttpol Посмотреть сообщение
"список сыновей"
Если смотреть по ссылке (которую я нашёл), то там узлы по уровням слева-направо расположены в порядке возрастания. В корневом списке списка сыновей тоже. Такое могло случиться по двум независящим причинам.
-Корневой список формировался суммированием уровней (а они сортированны в примере на сайте);
-Корневой список создан из сортированной последовательности узлов, независимо от их расположения по уровням.
Мне нравится 2-й вариант и вот почему. В случае если вы десериализуете дерево из потока, его конкретный вид будет зависеть от порядка следования данных. Это значит что на одном и том же наборе можно получать различные по составу уровней деревья. Тогда первый алгоритм будет "нестандартен" завися от конкретного размещения, а второй всегда будет один и тот же на заданном множестве данных.
В целом, это глубоко философский вопрос и имеет больше значение для вашей головы, чем для вашей лабы. С чисто практической точки зрения, имеет смысл спросить у преподавателя, что ему представляется целесообразным. И сделать именно так. Для разугреву можете с ним слегка подискутировать использую полученные и осмысленные знания. Ему будет приятно (надеюсь).
Вдобавок, хочу заметить, что сортированный корневой список созданный на базе массива вектора будет обладать логарифмическим временем поиска при использовании таких алгоритмов как lower_bound, что делает существование такого списка вполне осмысленным.

Цитата Сообщение от Bonttpol Посмотреть сообщение
А можно ли после создания этого списка подчистить память и удаль дерево? Будут указатели после этого работать?
Нельзя и не будут. На сайте сказано, что используются курсоры Paskal ввиду того, что указатели у них отсутствуют. Я это воспринял буквально.
Вначале я думал о возможности создания копии... но передумал. По выше озвученной причине. То есть, список - промежуточный уровень доступа к дереву (более высокого ранга). Без дерева он мёртв.
Bonttpol, если я не прав, то реализовать копию, Вам не составит труда, имея то что мы тут раскопали.
1
4 / 4 / 0
Регистрация: 25.02.2019
Сообщений: 13
05.03.2019, 10:04  [ТС]
Большое Вам спасибо
1
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
05.03.2019, 10:24
Цитата Сообщение от Bonttpol Посмотреть сообщение
Большое Вам спасибо
И Вам спасибо за хороший вопрос и осмысленное участие в теме.
0
4 / 4 / 0
Регистрация: 25.02.2019
Сообщений: 13
05.03.2019, 14:08  [ТС]
Я тут кое что переписала. И теперь мой список выглядит вот так:
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
#include "pch.h"
#include <iostream>
#include <list>
 
using namespace std;
 
template<typename T>
 
struct Node
{
    T key;
    Node *left_;
    Node *right_;
    Node *parent_;
    Node *root_;
 
    Node(const T& key_)
        :key(key_), left_(nullptr), right_(nullptr)
    {
        root_ = this; parent_ = this;
    }
    Node(const T& key_, Node *root)
        :key(key_), root_(root), left_(nullptr), right_(nullptr), parent_(nullptr)
    {}
 
    Node(const Node & rhs)
        :key(rhs.key), root_(rhs.root_), left_(rhs.left_), right_(rhs.right_), parent_(rhs.parent_)
    {}
 
    void insert(Node *x, Node *z) {            // x — корень поддерева, z — вставляемый элемент
 
        while (x != nullptr) {
            if (z->key >= x->key)
                if (x->right_ != nullptr)
                    x = x->right_;
                else {
                    z->parent_ = x;
                    x->right_ = z;
                    break;
                }
            else if (z->key < x->key)
                if (x->left_ != nullptr)
                    x = x->left_;
                else {
                    z->parent_ = x;
                    x->left_ = z;
                    break;
                }
        }
    }
    void add(Node *x, T key) {
 
        if (root_ == nullptr) {
            root_ = new Node(key);
            root_->root_ = this;
            root_->parent_ = this;
        }
        else
        {
            Node *y = new Node(key, root_);
 
            insert(x, y);
        }
    }
 
    void add(T key) {
        if (root_ == nullptr) {
            root_ = new Node(key);
            root_->root_ = this;
            root_->parent_ = this;
        }
        else {
            Node *y = new Node(key, root_);
            insert(root_, y);
        }
    }
 
    void inorderTraversal(Node *x) {
        if (x != nullptr) {
            inorderTraversal(x->left_);
            cout << x->key << ' ';
            inorderTraversal(x->right_);
        }
    }
 
    void preorderTraversal(Node *x) {
        if (x != nullptr) {
            cout << x->key << ' ';
            preorderTraversal(x->left_);
            preorderTraversal(x->right_);
        }
    }
 
    void postorderTraversal(Node *x) {      
        if (x != nullptr) {
            cout << x->key << ' ';
            postorderTraversal(x->left_);
            postorderTraversal(x->right_);
        }
    }
 
    void get_next_level_nodes_list(list<list<Node*>>& list_nodes_by_levels) {
        auto it_begin = list_nodes_by_levels.begin(), it_last = list_nodes_by_levels.end();
        if (it_last == it_begin) {
            cout << "The tree is empty" << endl;
            return;
        }
        it_last--;
        list<Node*> list_nodes_next_level;
        auto it = it_last->begin(), it_fin = it_last->end();
        for (; it != it_fin; ++it) {
            list<Node*> this_children;
            if ((*it)->left_)
            { 
                list_nodes_next_level.push_back((*it)->left_);
                this_children.push_back((*it)->left_);
            }
            if ((*it)->right_)
            {
                list_nodes_next_level.push_back((*it)->right_);
                this_children.push_back((*it)->right_);
            }
            list_nodes_by_levels.push_back(this_children);
            this_children.clear();
            get_next_level_nodes_list(list_nodes_by_levels);
        }
        cout << endl;
        if (!list_nodes_next_level.empty()) {
            get_next_level_nodes_list(list_nodes_by_levels);
        }
    }
};
 
int main(int argc, char* argv[])
{
    cout << "How match nodes: ";
    cin >> sz;
    int *a = new int[sz];
    cout << "Node's key: " << endl;
    for (int i = 0; i < sz; ++i) cin >> a[i];
 
    Node<int> *node_root = new Node<int>(a[0]);
 
    for (int i = 1; i < sz; ++i) node_root->add(node_root, a[i]);
    cout << endl << "Tree:" << endl;
    A_root->preorderTraversal(node_root);
    cout << endl;
    delete a;
 
    list<Node<int>*> list_nodes_next_level;
    list_nodes_next_level.push_back(node_root->root_);
    list<list<Node<int>*>> list_nodes_by_levels;
    list_nodes_by_levels.push_back(list_nodes_next_level);
    node_root->get_next_level_nodes_list(list_nodes_by_levels);
    list<list<Node<int>*>> list_node = list_nodes_by_levels;
    list_nodes_by_levels.clear();
 
    cout << endl;
    system("pause");
    return 0;
}
Миниатюры
Реализация дерева поиска список сыновей   Реализация дерева поиска список сыновей  
1
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
05.03.2019, 14:55
C++
1
2
3
4
5
6
7
8
9
10
11
12
    size_t sz;///////////////////////////////////////// надо объявить
    cout << "How match nodes: ";
    cin >> sz;
    int *a = new int[sz];
    cout << "Node's key: " << endl;
    for (int i = 0; i < sz; ++i) cin >> a[i];
 
    Node<int> *node_root = new Node<int>(a[0]);
 
    for (int i = 1; i < sz; ++i) node_root->add(node_root, a[i]);
    cout << endl << "Tree:" << endl;
    node_root->preorderTraversal(node_root);//////////////////////A_root
теперь выводит список. Но нужно список со списками вывести. На сайте это делается вертикально со списками уровня в горизонталь. Посмотрите ещё раз.
0
4 / 4 / 0
Регистрация: 25.02.2019
Сообщений: 13
05.03.2019, 15:40  [ТС]
Мне кажется что этого списка достаточно. На том сайте же все сводилось к списку из связный списков. Тогда нужно делать связи между сыновьями (под "->" имеется ввиду указатель на брата):
1 [2]->[3]
2 [4]->[5]
3 [3]->[6]
Скорее всего, это дополнительные указатели в структуре node. Боюсь, я это не потяну. А то что сейчас удалось реализовать я понимаю и могу объяснить.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
05.03.2019, 15:40
Помогаю со студенческими работами здесь

Деревья. Список сыновей
Здравствуйте. Я не понимаю зачем нужны деревья с использованием списка сыновей. Не понимаю как они реализовываются и где применяются....

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

Реализация бинарного дерева поиска
Есть код, Помогите найти ошибку. using System; namespace BinarySearchTree { public class Node { public...

Реализация двоичного дерева поиска
Вот, собственно, код: #ifndef DICTIONARY_H_INCLUDED #define DICTIONARY_H_INCLUDED #include &lt;string.h&gt; typedef struct...

Реализация дерева цифрового поиска
Собственное, цифровое дерево - это такое дерево, где каждая буква слова располагается на своём уровне. С помощью него можно осуществлять...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
http://iceja.net/ математические сервисы
iceja 20.01.2026
Обновила свой сайт http:/ / iceja. net/ , приделала Fast Fourier Transform экстраполяцию сигналов. Однако предсказывает далеко не каждый сигнал (см ограничения http:/ / iceja. net/ fourier/ docs ). Также. . .
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит переходные токи и напряжения на элементах схемы. . . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru