Gistrec

Template Tree

Dec 17th, 2020 (edited)
1,126
0
Never
1
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 19.29 KB | None | 0 0
  1. ////////////////////////////////////////// main.cpp //////////////////////////////////////////
  2. #include <iostream>
  3. #include <cassert>
  4. #include <string>
  5.  
  6. #include "Tree.hpp"
  7.  
  8. using KeyType = size_t;
  9. using ValueType = std::string;
  10. using TreeType = Tree<KeyType, ValueType>;
  11.  
  12. int main() {
  13.     TreeType tree;
  14.     tree.insert(5, "");
  15.     tree.insert(3, "");
  16.     tree.insert(6, "");
  17.     tree.insert(7, "");
  18.  
  19.     // Проверка удаления листа (не корня)
  20.     tree.erase(7);
  21.     assert(tree.size() == 3U);
  22.     assert((tree.keys() == std::vector<KeyType>{ 3, 5, 6 }));
  23.     assert(tree.balanceFactor() == 0);
  24.  
  25.     // Проверка удаления корня + проверка балансировки
  26.     tree.insert(7, "");
  27.     tree.erase(5);
  28.     assert(tree.size() == 3U);
  29.     assert((tree.keys() == std::vector<KeyType>{ 3, 6, 7 }));
  30.     assert(tree.balanceFactor() == 0);
  31.  
  32.     return 0;
  33. }
  34.  
  35. ////////////////////////////////////////// Tree.hpp //////////////////////////////////////////
  36. #pragma once
  37. #include <vector>
  38. #include <functional>
  39.  
  40. #include "TreeNode.hpp"
  41. #include "TreeForwardIterator.hpp"
  42. #include "TreeReverseIterator.hpp"
  43.  
  44.  
  45. //! Класс, реализующий бинарное дерево поиска
  46. //!
  47. //! @tparam KeyT       Тип ключа
  48. //! @tparam ValueT     Тип значения
  49. template <typename KeyT,
  50.           typename ValueT>
  51. class Tree {
  52. public:
  53.     using TreeNode = TreeNode<KeyT, ValueT>;
  54.     using ForwardIterator = TreeForwardIterator<TreeNode>;
  55.     using ReverseIterator = TreeReverseIterator<TreeNode>;
  56.  
  57.     //! Конструктор
  58.     Tree() = default;
  59.  
  60.     //! Конструктор копирования
  61.     //!
  62.     //! @param  other   Другой объект дерева
  63.     Tree(const Tree &other) {
  64.         using CopyFunctionT = std::function<TreeNode*(const TreeNode*)>;
  65.  
  66.         const CopyFunctionT copy = [&](const TreeNode* source) {
  67.             TreeNode* dist = new TreeNode(source->key, source->value);
  68.             if (source->left) {
  69.                 dist->left = copy(source->left);
  70.             }
  71.             if (source->right) {
  72.                 dist->right = copy(source->right);
  73.             }
  74.             return dist;
  75.         };
  76.         _root = copy(other._root);
  77.     }
  78.  
  79.     //! Деструктор
  80.     ~Tree() {
  81.         clearNode(_root);
  82.     }
  83.  
  84.     //! Размер дерева
  85.     //!
  86.     //! @return Количество нод в дереве
  87.     std::size_t size() const {
  88.         return _size;
  89.     }
  90.  
  91.     //! Отчистка дерева
  92.     void clear() {
  93.         clearNode(_root);
  94.         _root = nullptr;
  95.     }
  96.  
  97.     //! Проверка дерева на пустоту
  98.     bool empty() const {
  99.         return _size == 0;
  100.     }
  101.    
  102.     //! Доступ к данным по ключу.
  103.     //!
  104.     //! @param  key     Ключ элемента в дереве
  105.     //! @return         Значение элемента внутри дерева
  106.     ValueT& operator()(const KeyT& key) const {
  107.         TreeNode* node = _find(key, _root);
  108.         return node->value;
  109.     }
  110.  
  111.     //! Добавление элемента в дерево
  112.     //!
  113.     //! @param  key       Ключ
  114.     //! @param  value     Значение
  115.     void insert(const KeyT& key, const ValueT& value) {
  116.         TreeNode** indirect = &_root;  // Чтобы обобщить вставку
  117.         std::vector<TreeNode**> path;  //
  118.  
  119.         while (*indirect != nullptr) {
  120.             path.push_back(indirect);
  121.  
  122.             if ((*indirect)->key > key)
  123.                 indirect = &((*indirect)->left);
  124.             else
  125.                 indirect = &((*indirect)->right);
  126.         }
  127.  
  128.         *indirect = new TreeNode(key, value);
  129.         path.push_back(indirect);
  130.  
  131.         _balance(path);
  132.         _size++;
  133.     }
  134.  
  135.     //! Удаление элемента из дерева
  136.     //!
  137.     //! @param  key       Ключ
  138.     void erase(const KeyT& key) {
  139.         TreeNode** indirect = &_root;  // to generalize insertion
  140.         std::vector<TreeNode**> path;  // to update height values
  141.  
  142.         while (*indirect != nullptr && (*indirect)->key != key) {
  143.             path.push_back(indirect);
  144.  
  145.             if ((*indirect)->key > key)
  146.                 indirect = &((*indirect)->left);
  147.             else
  148.                 indirect = &((*indirect)->right);
  149.         }
  150.  
  151.         // В дереве нет ноды с таким ключем
  152.         if (*indirect == nullptr) {
  153.             throw std::runtime_error("Key doesn't exist");
  154.         } else {
  155.             path.push_back(indirect);
  156.         }
  157.  
  158.         std::size_t index = path.size();
  159.  
  160.         // Удаляемая нода является листом - нет поддеревьев
  161.         if ((*indirect)->left == nullptr || (*indirect)->right == nullptr) {
  162.             delete *indirect;  // Просто удаляем ноду
  163.             *indirect = nullptr;
  164.             path.pop_back();
  165.         } else if ((*indirect)->right == nullptr) {  // Существует только левое поддерево
  166.             TreeNode *remove = *indirect;
  167.  
  168.             (*indirect) = (*indirect)->left;
  169.             delete remove;
  170.  
  171.             path.pop_back();
  172.         } else {  // Существует только правое поддерево
  173.             TreeNode **successor = &((*indirect)->right);
  174.  
  175.             while ((*successor)->left != nullptr) {
  176.                 path.push_back(successor);
  177.                 successor = &((*successor)->left);
  178.             }
  179.  
  180.             if (*successor == (*indirect)->right) {
  181.                 (*successor)->left = (*indirect)->left;
  182.  
  183.                 TreeNode *toRemove = *indirect;
  184.                 *indirect = *successor;
  185.                 delete toRemove;
  186.             } else {
  187.                 TreeNode *tmp = *path.back();
  188.                 TreeNode *suc = *successor;
  189.  
  190.                 tmp->left = (*successor)->right;
  191.                 suc->left = (*indirect)->left;
  192.                 suc->right = (*indirect)->right;
  193.  
  194.                 delete *indirect;
  195.                 *indirect = suc;
  196.                 path[index] = &(suc->right);
  197.             }
  198.         }
  199.  
  200.         _balance(path);
  201.         _size--;
  202.     }
  203.  
  204.     //! Список ключей в дереве
  205.     std::vector<KeyT> keys() {
  206.         std::vector<KeyT> result;
  207.         for (auto it = begin(); it != end(); ++it) {
  208.              result.push_back(it->key);
  209.         }
  210.         return result;
  211.     }
  212.  
  213.     //! Доп. операция в варианте задания - определение критерия сбалансированности
  214.     int balanceFactor() const {
  215.         if (!_root) return 0;
  216.         return _root->balanceFactor();
  217.     }
  218.    
  219.     //! Получаем итератор на первый элемент в дереве
  220.     //!
  221.     //! @return Итератор, указывающий на первый элемент в дереве
  222.     ForwardIterator begin() {
  223.         return ForwardIterator(_root);
  224.     }
  225.  
  226.     //! Получаем обратный итератор на последний элемент в дереве
  227.     //!
  228.     //! @return Обратный итератор, указывающий на последний элемент в дереве
  229.     ReverseIterator rbegin() {
  230.         return ReverseIterator(_root);
  231.     }
  232.  
  233.     //! Получаем итератор, указывающий на элемент, после последнего
  234.     //!
  235.     //! @return Итератор, указывающий на элемент после последнего
  236.     ForwardIterator end() {
  237.         return ForwardIterator(nullptr);
  238.     }
  239.  
  240.     //! Получаем обратный итератор, указывающий на элемент, перед первым
  241.     //!
  242.     //! @return Обратный итератор, указывающий на элемент, перед первым
  243.     ReverseIterator rend() {
  244.         return ReverseIterator(nullptr);
  245.     }
  246.  
  247. private:
  248.     //! Рекурсивный поиск ноды по ключу
  249.     TreeNode* _find(const KeyT& key, TreeNode* node) const {
  250.         if (!node) {
  251.             return nullptr;
  252.         }
  253.         if (key == node->key) {
  254.             return node;
  255.         }
  256.         if (key < node->key) {
  257.             return _find(key, node->left);
  258.         } else {
  259.             return _find(key, node->right);
  260.         }
  261.     }
  262.  
  263.     //! Процедура балансировки дерева
  264.     //! https://github.com/KadirEmreOto/AVL-Tree
  265.     void _balance(std::vector<TreeNode **> path) {
  266.         // Начинаем балансировать с корня к листу
  267.         std::reverse(path.begin(), path.end());
  268.  
  269.         for (auto indirect : path) {
  270.             TreeNode* node = *indirect;
  271.             TreeNode* leftLeaf  = node->left;
  272.             TreeNode* rightLeaf = node->right;
  273.  
  274.             node->updateValues();
  275.  
  276.             if (node->balanceFactor() >= 2 || (leftLeaf && leftLeaf->balanceFactor() > 0)) { // left - left
  277.                 *indirect = (*indirect)->rotateR();
  278.             } else if (node->balanceFactor() >= 2) {  // left - right
  279.                 (*indirect)->left = (*indirect)->left->rotateL();
  280.                 *indirect = (*indirect)->rotateR();
  281.             } else if (node->balanceFactor() <= -2 || (rightLeaf && rightLeaf->balanceFactor() < 0)) { // right - right
  282.             } else if (node->balanceFactor() <= -2 || (rightLeaf && rightLeaf->balanceFactor() < 0)) { // right - right
  283.                 *indirect = (*indirect)->rotateL();
  284.             } else if (node->balanceFactor() <= -2) {  // right - left
  285.                 (*indirect)->right = ((*indirect)->right)->rotateR();
  286.                 *indirect = (*indirect)->rotateL();
  287.             }
  288.         }
  289.     }
  290.  
  291.     //! Удаляем поддерево
  292.     void clearNode(TreeNode* node) {
  293.         if (node->left)  clearNode(node->left);
  294.         if (node->right) clearNode(node->right);
  295.         delete node;
  296.     };
  297.  
  298. private:
  299.     TreeNode* _root = nullptr;
  300.     size_t    _size = 0;
  301. };
  302.  
  303. ////////////////////////////////////////// TreeForwardIterator.hpp //////////////////////////////////////////
  304. #pragma once
  305. #include <iterator>
  306. #include <stack>
  307.  
  308. // Article: inorder depth-first traversal
  309. // http://mike.eshva.ru/dev/obhod-binarnogo-dereva-s-pomoschyu-iteratora
  310. template <typename TreeNode>
  311. class TreeForwardIterator {
  312. public:
  313.     explicit TreeForwardIterator(TreeNode* root) : _node(root) {
  314.         if (!_node) return;
  315.  
  316.         _stack.push(nullptr);
  317.  
  318.         while (_node->left) {
  319.             _stack.push(_node);
  320.             _node = _node->left;
  321.         }
  322.     };
  323.  
  324.     bool operator==(const TreeForwardIterator& other) const {
  325.         // Равны, если оба итератора указывают на nullptr
  326.         if (!_node && !other._node) return true;
  327.  
  328.         // Не равны, если один из них nullptr
  329.         if ((!_node && other._node) || (_node && !other._node)) return false;
  330.  
  331.         // Равны, если указывают на одинаковый ключ (и значение?)
  332.         if (_node->key == other._node->key) return true;
  333.         return false;
  334.     }
  335.  
  336.     bool operator!=(const TreeForwardIterator& other) const {
  337.         return !operator==(other);
  338.     }
  339.  
  340.     TreeNode* operator->() {
  341.         if (!_node) {
  342.             throw std::runtime_error("Iterator not dereferenceable");
  343.         }
  344.         return _node;
  345.     }
  346.  
  347.     TreeForwardIterator& operator++() {
  348.         if (!_node) return *this;
  349.  
  350.         if (_node->right) {
  351.             _node = _node->right;
  352.             while (_node->left) {
  353.                 _stack.push(_node);
  354.                 _node = _node->left;
  355.             }
  356.         } else {
  357.             _node = _stack.top();
  358.             _stack.pop();
  359.         }
  360.  
  361.         return *this;
  362.     }
  363.  
  364. private:
  365.     std::stack<TreeNode*> _stack;
  366.     TreeNode* _node;
  367. };
  368.  
  369. ////////////////////////////////////////// TreeReverseIterator.hpp //////////////////////////////////////////
  370. #pragma once
  371. #include <iterator>
  372. #include <stack>
  373.  
  374. // Article: inorder depth-first traversal
  375. // http://mike.eshva.ru/dev/obhod-binarnogo-dereva-s-pomoschyu-iteratora
  376. template <typename TreeNode>
  377. class TreeReverseIterator {
  378. public:
  379.     explicit TreeReverseIterator(TreeNode* root) : _node(root) {
  380.         if (!_node) return;
  381.  
  382.         _stack.push(nullptr);
  383.  
  384.         while (_node->right) {
  385.             _stack.push(_node);
  386.             _node = _node->right;
  387.         }
  388.     };
  389.  
  390.     bool operator==(const TreeReverseIterator& other) const {
  391.         // Равны, если оба итератора указывают на nullptr
  392.         if (!_node && !other._node) return true;
  393.  
  394.         // Не равны, если один из них nullptr
  395.         if ((!_node && other._node) || (_node && !other._node)) return false;
  396.  
  397.         // Равны, если указывают на одинаковый ключ (и значение?)
  398.         if (_node->key == other._node->key) return true;
  399.         return false;
  400.     }
  401.  
  402.     bool operator!=(const TreeReverseIterator& other) const {
  403.         return !operator==(other);
  404.     }
  405.  
  406.     TreeNode* operator->() {
  407.         if (!_node) {
  408.             throw std::runtime_error("Iterator not dereferenceable");
  409.         }
  410.         return _node;
  411.     }
  412.  
  413.     TreeReverseIterator& operator++() {
  414.         if (!_node) return *this;
  415.  
  416.         if (_node->left) {
  417.             _node = _node->left;
  418.             while (_node->right) {
  419.                 _stack.push(_node);
  420.                 _node = _node->right;
  421.             }
  422.         } else {
  423.             _node = _stack.top();
  424.             _stack.pop();
  425.         }
  426.  
  427.         return *this;
  428.     }
  429.  
  430. private:
  431.     std::stack<TreeNode*> _stack;
  432.     TreeNode* _node;
  433. };
  434.  
  435. ////////////////////////////////////////// TreeNode.hpp //////////////////////////////////////////
  436. #pragma once
  437.  
  438.  
  439. //! Класс, реализующий узел бинарного дерева поиска
  440. //!
  441. //! @tparam KeyT       Тип ключа
  442. //! @tparam ValueT     Тип значения
  443. template <typename KeyT,
  444.           typename ValueT>
  445. struct TreeNode {
  446.     // Данные, хранящиеся в элементе
  447.     KeyT   key;
  448.     ValueT value;
  449.  
  450.     // Высота элемента
  451.     size_t height = 1;
  452.  
  453.     // Количество элементов в поддереве
  454.     size_t count = 1;
  455.  
  456.     // Указатель на дочерние элементы
  457.     TreeNode* left = nullptr;
  458.     TreeNode* right = nullptr;
  459.  
  460.     void updateValues() {
  461.         const auto leftCount  = (left  != nullptr) ? left->count  : 0;
  462.         const auto rightCount = (right != nullptr) ? right->count : 0;
  463.         count = leftCount + rightCount + 1;
  464.  
  465.         const auto leftHeight  = (left  != nullptr) ? left->height  : 0;
  466.         const auto rightHeight = (right != nullptr) ? right->height : 0;
  467.         height = leftHeight + rightHeight + 1;
  468.     }
  469.     int balanceFactor() const {
  470.         const auto leftHeight  = (left  != nullptr) ? left->height  : 0;
  471.         const auto rightHeight = (right != nullptr) ? right->height : 0;
  472.         return leftHeight - rightHeight;
  473.     }
  474.  
  475.     // Поворот дерева вокруг узла
  476.     TreeNode* rotateL() {
  477.         TreeNode* root = right; // Правый лист стал корнем
  478.         right = right->left;
  479.         root->left = this;
  480.  
  481.         this->updateValues();  // Порядок обновления важен
  482.         root->updateValues();
  483.  
  484.         return root;
  485.     }
  486.     TreeNode* rotateR() {
  487.         TreeNode* root = left; // Левый лист стал корнем
  488.         left = left->right;
  489.         root->right = this;
  490.  
  491.         this->updateValues();  // Порядок обновления важен
  492.         root->updateValues();
  493.  
  494.         return root;
  495.     }
  496.  
  497.     TreeNode(const KeyT& key, const ValueT& value)
  498.         : key(key), value(value) {}
  499. };
  500.  
  501. ////////////////////////////////////////// TemplateTreeTest.cpp //////////////////////////////////////////
  502. #include <CppUnitTest.h>
  503. #include "../TemplateTree/Tree.hpp"
  504.  
  505. #include <vector>
  506. #include <string>
  507. #include <numeric>
  508.  
  509. using namespace Microsoft::VisualStudio::CppUnitTestFramework;
  510.  
  511. template<> inline
  512. std::wstring Microsoft::VisualStudio::CppUnitTestFramework::ToString<std::vector<size_t>>(const std::vector<size_t>& vector) {
  513.     return std::accumulate(std::begin(vector), std::end(vector), std::wstring{},
  514.                            [](std::wstring &ss, const unsigned int &s) {
  515.                                return ss.empty() ? std::to_wstring(s) : ss + L"," + std::to_wstring(s);
  516.                            });
  517.  
  518. }
  519.  
  520. TEST_CLASS(TemplateTreeTest) {
  521. private:
  522.     using KeyType   = size_t;
  523.     using ValueType = std::string;
  524.     using TreeType  = Tree<KeyType, ValueType>;
  525.  
  526. public:
  527.     TEST_METHOD(SimpleTests) {
  528.         TreeType tree;
  529.         Assert::IsTrue(tree.size() == 0);
  530.         Assert::IsTrue(tree.balanceFactor() == 0);
  531.         Assert::IsTrue(tree.keys() == std::vector<KeyType>{});
  532.  
  533.         // Элемент добавился в корень дерева
  534.         tree.insert(5, "пять");
  535.         Assert::IsTrue(tree.size() == 1U);
  536.         Assert::IsTrue(tree.balanceFactor() == 0);
  537.         Assert::IsTrue(tree.keys() == std::vector<KeyType>{ 5 });
  538.  
  539.         // Элемент добавился в левый лист
  540.         tree.insert(3, "три");
  541.         Assert::IsTrue(tree.size() == 2U);
  542.         Assert::IsTrue(tree.balanceFactor() == 1);
  543.         Assert::IsTrue(tree.keys() == std::vector<KeyType>{ 3, 5 });
  544.  
  545.         // Элемент добавился в правый лист
  546.         tree.insert(6, "шесть");
  547.         Assert::IsTrue(tree.size() == 3U);
  548.         Assert::IsTrue(tree.balanceFactor() == 0);
  549.         Assert::IsTrue(tree.keys() == std::vector<KeyType>{ 3, 5, 6 });
  550.  
  551.         tree.insert(7, "семь");
  552.         Assert::IsTrue(tree.size() == 4U);
  553.         Assert::IsTrue(tree.balanceFactor() == -1);
  554.         Assert::IsTrue(tree.keys() == std::vector<KeyType>{ 3, 5, 6, 7 });
  555.     }
  556.  
  557.     TEST_METHOD(ReverseIteratorTest) {
  558.         TreeType tree;
  559.         tree.insert(5, "");
  560.         tree.insert(3, "");
  561.         tree.insert(6, "");
  562.         tree.insert(7, "");
  563.  
  564.         // Проверка обратного итератора
  565.         auto it = tree.rbegin();
  566.         Assert::IsTrue(it->key == 7U);
  567.         ++it;
  568.         Assert::IsTrue(it->key == 6U);
  569.         ++it;
  570.         Assert::IsTrue(it->key == 5U);
  571.         ++it;
  572.         Assert::IsTrue(it->key == 3U);
  573.         ++it;
  574.         Assert::IsTrue(it == tree.rend());
  575.     }
  576.  
  577.     TEST_METHOD(RemoveTest) {
  578.         TreeType tree;
  579.         tree.insert(5, "");
  580.         tree.insert(3, "");
  581.         tree.insert(6, "");
  582.         tree.insert(7, "");
  583.  
  584.         // Проверка удаления не вершины
  585.         tree.erase(7);
  586.         Assert::IsTrue(tree.size() == 3U);
  587.         Assert::IsTrue(tree.balanceFactor() == 0);
  588.         Assert::IsTrue(tree.keys() == std::vector<KeyType>{ 3, 5, 6 });
  589.  
  590.         // Проверка удаления вершины + проверка балансировки
  591.         tree.insert(7, "");
  592.         tree.erase(5);
  593.         Assert::IsTrue(tree.size() == 3U);
  594.         Assert::IsTrue(tree.balanceFactor() == 0);
  595.         Assert::IsTrue(tree.keys() == std::vector<KeyType>{ 3, 6, 7 });
  596.     }
  597. };
Advertisement
Comments
  • User was banned
Add Comment
Please, Sign In to add comment