zoukankan      html  css  js  c++  java
  • 二叉树之二叉搜索树(BSTree)

    二叉搜索树(Binary Search Tree)

      引用:https://www.cnblogs.com/skywang12345/

      详解以后再补充。。。

      代码含注释,下面是输出效果(msys2)

    代码

    开发环境:Qt Creator 4.8.2  Mingw64 7.3  windows 8.1

    完整代码:https://github.com/Duacai/Data-Structure-and-Algorithms/tree/master/Data-Structure/Tree/BSTree

    BSTree.h

      1 #ifndef BSTREE_H
      2 #define BSTREE_H
      3 
      4 #include <iostream>
      5 #include <queue>
      6 
      7 using namespace std;
      8 
      9 namespace Viclib
     10 {
     11 
     12 template < typename T >
     13 class BSTNode
     14 {
     15 public:
     16     T mKey;
     17     BSTNode<T>    *mLeft;
     18     BSTNode<T>    *mRight;
     19     BSTNode<T>    *mParent;
     20 
     21     BSTNode() = delete;
     22     BSTNode(const T& key, BSTNode<T> *left, BSTNode<T> *right, BSTNode<T> *parent);
     23     BSTNode(const BSTNode<T>& tree) = delete;
     24     BSTNode(BSTNode<T> && tree);
     25     BSTNode<T>& operator = (const BSTNode<T>& tree) = delete;
     26     BSTNode<T>& operator = (BSTNode<T> && tree);
     27     virtual ~BSTNode();
     28 };
     29 
     30 template < typename T >
     31 BSTNode<T>::BSTNode(const T& key, BSTNode<T> *left, BSTNode<T> *right, BSTNode<T> *parent) :
     32     mKey(key), mLeft(left), mRight(right), mParent(parent)
     33 {
     34 }
     35 
     36 template < typename T >
     37 BSTNode<T>::BSTNode(BSTNode<T> && tree)
     38 {
     39     mLeft = tree.mLeft;
     40     mRight = tree.mRight;
     41     mParent = tree.mParent;
     42 
     43     tree->mLeft = nullptr;
     44     tree->mRight = nullptr;
     45     tree->mParent = nullptr;
     46 }
     47 
     48 template < typename T >
     49 BSTNode<T>& BSTNode<T>::operator = (BSTNode<T> && tree)
     50 {
     51     if ( this == &tree )
     52         return *this;
     53     
     54     delete mLeft;
     55     delete mRight;
     56     delete mParent;
     57     
     58     mLeft = tree->mLeft;
     59     mRight = tree->mRight;
     60     mParent = tree->mParent;
     61 
     62     return *this;
     63 }
     64 
     65 template < typename T >
     66 BSTNode<T>::~BSTNode()
     67 {
     68 }
     69 
     70 template < typename T >
     71 class BSTree
     72 {
     73 protected:
     74     BSTNode<T>* mRoot;
     75     size_t mCount;
     76 
     77     virtual void preOrder(BSTNode<T> *tree) const;                                // 深度优先的前、中、后序遍历
     78     virtual void inOrder(BSTNode<T> *tree) const;
     79     virtual void postOrder(BSTNode<T> *tree) const;
     80 
     81     virtual void levelOrder(BSTNode<T> *tree) const;                            // 广度优先
     82 
     83     virtual BSTNode<T>* search(BSTNode<T> *tree, const T& key) const;            // 递归版搜索
     84     virtual BSTNode<T>* iterativeSearch(BSTNode<T> *tree, const T& key) const;    // 非递归版搜索
     85 
     86     virtual BSTNode<T>* minimum(BSTNode<T> *tree) const;                        // 获取最小最大值
     87     virtual BSTNode<T>* maximum(BSTNode<T> *tree) const;
     88 
     89     virtual BSTNode<T>* successor(BSTNode<T> *node) const;                        // 查找后继,即大于又最接近node的节点
     90     virtual BSTNode<T>* predecessor(BSTNode<T> *node) const;                    // 查找前继
     91 
     92     virtual void insert(BSTNode<T> *node);
     93     virtual BSTNode<T>* remove(BSTNode<T> *node);                                // 返回值用于删除,返回值实际是替换结点
     94     virtual void destroy(BSTNode<T> *tree);
     95 
     96     void printTree(BSTNode<T> *tree, bool firstNode) const;                        // 打印树,类似linux的tree命令
     97 
     98     virtual int height(BSTNode<T> *tree) const;                                    // 树的高度
     99     virtual int degree(BSTNode<T> *tree) const;                                    // 结点的度数
    100 
    101 public:
    102     BSTree();
    103     BSTree(const BSTree<T>&) = default;
    104     BSTree(BSTree<T> &&) = default;
    105     BSTree<T>& operator = (const BSTree<T>&) = default;
    106     BSTree<T>& operator = (BSTree<T> &&) = default;
    107     virtual ~BSTree();
    108 
    109     virtual void preOrder() const;
    110     virtual void inOrder() const;
    111     virtual void postOrder() const;
    112 
    113     virtual void levelOrder() const;
    114 
    115     virtual BSTNode<T>* search(const T& key) const;
    116     virtual BSTNode<T>* iterativeSearch(const T& key) const;
    117 
    118     virtual const T& minimum() const;
    119     virtual const T& maximum() const;
    120 
    121     virtual void insert(const T& key);
    122     virtual void remove(const T& key);
    123     virtual void destroy();
    124 
    125     virtual int height() const;
    126     virtual int degree() const;
    127 
    128     virtual size_t getCount() const;
    129 
    130     virtual const T& getRootKey() const;
    131     virtual void printTree() const;
    132 };
    133 
    134 template < typename T >
    135 BSTree<T>::BSTree() : mRoot(nullptr), mCount(0)
    136 {
    137 }
    138 
    139 template < typename T >
    140 void BSTree<T>::preOrder(BSTNode<T> *tree) const
    141 {
    142     if ( tree != nullptr )
    143     {
    144         cout << tree->mKey << " " << flush;
    145         preOrder(tree->mLeft);
    146         preOrder(tree->mRight);
    147     }
    148 }
    149 
    150 template < typename T >
    151 void BSTree<T>::preOrder() const
    152 {
    153     preOrder(dynamic_cast<BSTNode<T>*>(this->mRoot));
    154 }
    155 
    156 template < typename T >
    157 void BSTree<T>::inOrder(BSTNode<T> *tree) const
    158 {
    159     if ( tree != nullptr )
    160     {
    161         inOrder(tree->mLeft);
    162         cout << tree->mKey << " " << flush;
    163         inOrder(tree->mRight);
    164     }
    165 }
    166 
    167 template < typename T >
    168 void BSTree<T>::inOrder() const
    169 {
    170     inOrder(dynamic_cast<BSTNode<T>*>(this->mRoot));
    171 }
    172 
    173 template < typename T >
    174 void BSTree<T>::postOrder(BSTNode<T> *tree) const
    175 {
    176     if ( tree != nullptr )
    177     {
    178         postOrder(tree->mLeft);
    179         postOrder(tree->mRight);
    180         cout << tree->mKey << " " << flush;
    181     }
    182 }
    183 
    184 template < typename T >
    185 void BSTree<T>::postOrder() const
    186 {
    187     postOrder(dynamic_cast<BSTNode<T>*>(this->mRoot));
    188 }
    189 
    190 template < typename T >
    191 void BSTree<T>::levelOrder(BSTNode<T> *tree) const
    192 {
    193     if ( tree != nullptr )
    194     {
    195         queue<BSTNode<T>*> tmp;
    196         tmp.push(tree);
    197 
    198         while( tmp.size() > 0 )
    199         {
    200             BSTNode<T>* t = tmp.front();
    201             tmp.pop();
    202 
    203             if ( t->mLeft != nullptr )
    204                 tmp.push(t->mLeft);
    205 
    206             if ( t->mRight != nullptr )
    207                 tmp.push(t->mRight);
    208 
    209             cout << t->mKey << " " << flush;
    210         }
    211     }
    212 }
    213 
    214 template < typename T >
    215 void BSTree<T>::levelOrder() const
    216 {
    217     levelOrder(dynamic_cast<BSTNode<T>*>(this->mRoot));
    218 }
    219 
    220 template < typename T >
    221 BSTNode<T>* BSTree<T>::search(BSTNode<T> *node, const T& key) const
    222 {
    223     if ( node == nullptr || node->mKey == key )
    224     {
    225         return node;
    226     }
    227     else if ( key < node->mKey )
    228         return search(dynamic_cast<BSTNode<T>*>(node)->mLeft, key);
    229     else
    230         return search(dynamic_cast<BSTNode<T>*>(node)->mRight, key);
    231 }
    232 
    233 template < typename T >
    234 BSTNode<T>* BSTree<T>::search(const T& key) const
    235 {
    236     return search(dynamic_cast<BSTNode<T>*>(this->mRoot), key);
    237 }
    238 
    239 template < typename T >
    240 BSTNode<T>* BSTree<T>::iterativeSearch(BSTNode<T>* node, const T& key) const
    241 {
    242     while ( (node != nullptr) && (node->mKey != key) )
    243     {
    244         if ( key < node->mKey )
    245             node = node->mLeft;
    246         else
    247             node = node->mRight;
    248     }
    249 
    250     return node;
    251 }
    252 
    253 template < typename T >
    254 BSTNode<T>* BSTree<T>::iterativeSearch(const T& value) const
    255 {
    256     return iterativeSearch(dynamic_cast<BSTNode<T>*>(this->mRoot), value);
    257 }
    258 
    259 template < typename T >
    260 BSTNode<T>* BSTree<T>::minimum(BSTNode<T>* tree) const
    261 {
    262     if ( tree == nullptr )
    263         return nullptr;
    264 
    265     while ( tree->mLeft != nullptr )
    266         tree = tree->mLeft;
    267 
    268     return tree;
    269 }
    270 
    271 template < typename T >
    272 const T& BSTree<T>::minimum() const
    273 {
    274     BSTNode<T> *p = minimum(dynamic_cast<BSTNode<T>*>(this->mRoot));
    275 //    if ( p == nullptr )
    276 //        THROW_EXCEPTION(EmptyTreeException, "The tree is empty ...");
    277 
    278     return p->mKey;
    279 }
    280 
    281 template < typename T >
    282 BSTNode<T>* BSTree<T>::maximum(BSTNode<T>* tree) const
    283 {
    284     if ( tree == nullptr )
    285         return nullptr;
    286 
    287     while ( tree->mRight != nullptr )
    288         tree = tree->mRight;
    289 
    290     return tree;
    291 }
    292 
    293 template < typename T >
    294 const T& BSTree<T>::maximum() const
    295 {
    296     BSTNode<T> *p = maximum(dynamic_cast<BSTNode<T>*>(this->mRoot));
    297 //    if ( p == nullptr )
    298 //        THROW_EXCEPTION(EmptyTreeException, "The tree is empty ...");
    299 
    300     return p->mKey;
    301 }
    302 
    303 template < typename T >
    304 BSTNode<T>* BSTree<T>::successor(BSTNode<T> *node) const    // 查找后继
    305 {
    306     if ( node->mRight != nullptr )                            // 如果node有右孩子,则在它的右孩子里面最小的是后继
    307     {
    308         return minimum(node->mRight);
    309     }
    310 
    311     BSTNode<T>* ret = node->mParent;                        // 如果node没有右孩子,且它自身是左孩子,则它的父亲是后继
    312     while ( (ret != nullptr) && (node == ret->mRight) )        // 如果node没有右孩子,且它自身是右孩子,它的最近祖先是左孩子的,则这个祖先的父亲就是后继
    313     {
    314         node = ret;
    315         ret = ret->mParent;
    316     }
    317 
    318     return ret;
    319 }
    320 
    321 template < typename T >
    322 BSTNode<T>* BSTree<T>::predecessor(BSTNode<T>* node) const    // 查找前继
    323 {
    324     if ( node->mLeft != nullptr )                            // 如果node有左孩子,则在它的左孩子里面最大的是前继
    325         return maximum(node->mLeft);
    326 
    327     BSTNode<T>* ret = node->mParent;                        // 如果node没有左孩子,且它自身是右孩子,则它的父亲是后继
    328     while ( (ret != nullptr) && (node == ret->mLeft) )        // 如果node没有左孩子,且它自身是左孩子,它的最近祖先是右孩子的,则这个祖先的父亲就是后继
    329     {
    330         node = ret;
    331         ret = ret->mLeft;
    332     }
    333 
    334     return ret;
    335 }
    336 
    337 template < typename T >
    338 void BSTree<T>::insert(BSTNode<T>* node)
    339 {
    340     BSTNode<T>* in = nullptr;                // 插入点
    341     BSTNode<T>* parent = dynamic_cast<BSTNode<T>*>(this->mRoot);        // 插入点的父节点
    342 
    343     while ( parent != nullptr )                // 查找node的插入点
    344     {
    345         in = parent;
    346         if ( node->mKey < in->mKey )        // 如果node结点小于插入点,则插入到左孩子分支
    347             parent = parent->mLeft;
    348         else if ( node->mKey > in->mKey )    // 如果node结点大于插入点,则插入到右孩子分支
    349             parent = parent->mRight;
    350         else                                // 如果数据等同则跳出
    351             break;
    352     }
    353 
    354     node->mParent = in;                    // 设置node结点的父亲为插入点
    355     if ( in == nullptr )                // 如果插入点为空,设node结点为根节点
    356         this->mRoot = node;
    357     else if ( node->mKey < in->mKey )    // 如果node结点小于插入点,插入左边
    358         in->mLeft = node;
    359     else if ( node->mKey > in->mKey )    // 如果node结点大于插入点,插入右边
    360         in->mRight = node;
    361     else                                // 如果数据等同则直接替换并释放插入的结点
    362     {
    363         in->mKey = node->mKey;
    364         delete node;
    365         return;
    366     }
    367 
    368     ++this->mCount;                        // 结点统计,注意重复结点插入时不能增加
    369 }
    370 
    371 template < typename T >
    372 void BSTree<T>::insert(const T& key)
    373 {
    374     insert(new BSTNode<T>(key, nullptr, nullptr, nullptr));
    375 }
    376 
    377 template < typename T >
    378 BSTNode<T>* BSTree<T>::remove(BSTNode<T> *node)
    379 {
    380     BSTNode<T>* replace = nullptr;            // 代替结点
    381     BSTNode<T>* del = nullptr;                // 删除点
    382 
    383     if ( (node->mLeft == nullptr) || (node->mRight == nullptr) )    // 如果孩子不全,node就是删除点,可以直接用仅有的孩子代替
    384         del = node;
    385     else                                                            // 否则有两个孩子,后继就是删除点(右子树中最小的成员)
    386     {
    387         del = successor(node);                                        // 查找后继
    388         node->mKey = del->mKey;                                        // 直接用后继key替换node的key
    389     }
    390 
    391     if ( del->mLeft != nullptr )            // 如果有左孩子,则更新左孩子为代替结点(如果if成立就只有左孩子)
    392         replace = del->mLeft;
    393     else                                    // 否则设右孩子为代替结点
    394         replace = del->mRight;
    395 
    396     if ( replace != nullptr )                // 如果代替结点不是空树,更新代替结点的父亲
    397         replace->mParent = del->mParent;
    398 
    399     if ( del->mParent == nullptr )            // 如果结点是根节点且孩子不全,那就直接替换
    400         this->mRoot = replace;
    401     else if ( del == del->mParent->mLeft )    // 如果删除点为左孩子,则更新父节点的左孩子
    402         del->mParent->mLeft = replace;
    403     else                                    // 否则更新父节点的右孩子
    404         del->mParent->mRight = replace;
    405 
    406     --this->mCount;
    407 
    408     return del;
    409 }
    410 
    411 template < typename T >
    412 void BSTree<T>::remove(const T& key)
    413 {
    414     BSTNode<T> *del = nullptr, *node;
    415     del = search(dynamic_cast<BSTNode<T>*>(this->mRoot), key);
    416 
    417     if ( del != nullptr )                        // 找到的删除点不为空
    418         if ( (node = remove(del)) != nullptr )    // 删除node并返回代替结点
    419             delete node;                        // 删除代替结点
    420 }
    421 
    422 template < typename T >
    423 void BSTree<T>::destroy(BSTNode<T> *tree)
    424 {
    425     if ( tree == nullptr )
    426         return;
    427 
    428     if ( tree->mLeft != nullptr )
    429         destroy(tree->mLeft);
    430 
    431     if ( tree->mRight != nullptr )
    432         destroy(tree->mRight);
    433 
    434     delete tree;
    435     tree = nullptr;
    436 }
    437 
    438 template < typename T >
    439 void BSTree<T>::destroy()
    440 {
    441     destroy(dynamic_cast<BSTNode<T>*>(this->mRoot));
    442     this->mRoot = nullptr;
    443     this->mCount = 0;
    444 }
    445 
    446 template < typename T >
    447 int BSTree<T>::height(BSTNode<T>* node) const
    448 {
    449     int ret = 0;
    450 
    451     if( node != nullptr )
    452     {
    453         int lh = height(node->mLeft);
    454         int rh = height(node->mRight);
    455 
    456         ret = ((lh > rh) ? lh : rh) + 1;
    457     }
    458 
    459     return ret;
    460 }
    461 
    462 template < typename T >
    463 int BSTree<T>::height() const
    464 {
    465     int ret = 0;
    466 
    467     if( this->mRoot != nullptr )
    468     {
    469         ret = height(dynamic_cast<BSTNode<T>*>(this->mRoot));
    470     }
    471 
    472     return ret;
    473 }
    474 
    475 template < typename T >
    476 int BSTree<T>::degree(BSTNode<T>* node) const
    477 {
    478     int ret = 0;
    479 
    480     if( node != nullptr )
    481     {
    482         BSTNode<T>* child[] = { node->mLeft, node->mRight };
    483 
    484         ret = (!!node->mLeft + !!node->mRight);        // 统计有效结点数,!!用于转换成bool类型,如果是有效结点则为1,否则为0
    485 
    486         for(int i=0; (i<2) && (ret<2); i++)            // 如果儿子不足2个需要检查
    487         {
    488             int d = degree(child[i]);
    489 
    490             if( ret < d )
    491             {
    492                 ret = d;
    493             }
    494         }
    495     }
    496 
    497     return ret;
    498 }
    499 
    500 template < typename T >
    501 int BSTree<T>::degree() const
    502 {
    503     return degree(dynamic_cast<BSTNode<T>*>(this->mRoot));
    504 }
    505 
    506 template < typename T >
    507 size_t BSTree<T>::getCount() const
    508 {
    509     return this->mCount;
    510 }
    511 
    512 template <typename T>
    513 void BSTree<T>::printTree(BSTNode<T> *tree, bool firstNode) const
    514 {
    515     if ( tree == nullptr )
    516         return;
    517 
    518     size_t height = this->height();                // 树的高度
    519     static bool *outTag = new bool[height]();    // 左边是否还有结点的标记,初始化为false
    520     uint8_t static layer = 0;                    // 当前层数,根结点为第一层
    521     uint8_t i;
    522     ++layer;
    523 
    524     if ( layer > 1 )                    // 如果不是根节点需要输出特殊符号
    525     {
    526         for (i=1; i<layer-1; ++i )        // 根节点和最后一个结点不需要,所以从1至(layer-1)
    527             if ( outTag[i] )            // 如果左边还有结点
    528                 cout << "|       ";
    529             else
    530                 cout << "        ";
    531 
    532         if ( firstNode == true )        // 判断左右结点,非二叉树需要另外处理
    533             cout << "L-------" << flush;
    534         else
    535             cout << "R-------" << flush;
    536     }
    537     cout << tree->mKey << endl;
    538 
    539     if ( (tree->mRight) != nullptr )    // 先输出右节点
    540     {
    541         if ( tree->mLeft != nullptr )    // 如果左边还有结点需要做标记
    542             outTag[layer] = true;
    543         printTree(tree->mRight, false);    // false表示当前是右节点
    544     }
    545 
    546     if ( tree->mLeft != nullptr )
    547     {
    548         outTag[layer] = false;            // 左结点左边不再有结点,恢复默认标记
    549         printTree(tree->mLeft, true);
    550     }
    551 
    552     --layer;                            // 结点回溯时高度需要减1
    553 }
    554 
    555 template <typename T>
    556 void BSTree<T>::printTree() const
    557 {
    558     printTree(dynamic_cast<BSTNode<T>*>(this->mRoot), false);    // 作为根节点时,右参数无意义
    559 }
    560 
    561 template < typename T >
    562 const T& BSTree<T>::getRootKey() const
    563 {
    564     return this->mRoot->mKey;
    565 }
    566 
    567 template < typename T >
    568 BSTree<T>::~BSTree()
    569 {
    570     destroy();
    571 }
    572 
    573 }
    574 
    575 #endif // BSTREE_H

    main.cpp

      1 #include <iostream>
      2 #include <iomanip>
      3 #include <cmath>
      4 
      5 #include "BSTree.h"
      6 
      7 #include "Times.h"
      8 
      9 using namespace std;
     10 using namespace Viclib;
     11 
     12 int main(int argc, char* argv[])
     13 {
     14     uint16_t layer = 8;    // 结点最小层数
     15 
     16     if ( argc == 2 && atoi(argv[1])>0 )
     17         layer = static_cast<uint8_t>(atoi(argv[1]));
     18     else {
     19         cout << "请输入结点最小层数,注意内存大小" << log(RAND_MAX*RAND_MAX+1+RAND_MAX*2)/log(2) << endl;
     20         cin >> layer;
     21     }
     22 
     23     timingStart();                            // 启动计时
     24 
     25     cout << endl;
     26 
     27     uint64_t const count = (1ull<<layer)-1;    // 结点数
     28     uint16_t speed;                            // 记录插入和删除的进度百分比(0~100)
     29 
     30     BSTree<uint64_t> *tree = new BSTree<uint64_t>();
     31 
     32     speed = 0;
     33     srand(static_cast<unsigned int>(time(nullptr)));
     34     while ( tree->getCount() < count )
     35     {
     36         tree->insert(static_cast<size_t>(rand()*rand()+1+RAND_MAX*2));    // 使用随机值插入;如果是顺序值,会退化成链表模式,且插入变慢
     37 
     38         if ( (tree->getCount()*100/count > speed) || (tree->getCount() == count) )    // 进度值出现变化或完成操作时才能输出
     39         {
     40             speed = static_cast<uint16_t>(tree->getCount()*100/count);
     41             cout << "
    已添加:" << setw(3) << speed << '%' << flush;
     42         }
     43     }
     44     cout << endl;
     45 
     46     cout << "
    前序遍历: ";
     47     tree->preOrder();
     48     cout << endl;
     49 
     50     cout << "
    中序遍历: ";
     51     tree->inOrder();
     52     cout << endl;
     53 
     54     cout << "
    后续遍历: ";
     55     tree->postOrder();
     56     cout << endl;
     57 
     58     cout << "
    广度遍历:";
     59     tree->levelOrder();
     60     cout << endl;
     61 
     62     cout << "
    最小值: " << tree->minimum();
     63     cout << "
    最大值: " << tree->maximum();
     64     cout << "
    树高度 = " << tree->height();
     65     cout << "
    结点数= " << tree->getCount();
     66     cout << endl;
     67 
     68     cout << "
    输出树形信息:" << endl;
     69     tree->printTree();
     70     cout << endl;
     71 
     72     speed = 0;
     73     srand(static_cast<unsigned int>(time(nullptr)));
     74     while ( tree->getCount() )
     75     {
     76         uint64_t node;
     77 //        if ( tree->getCount()*100/count < 20 )            // 剩余量太少时,随机值命中有效结点的概率太低,从而导致删除缓慢
     78             node = tree->getRootKey();
     79 //        else
     80 //            node = static_cast<size_t>(rand()*rand()+1+RAND_MAX*2);
     81 
     82         tree->remove(node);
     83 
     84         if ( ((count-tree->getCount())*100/count > speed) || (tree->getCount() == count) )
     85         {
     86             speed = static_cast<uint16_t>((count-tree->getCount())*100/count);
     87             cout << "
    已删除:" << setw(3) << speed << '%' << flush;
     88         }
     89     }
     90     cout << endl;
     91 
     92     tree->destroy();
     93     delete tree;
     94     tree = nullptr;
     95 
     96     cout << endl;
     97     timingEnd();
     98 
     99     return 0;
    100 }
  • 相关阅读:
    Pyspider
    tornado websocket
    cookie、session、csrf
    python图片拼接
    SQLAlchemy查询
    tornado的ORM
    模板继承和UImodul 和 UImethods
    图像处理-05-浮雕效果处理
    图像处理-04-图像的黑白处理
    图像处理-03-实现图像的旋转
  • 原文地址:https://www.cnblogs.com/duacai/p/10891287.html
Copyright © 2011-2022 走看看