zoukankan      html  css  js  c++  java
  • 数据结构---二叉搜索树BST实现

    1. 二叉查找树

    二叉查找树(Binary Search Tree),也称为二叉搜索树、有序二叉树(ordered binary tree)或排序二叉树(sorted binary tree),是指一棵空树或者具有下列性质的二叉树:

    1. 若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值;
    2. 若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值;
    3. 任意节点的左、右子树也分别为二叉查找树;
    4. 没有键值相等的节点。

    2. 节点类

    1 class BSTNode{
    2 public:
    3     int data;
    4     BSTNode *left;
    5     BSTNode *right;
    6     BSTNode(int x):
    7     data(x), left(NULL), right(NULL){}
    8 };

    在写代码的过程中发现有的类方法需要经常使用某节点的父节点,所以可以考虑在数据成员中添加父节点 BSTNode* parents ,本文是在BSTree的方法中添加了函数 BSTNode* BSTree::getParents(int value) 

    3. 二叉搜索树类

     1 class BSTree{
     2 public:
     3     BSTNode *root;
     4     BSTree():
     5     root(NULL){}
     6     ~BSTree(){destory(root);}
     7 
     8     // 是否为空
     9     bool isEmpty();
    10     // 深度
    11     int depth(BSTNode *&proot);
    12     // 节点数
    13     int size(BSTNode *&proot);
    14     // 叶子节点数
    15     int leafsize(BSTNode *&proot);
    16 
    17     // 前序遍历
    18     void preOrder(BSTNode* &pRoot);
    19     // 中序遍历
    20     void inOrder(BSTNode* &pRoot);
    21     // 后序遍历
    22     void postOrder(BSTNode* &pRoot);
    23     // 层序遍历
    24     void levelOrder(BSTNode* &pRoot);
    25 
    26     // 查找
    27     bool search(int value);
    28     // 插入
    29     void insert(int value);
    30     // 删除
    31     void remove(int value);
    32 
    33     // 寻找前驱节点
    34     BSTNode* predecessor(int value);
    35     // 寻找后继节点
    36     BSTNode* successor(int value);
    37 
    38     // 最小值
    39     int minimum();
    40     // 最大值
    41     int maximum();
    42 
    43     // 销毁BST
    44     void destory(BSTNode *&proot);
    45 
    46 private:
    47     // 获取value节点的地址
    48     BSTNode* getAddr(int value);
    49     // 获取value父节点的地址
    50     BSTNode* getParents(int value);
    51 };

    4. 主要方法

    对于基本的方法,如深度、节点数、叶子节点数没什么难点;

    对于三种遍历方法使用的是经典的递归方法;

    对于BST的最大/最小值,主要记住最小值永远在根节点的最左边,最大值永远在根节点的最右边,只需要不停的向最左或最优遍历即可,直到空节点结束(最大最小值也可能是根节点);

    BST的难点可能就在节点删除的部分,以下图所示的树为对象,讲一下节点删除:

    /*
     *                         62
     *                       /    
     *                     58      88
     *                     /       / 
     *                    47      73  99
     *                   /           /
     *                 35    51      93
     *                 /    / 
     *               29  37 49 56
     *                   /     / 
     *                  36    48 50
     *
     */

    被删除的节点可能是一下3种情况之一:

    1. 叶子节点   2. 只含有左子树或只含有右子树的节点   3. 同时含有左右子树的节点

    细分:

    1. 叶子节点

    1.1 树只含有一个节点,删除叶子节点

    如果树只有一个节点,则该节点即是根节点又是叶节点,删除时需要将root置空

    1.2 树含有至少2个节点,删除叶子节点

    如图上的 29  36  73等,删除叶子节点对BST没有影响,删除即可,同时需要维护指针;

    2. 仅有左或者右子树的节点

    2.1 仅有左子树的节点,同时该节点是根节点

    2.2 仅有左子树的节点,同时该节点非根节点

    2.3 仅有右子树的节点,同时该节点是根节点

    2.4 仅有右子树的节点,同时该节点非根节点

    上述四种情况只需要将待删节点的左右孩子放到待删节点的位置即可,同时注意是不是需要维护根节点

     3. 左右子树都有的节点

    首先寻找待删节点的直接前驱,然后用直接前驱代替待删节点。如删除47,47的前驱是37,那么将37节点的数据复制到47节点,释放37,同时将35的右孩子指向36,原47节点的右子树不动。

    以上具体细节见完整代码

    5. 完整代码

      1 #include<iostream>
      2 #include<vector>
      3 #include<queue>
      4 using namespace std;
      5 
      6 class BSTNode{
      7 public:
      8     int data;
      9     BSTNode *left;
     10     BSTNode *right;
     11     BSTNode(int x):
     12     data(x), left(NULL), right(NULL){}
     13 };
     14 
     15 class BSTree{
     16 public:
     17     BSTNode *root;
     18     BSTree():
     19     root(NULL){}
     20     ~BSTree(){destory(root);}
     21 
     22     // 是否为空
     23     bool isEmpty();
     24     // 深度
     25     int depth(BSTNode *&proot);
     26     // 节点数
     27     int size(BSTNode *&proot);
     28     // 叶子节点数
     29     int leafsize(BSTNode *&proot);
     30 
     31     // 前序遍历
     32     void preOrder(BSTNode* &pRoot);
     33     // 中序遍历
     34     void inOrder(BSTNode* &pRoot);
     35     // 后序遍历
     36     void postOrder(BSTNode* &pRoot);
     37     // 层序遍历
     38     void levelOrder(BSTNode* &pRoot);
     39 
     40     // 查找
     41     bool search(int value);
     42     // 插入
     43     void insert(int value);
     44     // 删除
     45     void remove(int value);
     46 
     47     // 寻找前驱节点
     48     BSTNode* predecessor(int value);
     49     // 寻找后继节点
     50     BSTNode* successor(int value);
     51 
     52     // 最小值
     53     int minimum();
     54     // 最大值
     55     int maximum();
     56 
     57     // 销毁BST
     58     void destory(BSTNode *&proot);
     59 
     60 private:
     61     // 获取value节点的地址
     62     BSTNode* getAddr(int value);
     63     // 获取value父节点的地址
     64     BSTNode* getParents(int value);
     65 };
     66 
     67 bool BSTree::isEmpty(){
     68     return root==NULL;
     69 }
     70 
     71 int BSTree::depth(BSTNode *&proot){
     72     if(proot == NULL)
     73         return 0;
     74     int left = depth(proot->left);
     75     int right = depth(proot->right);
     76     if(left > right)
     77         return left + 1;
     78     else
     79         return right + 1;
     80 }
     81 
     82 int BSTree::size(BSTNode *&proot){
     83     if(proot == NULL)
     84         return 0;
     85     int left = size(proot->left);
     86     int right = size(proot->right);
     87     return left + right + 1;
     88 }
     89 
     90 int BSTree::leafsize(BSTNode *&proot){
     91     if(proot == NULL)
     92         return 0;
     93     if(proot->left == NULL && proot->right == NULL)
     94         return 1;
     95     int leftLeaf = leafsize(proot->left);
     96     int rightLeaf = leafsize(proot->right);
     97     return leftLeaf + rightLeaf;
     98 }
     99 
    100 BSTNode* BSTree::getParents(int value){
    101     if(BSTree::search(value) == true){
    102         BSTNode* pRoot = root;
    103         BSTNode* parents; // 用于存储value节点的父节点
    104         while(pRoot->data!=value){
    105             parents = pRoot;
    106             if(pRoot->data > value)
    107                 pRoot = pRoot->left;
    108             else
    109                 pRoot = pRoot->right;
    110         }
    111         if(pRoot == root){
    112             //cout<<"the value is root of the tree, NO PARENTS."<<endl;
    113             return NULL;
    114         }
    115         else
    116             return parents;
    117     }
    118     else{
    119         cout<<"the value is not in the tree."<<endl;
    120         return NULL;
    121     }
    122 }
    123 
    124 BSTNode* BSTree::getAddr(int value){
    125     if(BSTree::search(value) == true){
    126         BSTNode* pRoot = root;
    127         while(pRoot->data!=value){
    128             if(pRoot->data > value)
    129                 pRoot = pRoot->left;
    130             else
    131                 pRoot = pRoot->right;
    132         }
    133         return pRoot;
    134     }
    135     else{
    136         cout<<"the value is not in the tree."<<endl;
    137         return NULL;
    138     }
    139 }
    140 
    141 // 若value不在树内或者value没有前驱,返回null,否则,返回前驱节点地址
    142 BSTNode* BSTree::predecessor(int value){
    143     if(!search(value)){
    144         cout<<"the value is not in the tree."<<endl;
    145         return NULL;
    146     }
    147     else if(BSTree::minimum() == value){
    148         cout<<"节点"<<value<<"没有前驱节点"<<endl;
    149         return NULL;
    150     }
    151     else{
    152         BSTNode* pRoot = getAddr(value);// 用于存储value节点的地址
    153         BSTNode* parents = getParents(value); // 用于存储value的父节点地址
    154         // 含左子树的节点
    155         if(pRoot->left != NULL){
    156             BSTNode* pre = pRoot->left;
    157             while(pre->right != NULL){
    158                 pre = pre->right;
    159             }
    160             return pre;
    161         }
    162         //没有左子树的节点
    163         else{
    164             if(parents->right == pRoot)
    165                 return parents;
    166             else if(parents->left == pRoot){
    167                 while(parents->data > value)
    168                     parents = getParents(parents->data);
    169                 return parents;
    170             }
    171         }
    172     }
    173 }
    174 
    175 // 若value不在树内或者value没有后继,返回null,否则,返回前后继节点地址
    176 BSTNode* BSTree::successor(int value){
    177     if(!search(value)){
    178         cout<<"the value is not in the tree."<<endl;
    179         return NULL;
    180     }
    181     else if(BSTree::maximum() == value){
    182         cout<<"节点"<<value<<"没有后继节点"<<endl;
    183         return NULL;
    184     }
    185     else{
    186         BSTNode* pRoot = getAddr(value);// 用于存储value节点的地址
    187         BSTNode* parents = getParents(value); // 用于存储value的父节点地址
    188         // 含右子树的节点
    189         if(pRoot->right != NULL){
    190             BSTNode* pre = pRoot->right;
    191             while(pre->left != NULL){
    192                 pre = pre->left;
    193             }
    194             return pre;
    195         }
    196         //没有右子树的节点
    197         else{
    198             if(parents->left == pRoot)
    199                 return parents;
    200             else if(parents->right == pRoot){
    201                 while(parents->data < value)
    202                     parents = getParents(parents->data);
    203                 return parents;
    204             }
    205         }
    206     }
    207 }
    208 
    209 int BSTree::minimum(){
    210     BSTNode* proot = root;
    211     while(proot->left != NULL){
    212         proot = proot->left;
    213     }
    214     return proot->data;
    215 }
    216 
    217 int BSTree::maximum(){
    218     BSTNode* proot = root;
    219     while(proot->right != NULL){
    220         proot = proot->right;
    221     }
    222     return proot->data;
    223 }
    224 
    225 /*
    226  *                         62
    227  *                       /    
    228  *                     58      88
    229  *                     /       / 
    230  *                    47      73  99
    231  *                   /           /
    232  *                 35    51      93
    233  *                 /    / 
    234  *               29  37 49 56
    235  *                   /     / 
    236  *                  36    48 50
    237  *
    238  * 删除节点的3种情况:
    239  * 1. 叶子节点
    240  *         1.1 树只含有一个节点,删除叶子节点
    241  *         1.2 树含有至少2个节点,删除叶子节点
    242  * 2. 仅有左或者右子树的节点
    243  *        2.1 仅有左子树的节点,删除根节点
    244  *        2.2 仅有左子树的节点,删除非根节点
    245  *        2.3 仅有右子树的节点,删除根节点
    246  *        2.4 仅有右子树的节点,删除非根节点
    247  * 3. 左右子树都有的节点
    248  *
    249  */
    250 
    251 void BSTree::remove(int value){
    252     if(!search(value)){
    253         cout<<"the value is not in the tree. please check."<<endl;
    254         return ;
    255     }
    256     else{
    257         // 查找value节点
    258         BSTNode* pRoot = getAddr(value);// 用于存储value节点的地址
    259         BSTNode* parents = getParents(value); // 用于存储待删除节点的父节点
    260         // 删除value节点
    261         // 1.叶节点
    262         // 1.1 树只含有一个节点
    263         if(pRoot == root && pRoot->left == NULL && pRoot->right == NULL){
    264             root = NULL;
    265             free(pRoot);
    266         }
    267         // 1.2 树含有至少2个节点
    268         else if(pRoot != root && pRoot->left == NULL && pRoot->right == NULL){
    269             // 待删节点是父节点的右孩子
    270             if(parents->right != NULL && parents->right->data == value){
    271                 parents->right = NULL;
    272                 free(pRoot);
    273             }
    274             // 待删节点是父节点的左孩子
    275             else{
    276                 parents->left = NULL;
    277                 free(pRoot);
    278             }
    279         }
    280         // 2. 仅有左子树或右子树的节点
    281         // 2.1 仅有左子树,且删除根节点
    282         else if(pRoot == root && pRoot->left != NULL && pRoot->right == NULL){
    283             root = pRoot->left;
    284             free(pRoot);
    285         }
    286         // 2.2 仅有左子树的节点,删除非根节点
    287         else if(pRoot != root && pRoot->left != NULL && pRoot->right == NULL){
    288             // 待删节点是父节点的右孩子
    289             if(parents->right != NULL && parents->right->data == value){
    290                 parents->right = pRoot->left;
    291                 free(pRoot);
    292             }
    293             // 待删节点是父节点的左孩子
    294             else{
    295                 parents->left = pRoot->left;
    296                 free(pRoot);
    297             }
    298         }
    299         // 2.3 仅有右子树的节点,删除根节点
    300         else if(pRoot == root && pRoot->left == NULL && pRoot->right != NULL){
    301             root = pRoot->right;
    302             free(pRoot);
    303         }
    304         // 2.4 仅有右子树的节点, 删除非根节点
    305         else if(pRoot != root && pRoot->left == NULL && pRoot->right != NULL){
    306             // 待删节点是父节点的右孩子
    307             if(parents->right != NULL && parents->right->data == value){
    308                 parents->right = pRoot->right;
    309                 free(pRoot);
    310             }
    311             // 待删节点是父节点的左孩子
    312             else{
    313                 parents->left = pRoot->right;
    314                 free(pRoot);
    315             }
    316         }
    317         // 3. 左右子树都有的节点
    318         else{
    319             // 寻找待删除节点的直接前驱
    320             BSTNode* pre = predecessor(value);// pre存储直接前驱
    321             pRoot->data = pre->data;// 数据覆盖
    322             // 寻找直接前驱的左/右节点
    323             if(pre->right != NULL){
    324                 BSTNode *pRootNext = pRoot->right;
    325                 BSTNode *temp = pre->right;
    326                 if(pre == pRootNext)
    327                     pRoot->right = temp;
    328                 else
    329                     pRootNext->left = temp;
    330                 free(pre);
    331             }
    332             else if(pre->left != NULL){
    333                 BSTNode *pRootNext = pRoot->left;
    334                 BSTNode *temp = pre->left;
    335                 if(pre == pRootNext)
    336                     pRoot->left = temp;
    337                 else
    338                     pRootNext->right = temp;
    339                 free(pre);
    340             }
    341             else if(pre->left == NULL && pre->right == NULL){
    342                 pRoot->left = NULL;
    343                 free(pre);
    344             }
    345         }
    346     }
    347 }
    348 
    349 
    350 bool BSTree::search(int value){
    351     BSTNode* pRoot = root;
    352     while(pRoot!=NULL && pRoot->data!=value){
    353         if(pRoot->data > value)
    354             pRoot = pRoot->left;
    355         else
    356             pRoot = pRoot->right;
    357     }
    358     if(pRoot == NULL)
    359         return false;
    360     else
    361         return true;
    362 }
    363 
    364 void BSTree::insert(int value){
    365     // value节点已经存在
    366     if(BSTree::search(value) == true){
    367         cout<<"the value "<<value<<" in the tree already."<<endl;
    368         return ;
    369     }
    370     // value节点不存在
    371     else{
    372         BSTNode* pRoot = root;
    373         // 空树
    374         if(pRoot == NULL)
    375             root = new BSTNode(value);
    376         // 非空
    377         else{
    378             BSTNode* temp;
    379             while(pRoot!= NULL && pRoot->data!=value){
    380                 temp = pRoot;
    381                 if(pRoot->data > value)
    382                     pRoot = pRoot->left;
    383                 else
    384                     pRoot = pRoot->right;
    385             }
    386             pRoot = temp;
    387             if(pRoot->data>value)
    388                 pRoot->left = new BSTNode(value);
    389             else
    390                 pRoot->right = new BSTNode(value);
    391         }
    392     }
    393     cout<<"the value "<<value<<" is inserted."<<endl;
    394 }
    395 
    396 void BSTree::preOrder(BSTNode* &pRoot){
    397     if(pRoot == NULL)
    398         return ;
    399     cout<<pRoot->data<<' ';
    400     preOrder(pRoot->left);
    401     preOrder(pRoot->right);
    402 }
    403 
    404 void BSTree::inOrder(BSTNode* &pRoot){
    405     if(pRoot == NULL)
    406         return ;
    407     inOrder(pRoot->left);
    408     cout<<pRoot->data<<' ';
    409     inOrder(pRoot->right);
    410 }
    411 
    412 void BSTree::postOrder(BSTNode* &pRoot){
    413     if(pRoot == NULL)
    414         return ;
    415     postOrder(pRoot->left);
    416     postOrder(pRoot->right);
    417     cout<<pRoot->data<<' ';
    418 }
    419 
    420 void BSTree::levelOrder(BSTNode *&pRoot){
    421     queue<BSTNode*> p;
    422     if(pRoot == NULL)
    423         return ;
    424     p.push(pRoot);
    425     while (!p.empty()){
    426         BSTNode *temp = p.front();
    427         cout<<temp->data<<' ';
    428         p.pop();
    429         if(temp->left)
    430             p.push(temp->left);
    431         if(temp->right)
    432             p.push(temp->right);
    433     }
    434 }
    435 
    436 void BSTree::destory(BSTNode *&proot){
    437     if (proot== NULL)
    438         return ;
    439     destory(proot->left);
    440     destory(proot->right);
    441     cout<<"free value "<<proot->data<<endl;
    442     free(proot);
    443     proot = NULL;
    444 }
    445 
    446 
    447 int main(int argc, char const *argv[])
    448 {
    449     BSTree tree;
    450     int arr[] = {62, 58, 47, 35, 29,
    451                  37, 36, 51, 49, 48,
    452                  50, 56, 88, 73, 99, 93};
    453     for(int i=0; i<16; i++)
    454         tree.insert(arr[i]);
    455 
    456     cout<<"前序遍历: ";
    457     tree.preOrder(tree.root);
    458     cout<<endl;
    459     cout<<"中序遍历: ";
    460     tree.inOrder(tree.root);
    461     cout<<endl;
    462     cout<<"最小值: "<<tree.minimum()<<endl;
    463     cout<<"最大值: "<<tree.maximum()<<endl;
    464 
    465     cout<<"深度: "<<tree.depth(tree.root)<<endl;
    466     cout<<"节点数: "<<tree.size(tree.root)<<endl;
    467     cout<<"叶子节点数: "<<tree.leafsize(tree.root)<<endl;
    468 
    469     int index = 2;
    470     BSTNode *pre = tree.predecessor(arr[index]);
    471     if(pre != NULL)
    472         cout<<"节点"<<arr[index]<<"的前驱节点是"<<pre->data<<endl;
    473 
    474     BSTNode *suc = tree.successor(arr[index]);
    475     if(suc != NULL)
    476         cout<<"节点"<<arr[index]<<"的后继节点是"<<suc->data<<endl;
    477 
    478     cout<<"删除节点: "<<arr[index]<<endl;
    479     tree.remove(arr[index]);
    480 
    481     cout<<"前序遍历: ";
    482     tree.preOrder(tree.root);
    483     cout<<endl;
    484     cout<<"中序遍历: ";
    485     tree.inOrder(tree.root);
    486     cout<<endl;
    487 
    488     tree.destory(tree.root);
    489     return 0;
    490 }
    View Code

    6. 运行结果

    6.1 测试使用的二叉搜索树

    /*
     *                         62
     *                       /    
     *                     58      88
     *                     /       / 
     *                    47      73  99
     *                   /           /
     *                 35    51      93
     *                 /    / 
     *               29  37 49 56
     *                   /     / 
     *                  36    48 50
     *
     */

    6.2 运行结果

     1 the value 62 is inserted.
     2 the value 58 is inserted.
     3 the value 47 is inserted.
     4 the value 35 is inserted.
     5 the value 29 is inserted.
     6 the value 37 is inserted.
     7 the value 36 is inserted.
     8 the value 51 is inserted.
     9 the value 49 is inserted.
    10 the value 48 is inserted.
    11 the value 50 is inserted.
    12 the value 56 is inserted.
    13 the value 88 is inserted.
    14 the value 73 is inserted.
    15 the value 99 is inserted.
    16 the value 93 is inserted.
    17 前序遍历: 62 58 47 35 29 37 36 51 49 48 50 56 88 73 99 93 
    18 中序遍历: 29 35 36 37 47 48 49 50 51 56 58 62 73 88 93 99 
    19 最小值: 29
    20 最大值: 99
    21 深度: 6
    22 节点数: 16
    23 叶子节点数: 7
    24 节点47的前驱节点是37
    25 节点47的后继节点是48
    26 删除节点: 47
    27 前序遍历: 62 58 37 35 29 36 51 49 48 50 56 88 73 99 93 
    28 中序遍历: 29 35 36 37 48 49 50 51 56 58 62 73 88 93 99 
    29 free value 29
    30 free value 36
    31 free value 35
    32 free value 48
    33 free value 50
    34 free value 49
    35 free value 56
    36 free value 51
    37 free value 37
    38 free value 58
    39 free value 73
    40 free value 93
    41 free value 99
    42 free value 88
    43 free value 62
    44 [Finished in 2.1s]
  • 相关阅读:
    Centos 安装git
    mybatis 整合redis作为二级缓存
    jedis 连接池工具类
    IE8下使用asp.net core mvc+jquery ajaxSubmit问题
    .net core mvc部署到IIS导出Word 提示80070005拒绝访问
    IdentityServer4在Asp.Net Core中的应用(三)
    理解OpenID和OAuth的区别
    IdentityServer4在Asp.Net Core中的应用(二)
    使用Bind读取配置到C#的实例
    IdentityServer4在Asp.Net Core中的应用(一)
  • 原文地址:https://www.cnblogs.com/iwangzhengchao/p/9805439.html
Copyright © 2011-2022 走看看