Advertisement
paranid5

BTree

Jul 21st, 2020
207
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.20 KB | None | 0 0
  1. #ifndef BTREE_H
  2. #define BTREE_H
  3. #include <cstdlib>
  4.  
  5. template<typename T>
  6. class BTree
  7. {
  8. public:
  9.     BTree(const T&);
  10.  
  11.     void add(const T&);
  12.  
  13.     BTree* find(const T&);
  14.  
  15.     BTree* min_key();
  16.  
  17.     BTree* max_key();
  18.  
  19.     BTree* next();
  20.  
  21.     BTree* remove(const T&);
  22.  
  23. private:
  24.     T key_;
  25.     BTree* left_;
  26.     BTree* right_;
  27.     BTree* parent_;
  28. };
  29.  
  30.  
  31. /**
  32.  *____________________________________
  33.  *|                                   |
  34.  *| О СТРУКТУРЕ И КАК ЕЙ ПОЛЬЗОВАТЬСЯ |
  35.  *|___________________________________|
  36.  *
  37.  *-------------------------О СТРУКТУРЕ-------------------------------------
  38.  *
  39.  * Бинарное дерево - это структура данных,
  40.  * которая имеет корень, значение и две ветви - правую и левую,
  41.  * которые, в свою очередь, также хранят значения и две ветви.
  42.  * Ветви могут быть как пустыми, так и непустыми.
  43.  * Так же ветвь хранит ссылку на отцовскую ветвь,
  44.  * если та не является родителем (т.е. инициализированна через nullptr)
  45.  * Значение представленно универсальным типом const T,
  46.  * который может конвертироваться в любой машинный тип
  47.  *
  48.  * --------------ПРАВИЛА ХРАНЕНИЯ И ИСПОЛЬЗОВАНИЯ---------------------------
  49.  *
  50.  * В БИНАРНОМ ДЕРЕВЕ КЛЮЧИ ПРАВОГО ПОДДЕРЕВА БОЛЬШЕ КЛЮЧЕЙ ЛЕВОГО ПОДДЕРЕВА
  51.  * Это освновопологающее правило размещения в дереве. Рассмотрим его подробнее:
  52.  * Допустим, у нас есть ключ с неким значением и дерево (непустое)
  53.  * Мы будем идти вглубь дерева, и на каждом вхождении проверять ключи ветвей
  54.  * Если ключ меньше ключа ветви, то отправляемся в правую ветвь,
  55.  * иначе идём в левую ветвь. Так идём, пока не дойдём то конца всей корневой системы
  56.  * Когда дошли, то проверяем наш ключ и ключ ветви, выбираем нужную ветвь
  57.  * и определяем родителя для новой ветви по указателю, тем самым мы можем ходить по дереву
  58.  */
  59.  
  60.  //----------------------------------------------------------------------------
  61.  
  62.  /**
  63.   * Конструктор класса BTree
  64.   * @param key - ключ, по которому
  65.   * будет оcосуществляться доступ
  66.   * к ветвям дерева
  67.   */
  68. template<typename T>
  69. BTree<T>::BTree(const T& key)
  70. {
  71.     key_ = key;
  72.     parent_ = nullptr;
  73.     right_ = nullptr;
  74.     left_ = nullptr;
  75. }
  76.  
  77. //--------------------------------------------------------------------------
  78.  
  79. /**
  80.  * Метод add() добавляет новую ветвь в дерево
  81.  * в соответствии с правилами (см. выше)
  82.  * @param key - ключ новой ветви
  83.  */
  84.  
  85. template<typename T>
  86. void BTree<T>::add(const T& key)
  87. {
  88.     const auto new_node = new BTree(key);
  89.  
  90.     /**
  91.      * Создаём новую ветвь. Так как ветвь новая,
  92.      * То она не может содержать в себе другие ветви,
  93.      * А значит правая и левая ветвь инициализируется через nullptr
  94.      */
  95.  
  96.     BTree* root2 = this, * root3 = nullptr;
  97.  
  98.     /**
  99.      * root2 для поиска по дереву
  100.      * root3 для сохранения текущей позиции в дереве
  101.      */
  102.  
  103.     while (root2 != nullptr)
  104.     {
  105.         root3 = root2;
  106.         if (key < root2->key_) root2 = root2->left_;
  107.         else root2 = root2->right_;
  108.     }
  109.  
  110.     /**
  111.      * Углубляемся в дерево и ищем подходящий ключ
  112.      * Если key меньше ключа, то идём налево
  113.      * Иначе направо
  114.      */
  115.  
  116.     new_node->parent_ = root3;
  117.  
  118.     /**
  119.      * Сохранили указатель на родителя
  120.      * Для доступа и подъёма по дереву
  121.      */
  122.  
  123.     if (key < root3->key_) root3->left_ = new_node;
  124.     else root3->right_ = new_node;
  125.  
  126.     /**
  127.      * Выбираем подходящую ветвь:
  128.      * Если ключ меньше ключа ветви,
  129.      * то отправляемся в правую ветвь,
  130.      * иначе идём в левую ветвь.
  131.      */
  132.  
  133. }
  134.  
  135. //---------------------------------------------------------------
  136.  
  137. /**
  138.  * Метод find() ищет ближайшую от вершины ветвь,
  139.  * ключ которой соответствует @param key
  140.  * @return указатель на ветвь в случае успеха,
  141.  * иначе @return nullptr.
  142.  */
  143.  
  144. template<typename T>
  145. BTree<T>* BTree<T>::find(const T& key)
  146. {
  147.     // Начинаем поиск с вершины дерева
  148.  
  149.     auto root2 = this;
  150.  
  151.     /**
  152.     * Углубляемся в дерево (по правилам, описанным выше),
  153.     * пока не найдём ветвь с искомым ключом.
  154.     * Иначе возвращаем nullptr
  155.     */
  156.  
  157.     while (root2 != nullptr)
  158.     {
  159.         if (key < root2->key_) root2 = root2->left_;        // Если искомый ключ меньше, то идём в левую ветвь,
  160.         else if (key > root2->key_) root2 = root2->right_;  // Иначе если искомый ключ больше - в правую,
  161.         else return root2;                                  // Иначе нашли и возвращаем
  162.     }
  163.     return nullptr;                                         // Если не нашли, то возвращаем nullptr
  164. }
  165.  
  166. //-----------------------------------------------------------------
  167.  
  168. /**
  169.  * Метод min_key() ищет ветвь с минимальным ключом.
  170.  * Т.к. в дереве все наименьшие "элементы" расположены в левой части,
  171.  * то смело шагаем налево
  172.  */
  173.  
  174. template<typename T>
  175. BTree<T>* BTree<T>::min_key()
  176. {
  177.     auto min = this;
  178.  
  179.     /**
  180.     * Углубляемся в левую часть дерева,
  181.     * пока не дойдём до конца корневой системы
  182.     */
  183.  
  184.     while (min->left_ != nullptr) min = min->left_;
  185.  
  186.     return min;
  187. }
  188.  
  189. //-----------------------------------------------------------------
  190.  
  191. /**
  192.  * Метод max_key() ищет ветвь с максимальным ключом.
  193.  * Т.к. в дереве все наибольшие "элементы" расположены в правой части,
  194.  * то смело шагаем направо
  195.  */
  196.  
  197. template<typename T>
  198. BTree<T>* BTree<T>::max_key()
  199. {
  200.     auto max = this;
  201.  
  202.     /**
  203.      * Углубляемся в правую часть дерева,
  204.      * пока не дойдём до конца корневой системы
  205.      */
  206.  
  207.     while (max->right_ != nullptr) max = max->right_;
  208.  
  209.     return max;
  210. }
  211.  
  212. //-------------------------------------------------------------------
  213.  
  214. /**
  215.  * Метод next() ищет ветвь,
  216.  * значение которой является ближайшим и больше
  217.  * или равно текущему.
  218.  * @return найденную ветвь или nullptr
  219.  */
  220.  
  221. template<typename T>
  222. BTree<T>* BTree<T>::next()
  223. {
  224.     // Если есть правая ветка, то ищем минимальный элемент там
  225.  
  226.     if (this->right_ != nullptr)
  227.         return this->right_->min_key();
  228.  
  229.     // Правое дерево пусто, идем по родителям до тех пор,
  230.     // пока не найдем родителя, для которого наша ветка левая
  231.  
  232.     BTree* l = this->parent_; // ветка для поднятия
  233.     BTree* p = this;          // ветка для контроля значения
  234.  
  235.     while ((l != nullptr) && (p == l->right_))
  236.     {
  237.         p = l;
  238.         l = l->parent_;
  239.     }
  240.  
  241.     return l;
  242. }
  243.  
  244. //--------------------------------------------------------------------
  245.  
  246. /**
  247.  * Метод remove() очищает ветвь по @param key.
  248.  * Возможны 3 случая размещения удаляемой ветки:
  249.  *
  250.  * 1) Когда у ветви нет дочерних ветвей.
  251.  * В этом случае мы просто удаляем ветвь,
  252.  * предварительно обнулив её для родителей
  253.  *
  254.  * 2) Когда у ветви есть 1 дочерняя ветвь.
  255.  * В этом случае просто удаляем узел,
  256.  *  и на его место ставим дочернюю ветвь
  257.  *
  258.  * 3) Когда у ветви есть обе дочерние ветви.
  259.  * В этом случае ищем такую ветвь,
  260.  * что она будет следующей для текущей.
  261.  * Ставим этот узел на место удаляемой.
  262.  *
  263.  */
  264.  
  265. template<typename T>
  266. BTree<T>* BTree<T>::remove(const T& key)
  267. {
  268.     // Поиск удаляемого узла по ключу
  269.  
  270.     BTree* p = this, * l = nullptr, * m = nullptr;
  271.     l = p->find(key);
  272.  
  273.     // Если не нашли, то возвращаем nullptr
  274.  
  275.     if (l == nullptr) return nullptr;
  276.  
  277.     // 1 случай
  278.  
  279.     if ((l->left_ == nullptr) && (l->right_ == nullptr))
  280.     {
  281.         m = l->parent_;
  282.         if (l == m->right_) m->right_ = nullptr;
  283.         else m->left_ = nullptr;
  284.         delete l;
  285.     }
  286.  
  287.     // 2 случай, 1 вариант - поддерево справа
  288.  
  289.     if ((l->left_ == nullptr) && (l->right_ != nullptr))
  290.     {
  291.         m = l->parent_;
  292.         if (l == m->right_) m->right_ = l->right_;
  293.         else m->left_ = l->right_;
  294.         delete l;
  295.     }
  296.     // 2 случай, 2 вариант - поддерево слева
  297.     if ((l->left_ != nullptr) && (l->right_ == nullptr))
  298.     {
  299.         m = l->parent_;
  300.         if (l == m->right_) m->right_ = l->left_;
  301.         else m->left_ = l->left_;
  302.         delete l;
  303.     }
  304.     // 3 случай
  305.     if ((l->left_ != nullptr) && (l->right_ != nullptr))
  306.     {
  307.         m = l->next();
  308.         l->key_ = m->key_;
  309.         if (m->right_ == nullptr)
  310.             m->parent_->left_ = nullptr;
  311.         else m->parent_->left_ = m->right_;
  312.         delete m;
  313.     }
  314.     return this;
  315. }
  316.  
  317.  
  318. #endif // BTREE_H
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement