zoukankan      html  css  js  c++  java
  • 查找(二叉排序树)

    【1】二叉排序树

    二叉排序树,又称为二叉查找树。

    它或者是一棵空树,或者具有下列性质:

    1. 若它的左子树不空,则左子树上所有的结点的值均小于它的根结点的值;

    2. 若它的右子树不空,则右子树上所有的结点的值均大于它的根结点的值;

    3. 它的左右子树也分别为二叉排序树。

    【2】二叉排序树的代码实现

    结合下图以及实现代码分析

    (1)构建二叉排序树

    (2)实现代码

      1 #include <iostream>
      2 using namespace std;
      3 
      4 template<class Type>   class BST;
      5 
      6 template<class Type>
      7 class BstNode
      8 {
      9     friend  class BST<Type>;
     10     Type  data;
     11     BstNode<Type> *leftChild, *rightChild;
     12     public:
     13         BstNode():leftChild(NULL), rightChild(NULL)
     14         {}
     15         BstNode(const Type &x,BstNode<Type> *left = NULL, BstNode<Type> *right = NULL)
     16             : data(x)
     17             , leftChild(left)
     18             , rightChild(right)
     19         {}
     20         ~BstNode()
     21         {}
     22         Type & GetData() { return data;}
     23         const Type & GetData() const { return data;}
     24         BstNode<Type> *&GetLeft() { return leftChild;}
     25         BstNode<Type> * const&GetLeft() const { return leftChild;}
     26         BstNode<Type> * &GetRight() { return rightChild;}
     27         BstNode<Type> * const &GetRight() const { return rightChild;}
     28 };
     29 template<class Type>  
     30 class BST
     31 {
     32 private:
     33     BstNode<Type>  *root;
     34 private:
     35     ///////////////////////////////////私有方法部分
     36     bool insert(BstNode<Type> *&ptr, const Type &x);
     37     bool insertElem(BstNode<Type> *&ptr, const Type &x);
     38     BstNode<Type>* find(BstNode<Type> * ptr, const Type &x);
     39     BstNode<Type>* findRecursive(BstNode<Type> * ptr, const Type &x);
     40     BstNode<Type>* findPre(BstNode<Type> *ptr, const Type &x);
     41     BstNode<Type>* max(BstNode<Type> *ptr) const;
     42     BstNode<Type>* min(BstNode<Type> *ptr) const;
     43     bool remove(BstNode<Type> *&ptr, const Type &x);
     44     bool removeRecursive(BstNode<Type> *&ptr, const Type &x);
     45     void InOrder(BstNode<Type> *ptr) const;
     46     void LevelOrder(BstNode<Type> *t) const;
     47 public:
     48     BST(): root(NULL)
     49     { }
     50     BST(Type x): root(NULL)
     51     { }
     52     ~BST()
     53     { }    
     54     BstNode<Type>* GetRoot()
     55     {
     56         return root;
     57     }
     58     void SetRoot(BstNode<Type>* pRoot)
     59     {
     60         root = pRoot;
     61     }
     62     int Insert(const Type &x)
     63     {
     64         return insert(root, x);
     65     }
     66     BstNode<Type>* Find(const Type &x)
     67     {
     68         return find(root, x);
     69     }
     70     void InOrder()
     71     {
     72         InOrder(root);
     73         cout << endl;
     74     }
     75     BstNode<Type>* Min() const  
     76     {
     77         return min(root);
     78     }
     79     BstNode<Type> * Max() const
     80     {
     81         return max(root);
     82     }
     83     int Remove(const Type &x)
     84     {
     85         return remove(root, x);
     86     }
     87     void LevelOrder()
     88     {
     89         LevelOrder(root);
     90     }
     91 };
     92 // 插入数据元素方法1 (递归实现)
     93 template<class Type>
     94 bool  BST<Type>::insert(BstNode<Type> *&ptr, const Type &x)
     95 {
     96     if (NULL == ptr)
     97     {    // 为空时就需要创建新节点
     98         ptr = new BstNode<Type>(x);
     99         if (NULL == ptr)
    100         {
    101             cerr << "out of space" << endl;
    102             return false;
    103         }
    104         return true;
    105     }
    106     else if (x < ptr->data)   
    107     {    // 小, 插入其左边
    108         return insert(ptr->leftChild, x);
    109     }
    110     else if (x > ptr->data)
    111     {    // 大, 插入其右边
    112         return insert(ptr->rightChild, x);
    113     }
    114     else
    115     {    // 两者相等
    116         cout << "数据" << x << "重复,请重新输入..." << endl;
    117         return false;
    118     }
    119 }
    120 // 插入数据元素方法2 (非递归实现)
    121 template<class Type>
    122 bool BST<Type>::insertElem(BstNode<Type> *&ptr, const Type &x)
    123 {
    124     if (NULL == ptr)
    125     {
    126         ptr = new BstNode<Type>(x);
    127         if (NULL == ptr)
    128         {
    129             cout << "out of space !" << endl;
    130             return false;
    131         }
    132         return true;
    133     }
    134     BstNode<Type>* p = ptr, *q = NULL;
    135     while (p != NULL)
    136     {
    137         q = p;
    138         if (x == p->data)
    139         {
    140             cout << "数据重复" << endl;
    141             return false;
    142         }
    143         if (x > p->data)
    144         {
    145             p = p->rightChild;
    146         }
    147         else if (x < p->data)
    148         {
    149             p = p->leftChild;
    150         }
    151     }
    152     p = new BstNode<Type>(x);
    153     if (x < q->data)
    154         q->leftChild = p;
    155     if (x > q->data)
    156         q->rightChild = p;
    157     return true;
    158 }
    159 // 查找某个数据元素的节点指针 (递归实现)
    160 template<class Type>
    161 BstNode<Type>* BST<Type>::findRecursive(BstNode<Type> *ptr, const Type &x)
    162 {
    163     if (NULL == ptr)
    164         return NULL;
    165     else if (x < ptr->data)
    166         return find(ptr->leftChild, x);
    167     else if (x > ptr->data)
    168         return find(ptr->rightChild, x);
    169     else
    170         return ptr;
    171 }
    172 // 查找某个数据元素的节点指针 (非递归实现)
    173 template<class Type>
    174 BstNode<Type>* BST<Type>::find(BstNode<Type> *ptr, const Type &x)
    175 {
    176     while (ptr != NULL)
    177     {
    178         if (x == ptr->data)  
    179             return ptr;
    180         else if (ptr->data > x)
    181             ptr = ptr->leftChild;
    182         else
    183             ptr = ptr->rightChild;
    184     }
    185     return  NULL;
    186 }
    187 // 查找某个数据元素的父节点指针 (非递归实现)
    188 // 记录父节点,当孩子值与查找的数据元素值相同,返回父节点即可。
    189 template<class Type>
    190 BstNode<Type>* BST<Type>::findPre(BstNode<Type> *ptr, const Type &x)
    191 {
    192     BstNode<Type>* q = NULL;
    193     while (ptr != NULL)
    194     {
    195         if (x == ptr->data)  
    196         {
    197             return q;
    198         }
    199         else if (ptr->data > x)
    200         {
    201             q = ptr;
    202             ptr = ptr->leftChild;
    203         }
    204         else
    205         {
    206             q = ptr;
    207             ptr = ptr->rightChild;
    208         }
    209     }
    210     return  NULL;
    211 }
    212 // 按元素值删除某个节点 (递归实现)
    213 // 具体删除思路请参考注释
    214 template<class Type>    
    215 bool BST<Type>::removeRecursive(BstNode<Type> *&ptr, const Type &x)
    216 {
    217     BstNode<Type>* tmp = NULL;
    218     if (ptr != NULL)
    219     { 
    220         if (x < ptr->data)      // 小于,转向左子树
    221             return remove(ptr->leftChild, x);
    222         else if (x > ptr->data) // 大于,转向右子树
    223             return remove(ptr->rightChild, x);
    224         // 相等时即找到  然后判断左右子树情况
    225         else if (ptr->leftChild != NULL && ptr->rightChild != NULL)  
    226         {    
    227             // 1. 左右均不空
    228             tmp = min(ptr->rightChild); // 找到右子树的最小值结点
    229             ptr->data = tmp->data;        // 数值更换
    230             return remove(ptr->rightChild, ptr->data); // 递归再删除那个最小值结点
    231         }
    232         else 
    233         {    // 2. 左为空 || 右为空 || 左右子树均为空
    234             tmp = ptr;
    235             if (NULL == ptr->leftChild)     // 先考虑左子树
    236                 ptr = ptr->rightChild;   // 衔接其右节点
    237             else if (NULL == ptr->rightChild) // 再考虑右子树
    238                 ptr = ptr->leftChild;          // 衔接其左节点
    239 
    240             delete tmp;
    241             tmp = NULL;  
    242             return true;
    243         }
    244     }
    245     return false;
    246 }
    247 // 按元素值删除某个节点 (非递归实现)
    248 // 具体删除思路请参考注释
    249 template<class Type>    
    250 bool BST<Type>::remove(BstNode<Type> *&ptr, const Type &x)
    251 {
    252     BstNode<Type>* pself = find(ptr, x); // 欲删除结点自身
    253     BstNode<Type>* parent = findPre(ptr, x); // 欲删除结点的父节点
    254     BstNode<Type>* pDelete = pself; // 最终删除结点
    255     if (NULL == pself)
    256     {
    257         cout << "删除数据不存在!" << endl;
    258         return false;
    259     }
    260     // 满足以下情况时需要转换一下实际删除节点
    261     if (pself->leftChild != NULL && pself->rightChild != NULL)  
    262     {    
    263         pDelete = min(pself->rightChild);    // 找到右子树的最小值结点,将来删除它即可
    264         pself->data = pDelete->data;         // 数值更换
    265         parent = findPre(pself->rightChild, pself->data); // 重新确定实际删除对象的父节点
    266         if (NULL == parent)
    267         {
    268             // 当删除右子树的根节点 (只有可能右子树存在)
    269             ptr->rightChild = pDelete->rightChild; // 衔接右子树即可
    270             // 执行删除 释放内存
    271             delete pDelete;
    272             pDelete = NULL;
    273             return true;
    274         }
    275     }
    276     // 当欲删除父节点  且其孩子为空
    277     if (NULL == parent)
    278     {
    279         if (NULL == pself->leftChild && 
    280             NULL == pself->rightChild)
    281         {    // 当树只有一个根节点 两孩子都为空
    282             delete ptr;
    283             ptr = NULL;
    284             return true;
    285         }
    286         else if (NULL == pself->leftChild)
    287         {    // 右孩子存在
    288             ptr = pself->rightChild;
    289         }
    290         else if (NULL == pself->rightChild)
    291         {    // 左孩子存在
    292             ptr = pself->leftChild;
    293         }
    294     }
    295     else
    296     {
    297         // 衔接结点
    298         if (parent->data < pDelete->data)
    299         {    // 右孩子
    300             if (NULL == pDelete->leftChild)    
    301                 parent->rightChild = pDelete->rightChild;
    302             else if (NULL == pDelete->rightChild) 
    303                 parent->rightChild = pDelete->leftChild;         
    304         }
    305         else
    306         {    // 左孩子
    307             if (NULL == pDelete->leftChild)    
    308                 parent->leftChild = pDelete->rightChild; 
    309             else if (NULL == pDelete->rightChild) 
    310                 parent->leftChild = pDelete->leftChild;
    311         }
    312     }
    313     // 执行删除 释放内存
    314     delete pDelete;
    315     pDelete = NULL;
    316     return true;
    317 }
    318 // 打印二叉搜索树的数据 (中序遍历)
    319 // 思路分析:
    320 // 先遍历左子树
    321 // 再遍历根节点
    322 // 最后遍历右子树
    323 template<class Type>
    324 void BST<Type>::InOrder(BstNode<Type> *ptr) const
    325 {
    326     if (ptr != NULL)
    327     {
    328         InOrder(ptr->leftChild);
    329         cout << ptr->data << " ";
    330         InOrder(ptr->rightChild);
    331     }
    332 }
    333 // 求二叉搜索树某一个子树的最小元素指针
    334 // 思路分析:
    335 // 一直向左子树递进即为最小
    336 template<class Type>
    337 BstNode<Type>* BST<Type>::min(BstNode<Type> *ptr) const
    338 {
    339     BstNode<Type> *p = ptr;
    340     while (p != NULL && p->leftChild != NULL)
    341     {
    342         p = p->leftChild;
    343     }
    344     return p;
    345 }
    346 // 求二叉搜索树某一个子树的最大元素指针
    347 // 思路分析:
    348 // 一直向右子树递进即为最大
    349 template<class Type>
    350 BstNode<Type>* BST<Type>::max(BstNode<Type> *ptr) const
    351 {
    352     BstNode<Type> *p = ptr;
    353     while (p != NULL && p->rightChild != NULL)  // 保证p不等于空!
    354     {
    355         p = p->rightChild;
    356     }
    357     return p;
    358 }
    359 
    360 void main()
    361 {
    362     BST<int> bst;
    363     int a[12] = {53,17,9,45,23,40,38,78,65,87,81,94};
    364     for (int i = 0; i < 12; ++i)
    365     {
    366         bst.Insert(a[i]);
    367     }
    368     cout << "中序遍历的结果如下:" << endl;
    369     bst.InOrder();
    370 
    371     int data = 0;
    372     cout << "请输入要查找的数据:";
    373     cin >> data;
    374     if (bst.Find(data) != NULL)
    375         cout << "查找成功!" << endl;
    376     else
    377         cout << "未查找到!" << endl;
    378 
    379     cout << "请输入要删除的数据:";
    380     for (; ;)
    381     {
    382         int num = 0;
    383         while (cin >> num, num != -1)
    384         {
    385             if (-1 == num)  
    386                 break;
    387             bst.Remove(num);
    388             cout << "删除后数据打印:" << endl;
    389             bst.InOrder();
    390             cout << "请输入要删除的数据(-1结束):";
    391         }
    392         break;
    393     }
    394 }

    Good  Good  Study, Day  Day  Up.

    顺序  选择  循环  总结

  • 相关阅读:
    【工具篇】利用DBExportDoc V1.0 For MySQL自动生成数据库表结构文档(转
    PHP Client for Mysql Binlog
    MySQL的binlog日志恢复(转)
    Linux 普通进程 后台进程 守护进程(转)
    实战:MySQL Sending data导致查询很慢的问题详细分析(转)
    mysql索引无效且sending data耗时巨大原因分析
    阿里云-DRDS(转)
    MySQL查看SQL语句执行效率(转)
    nginx php-fpm 输出php错误日志(转)
    Golang指针基本介绍及使用案例
  • 原文地址:https://www.cnblogs.com/Braveliu/p/3467097.html
Copyright © 2011-2022 走看看