Открыть Электронные книги
Категории
Открыть Аудиокниги
Категории
Открыть Журналы
Категории
Открыть Документы
Категории
Москва 2021
Оглавление
2 Описание алгоритма.........................................................................................3
4 Результаты тестов.............................................................................................8
5 Руководство пользователя...............................................................................8
7 Заключение.....................................................................................................11
Список литературы............................................................................................12
Приложение.......................................................................................................13
2
1 Постановка задачи проекта
2 Описание алгоритма
3
2.1 Добавление элемента
4. Если родитель (р) существует, он может иметь двух или трех сыновей. Если
сыновей было 2, то новый узел подсоединяется к родителю (р) таким
образом, чтобы все сыновья расположились в порядке возрастания значений.
Обновляются ключи.
5. В случае, когда в узел – родитель (р) имеет 3-х сыновей, этот узел
разделяется на два узла – родителя. Вводимый узел с элементом Х и уже
имеющиеся три узла – сыны распределяются между новообразованными
узлами – родителями (Рис.2).
4
Рис.2. Если у родителя (р) уже есть 3 сына.
5
2.3 Удаление элемента
6
Рис.4. Пример случая описанного в пункте 4.2.
7
3 Структура данных для хранения дерева
5 Результаты тестов
8
600000
500000
400000
300000
200000
100000
0
0 200000 400000 600000 800000 1000000 1200000
6 Руководство пользователя
11
7 Руководство системного программиста
8 Заключение
12
Список литературы
13
Приложение
Файл tree.h
/**
\file tree.h
\brief Класс описывающий дерево
\author Сухоставский С.О.
\date 20.05.2021
*/
#ifndef TREE_H_INCLUDED
#define TREE_H_INCLUDED
#include <iostream>
#include <fstream>
#include <vector>
class Tree
{
public:
///конструктор
Tree()
{
root=NULL;
length=0;
leaf_count=0;
}
///деструктор
~Tree()
{
if(root!=NULL)
{
root=delete_all_children(root);
leaf_count=0;
}
}
14
}
else
{
return false;
}
}
root->setData(leaf_data);
root->setKey(leaf_data,0);
root->setKey(leaf_data,1);
leaf_count++;
length++;
}
///если дерево не пусто
else
{
///создаем новый узел
Node *new_node = new Node(NULL);
new_node->setData(leaf_data);
new_node->setKey(leaf_data,0);
new_node->setKey(leaf_data,1);
leaf_count++;
length++;
15
else
{
try_add_LSon(new_root,new_node);
try_add_MSon(new_root,root);
}
root=new_root;
update_keys(root);
}
///когда родитель существует
else
{
///если добавить новый узел к родительскому не получилось
if(!try_add_to_node(parent_node,new_node))
{
///вызываем метод который добавляет узел при этом перестраивая дерево
fix_tree(parent_node,new_node);
}
///если элемент получилось добавить обновляем ключи
else
{
update_keys(parent_node);
}
}
}
16
}
private:
Node* root; ///указатель на корневой элемент
int length; ///каличество всех узлов дерева
int leaf_count;///каличество всех листовых вершин дерева
17
delete_node(deleted_node);
Node* old_root=root;
root=root->getLChild();
root->setParent(NULL);
delete old_root;
length--;
}
///когда родитель не корень
else
{
///создаем указатель на братский узел для родительского узла
Node* DeleteNodePerent_Brother=get_nearestBrother(DeleteNodePerent);
18
///возвращает указатель на братский узел
Node* get_nearestBrother(Node* node)
{
///если текущий узел - это левый сын возвращаем среднего сына
if(node->getParent()->getLChild()==node)
{
return node->getParent()->getMChild();
}
///если текущий узел - это средний сын возвращаем левого сына
else if(node->getParent()->getMChild()==node)
{
return node->getParent()->getLChild();
}
///если текущий узел - это правый сын возвращаем среднего сына
else
{
return node->getParent()->getMChild();
}
}
///разделяем сыновей родительского узла и новый узел между пустым узлом и родителем
split_sons(fix_node,parent_node,new_node);
///если родитель- это корень, создаем новый корень к нему подвешиваем родителя и пустой узел
if(isRoot(parent_node))
{
Node* new_root = new Node(NULL);
length++;
new_root->setLChild(fix_node);
fix_node->setParent(new_root);
new_root->setMChild(root);
root->setParent(new_root);
root=new_root;
update_keys(root);
}
///если родитель не корень
else
{
///если родитель родительского узла имеет 2 сына, подвешиваем пустой узел к нему
if(parent_node->getParent()->getSonsCount()<3)
{
///если пустой самый маленький, вешаем его левым сыном
if(fix_node->getKey(1)<=parent_node->getParent()->getKey(0))
{
try_add_LSon(parent_node->getParent(),fix_node);
}
///если он меньше среднего, вещаем его средним
else if(fix_node->getKey(1)<=parent_node->getParent()->getKey(1))
{
try_add_MSon(parent_node->getParent(),fix_node);
}
///если самый большой, вешаем правым
else
{
19
try_add_RSon(parent_node->getParent(),fix_node);
}
///обновляем ключи
update_keys(parent_node->getParent());
}
///если родитель родительского узла имеет 3 сына
else
{
///рекурсивно вызываем этот метод для добавления пустого узла к родителю родительского
fix_tree(parent_node->getParent(),fix_node);
}
}
///получает на вход пустой узел, родительский узел и новый узел(который добавляется в дерево)
///распределяет новый узел и детей родительского узла между родительским узлом и пустым узлом
///fix_node - пустой узел
///parent_node -родительский узел
///new_node - новый узел
void split_sons(Node* fix_node,Node* parent_node,Node* new_node)
{
///если новый узел самый маленький, он становится левым сыном пустого узла
if(new_node->getKey(1)<=parent_node->getKey(0))
{
fix_node->setLChild(new_node);
new_node->setParent(fix_node);
fix_node->setMChild(parent_node->getLChild());
parent_node->getLChild()->setParent(fix_node);
update_localNode_keys(fix_node);
parent_node->setLChild(parent_node->getMChild());
parent_node->setMChild(parent_node->getRChild());
delete_RSon(parent_node);
update_keys(parent_node);
}
///если новый узел меньше среднего сына родительского узла,
///он становится средним сыном пустого узла
else if(new_node->getKey(1)<=parent_node->getKey(1))
{
fix_node->setLChild(parent_node->getLChild());
parent_node->getLChild()->setParent(fix_node);
fix_node->setMChild(new_node);
new_node->setParent(fix_node);
update_localNode_keys(fix_node);
parent_node->setLChild(parent_node->getMChild());
parent_node->setMChild(parent_node->getRChild());
delete_RSon(parent_node);
update_keys(parent_node);
}
///если новый узел меньше правого сына родительского узла,
///он становится левым сыном родительского узла
else if(new_node->getKey(1)<=find_max_child(parent_node->getRChild()))
{
fix_node->setLChild(parent_node->getLChild());
parent_node->getLChild()->setParent(fix_node);
20
fix_node->setMChild(parent_node->getMChild());
parent_node->getMChild()->setParent(fix_node);
update_localNode_keys(fix_node);
parent_node->setLChild(new_node);
new_node->setParent(parent_node);
parent_node->setMChild(parent_node->getRChild());
delete_RSon(parent_node);
update_keys(parent_node);
}
///если новый узел больше правого сына родительского узла,
///он становится средним сыном родительского узла
else
{
fix_node->setLChild(parent_node->getLChild());
parent_node->getLChild()->setParent(fix_node);
fix_node->setMChild(parent_node->getMChild());
parent_node->getMChild()->setParent(fix_node);
update_localNode_keys(fix_node);
parent_node->setLChild(parent_node->getRChild());
parent_node->setMChild(new_node);
new_node->setParent(parent_node);
delete_RSon(parent_node);
update_keys(parent_node);
21
///если существует левый сын, печатаем его поддерево
if(start_node->getLChild()!=NULL)
{
print(start_node->getLChild(),output);
}
///если существует средний сын, печатаем его поддерево
if(start_node->getMChild()!=NULL)
{
print(start_node->getMChild(),output);
}
///если существует правый сын, печатаем его поддерево
if(start_node->getRChild()!=NULL)
{
print(start_node->getRChild(),output);
}
}
22
Node* find_where_add(Node* start_node,long add_data)
{
///если текущий узел лист, возвращаем его родителя
if(start_node->isLeaf())
{
return start_node->getParent();
}
///если значение add_data меньше первого ключа ищем в левом сыне
if(add_data <= start_node->getKey(0))
{
start_node=start_node->getLChild();
return find_where_add (start_node,add_data);
}
///если значение add_data меньше второго ключа ищем в среднем сыне
if(add_data <= start_node->getKey(1))
{
start_node=start_node->getMChild();
return find_where_add (start_node,add_data);
}
///если значение add_data больше второго ключа ищем в правом сыне
else
{
///если правый сын не существует
if(start_node->getRChild()==NULL)
{
///если дети данного узла являются листьями, возвращаем этот узел
if(start_node->getLChild()->isLeaf())
{
return start_node;
}
///если дети не листья, ищем в среднем сыне
else
{
start_node=start_node->getMChild();
return find_where_add (start_node,add_data);
}
}
///если правый сын существует, ищем в нем
else
{
start_node=start_node->getRChild();
return find_where_add (start_node,add_data);
}
}
23
///если текущий узел правый сын, удаляем его у родителя
else
{
d_node->getParent()->setRChild(NULL);
}
update_localNode_keys(d_node->getParent());
///если удаляемый узел - лист, уменьшаем количество листовых вершин
if(d_node->isLeaf())
{
leaf_count--;
}
delete d_node;
d_node=NULL;
length--;
///возвращает true, если удалось добавить узел leaf к узлу node. Иначе false
bool try_add_to_node(Node* node, Node* leaf)
{
///если добавляемый меньше левого сына, пытаемся сделать его левым сыном
if(leaf->getKey(1)<=node->getKey(0))
{
return try_add_LSon(node,leaf);
}
///если добавляемый узел меньше среднего, пытаемся сделать его средним сыном
if(leaf->getKey(1)<=node->getKey(1))
{
return try_add_MSon(node,leaf);
}
///иначе, пытаемся сделать его правым сыном
else
{
return try_add_RSon(node,leaf);
}
}
parent_node->setLChild(son_node);
son_node->setParent(parent_node);
return true;
}
///если детей 3, операцию выполнить не возможно
else
{
24
return false;
}
}
25
{
return find_max_child(start_node->getMChild());
}
///иначе, ищем в левом сыне
else
{
return find_max_child(start_node->getLChild());
}
}
}
}
///рекурсивно заполняет входной массив значениями листовых узлов в поддереве узла start_node
void get_all_tree_data(vector<long>& data_array,Node* start_node)
{
///если существует левый сын, ищем значения в его поддереве
if(start_node->getLChild()!=NULL)
26
{
get_all_tree_data(data_array,start_node->getLChild());
}
///если существует средний сын, ищем значения в его поддереве
if(start_node->getMChild()!=NULL)
{
get_all_tree_data(data_array,start_node->getMChild());
}
///если существует правый сын, ищем значения в его поддереве
if(start_node->getRChild()!=NULL)
{
get_all_tree_data(data_array,start_node->getRChild());
}
///если узел - лист
else
{
///если есть данные, записываем их в массив
if(start_node->getData()!=-1)
{
data_array.push_back(start_node->getData());
}
}
27
///удаляет правого сына
void delete_RSon(Node* parent_node)
{
parent_node->setRChild(NULL);
}
};
#endif // TREE_H_INCLUDED
28