zoukankan      html  css  js  c++  java
  • "《算法导论》之‘树’":二叉查找树

      树的介绍部分摘取自博文二叉查找树(一)二叉查找树(二)二叉查找树

    1. 树的介绍

    1.1 树的定义

      树是一种数据结构,它是由n(n>=1)个有限节点组成一个具有层次关系的集合。

      

      把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。它具有以下的特点:
      (1) 每个节点有零个或多个子节点;
      (2) 没有父节点的节点称为根节点;
      (3) 每一个非根节点有且只有一个父节点;
      (4) 除了根节点外,每个子节点可以分为多个不相交的子树。

    1.2 树的基本术语

      若一个结点有子树,那么该结点称为子树根的"双亲",子树的根是该结点的"孩子"。有相同双亲的结点互为"兄弟"。一个结点的所有子树上的任何结点都是该结点的后裔。从根结点到某个结点的路径上的所有结点都是该结点的祖先。

      结点的度:结点拥有的子树的数目。
      叶子:度为零的结点。
      分支结点:度不为零的结点。
      树的度:树中结点的最大的度。

      层次:根结点的层次为1,其余结点的层次等于该结点的双亲结点的层次加1。
      树的高度:树中结点的最大层次。
      无序树:如果树中结点的各子树之间的次序是不重要的,可以交换位置。
      有序树:如果树中结点的各子树之间的次序是重要的, 不可以交换位置。
      森林:0个或多个不相交的树组成。对森林加上一个根,森林即成为树;删去根,树即成为森林。

    2. 二叉树介绍

    2.1 二叉树的定义

      二叉树是每个节点最多有两个子树的树结构。它有五种基本形态:二叉树可以是空集;根可以有空的左子树或右子树;或者左、右子树皆为空。

      

    2.2 二叉树的性质

      二叉树有以下几个性质:TODO(上标和下标)
      性质1:二叉树第i层上的结点数目最多为 2{i-1} (i≥1)。
      性质2:深度为k的二叉树至多有2{k}-1个结点(k≥1)。
      性质3:包含n个结点的二叉树的高度至少为log2 (n+1)
      性质4:在任意一棵二叉树中,若终端结点的个数为n0,度为2的结点数为n2,则n0=n2+1

      性质1:二叉树第i层上的结点数目最多为 2{i-1} (i≥1)

      证明:下面用"数学归纳法"进行证明。
            (01) 当i=1时,第i层的节点数目为2{i-1}=2{0}=1。因为第1层上只有一个根结点,所以命题成立。
            (02) 假设当i>1,第i层的节点数目为2{i-1}。这个是根据(01)推断出来的!
                   下面根据这个假设,推断出"第(i+1)层的节点数目为2{i}"即可。
                   由于二叉树的每个结点至多有两个孩子,故"第(i+1)层上的结点数目" 最多是 "第i层的结点数目的2倍"。即,第(i+1)层上的结点数目最大值=2×2{i-1}=2{i}
                    故假设成立,原命题得证!

      性质2:深度为k的二叉树至多有2{k}-1个结点(k≥1)

      证明:在具有相同深度的二叉树中,当每一层都含有最大结点数时,其树中结点数最多。利用"性质1"可知,深度为k的二叉树的结点数至多为:
               20+21+…+2k-1=2k-1
               故原命题得证!

      性质3:包含n个结点的二叉树的高度至少为log2 (n+1)

      证明:根据"性质2"可知,高度为h的二叉树最多有2{h}–1个结点。反之,对于包含n个节点的二叉树的高度至少为log2(n+1)。

      性质4:在任意一棵二叉树中,若终端结点的个数为n0,度为2的结点数为n2,则n0=n2+1

      证明:因为二叉树中所有结点的度数均不大于2,所以结点总数(记为n)="0度结点数(n0)" + "1度结点数(n1)" + "2度结点数(n2)"。由此,得到等式一。
             (等式一) n=n0+n1+n2
          另一方面,0度结点没有孩子,1度结点有一个孩子,2度结点有两个孩子,故二叉树中孩子结点总数是:n1+2n2。此外,只有根不是任何结点的孩子。故二叉树中的结点总数又可表示为等式二。
             (等式二) n=n1+2n2+1
            由(等式一)和(等式二)计算得到:n0=n2+1。原命题得证!

    2.3 满二叉树,完全二叉树和二叉查找树

        (1)满二叉树

      定义:高度为h,并且由2{h} –1个结点的二叉树,被称为满二叉树。

      

        (2)完全二叉树

      定义:一棵二叉树中,只有最下面两层结点的度可以小于2,并且最下一层的叶结点集中在靠左的若干位置上。这样的二叉树称为完全二叉树。
      特点:叶子结点只能出现在最下层和次下层,且最下层的叶子结点集中在树的左部。显然,一棵满二叉树必定是一棵完全二叉树,而完全二叉树未必是满二叉树。

      

       (3)二叉查找树

      定义:二叉查找树(Binary Search Tree),又被称为二叉搜索树。设x为二叉查找树中的一个结点,x节点包含关键字key,节点x的key值记为key[x]。如果y是x的左子树中的一个结点,则key[y] < key[x];如果y是x的右子树的一个结点,则key[y] > key[x]。

      

        

      在二叉查找树中:

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

      2)任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;

      3)任意节点的左、右子树也分别为二叉查找树。

      4)没有键值相等的节点(no duplicate nodes)。

    3. 二叉查找树操作

    3.1 查找

      在二叉查找树中查找一个给定的关键字k的过程与二分查找很类似,根据二叉查找树在的关键字存放的特征,很容易得出查找过程:首先是关键字k与树根的关键字进行比较,如果k大比根的关键字大,则在根的右子树中查找,否则在根的左子树中查找,重复此过程,直到找到与遇到空结点为止。例如下图所示的查找关键字13的过程:(查找过程每次在左右子树中做出选择,减少一半的工作量)

      

      《算法导论》中给出的递归和非递归的伪代码如下:

    1 TREE_SEARCH(x,k)
    2   if x=NULL or k=key[x]
    3       then return x
    4   if(k<key[x])
    5       then return TREE_SEARCH(left[x],k)
    6   else
    7       then return TREE_SEARCH(right[x],k)
    1 ITERATIVE_TREE_SEARCH(x,k)
    2   while x!=NULL and k!=key[x]
    3       do if k<key[x]
    4               then x=left[x]
    5            else
    6               then x=right[x]
    7    return x

    3.2 查找最大关键字和最小关键字

      根据二叉查找树的特征,很容易查找出最大和最小关键字。查找二叉树中的最小关键字:从根结点开始,沿着各个节点的left指针查找下去,直到遇到NULL时结束。如果一个结点x无左子树,则以x为根的子树中,最小关键字就是key[x]。查找二叉树中的最大关键字:从根结点开始,沿着各个结点的right指针查找下去,直到遇到NULL时结束。书中给出了查找最大最小关键字的伪代码:

      《算法导论》中给出的伪代码如下:

    1 TREE_MINMUM(x)
    2     while left[x] != NULL
    3         do x=left[x]
    4     return x 
    1 TREE_MAXMUM(x)
    2     while right[x] != NULL
    3         do x= right[x]
    4     return x

    3.3 前驱和后继

      给定一个二叉查找树中的结点,找出在中序遍历顺序下某个节点的前驱和后继。如果树中所有关键字都不相同,则某一结点x的前驱就是小于key[x]的所有关键字中最大的那个结点,后继即是大于key[x]中的所有关键字中最小的那个结点。根据二叉查找树的结构和性质,不用对关键字做任何比较,就可以找到某个结点的前驱和后继。

      查找前驱步骤:先判断x是否有左子树,如果有则在left[x]中查找关键字最大的结点,即是x的前驱。如果没有左子树,则从x继续向上执行此操作,直到遇到某个结点是其父节点的右孩子结点。例如下图查找结点7的前驱结点6过程:

      

      查找后继步骤:先判断x是否有右子树,如果有则在right[x]中查找关键字最小的结点,即使x的后继。如果没有右子树,则从x的父节点开始向上查找,直到遇到某个结点是其父结点的左儿子的结点时为止。例如下图查找结点13的后继结点15的过程:

      

      《算法导论》中中给出了求x结点后继结点的伪代码:

    1 TREE_PROCESSOR(x)
    2     if right[x] != NULL
    3         then return TREE_MINMUM(right(x))
    4     y=parent[x]
    5     while y!= NULL and x ==right[y]
    6            do x = y
    7                y=parent[y]
    8     return y

        定理:对一棵高度为h的二叉查找,动态集合操作SEARCH、MINMUM、MAXMUM、SUCCESSOR、PROCESSOR等的运行时间均为O(h)。

    3.4 插入和删除

      插入和删除会引起二叉查找表示的动态集合的变化,难点在在插入和删除的过程中要保持二叉查找树的性质。插入过程相当来说要简单一些,删除结点比较复杂。

      (1)插入

      插入结点的位置对应着查找过程中查找不成功时候的结点位置,因此需要从根结点开始查找带插入结点位置,找到位置后插入即可。下图所示插入结点过程:

      

      《算法导论》中给出了插入过程的伪代码:

     1 TREE_INSERT(T, z)
     2     y = NULL;
     3     x = root[T]
     4     while x != NULL
     5         do y = x
     6     if key[z] < key[x]
     7         then x = left[x]
     8     else  
     9         x = right[x]
    10     parent[z] = y
    11     if y = NULL
    12         then root[T] = z
    13     else if key[z]>key[y]
    14         then  keft[y] = z
    15     else   right[y] = z

      插入过程运行时间为O(h),h为树的高度。

      (2)删除

      从二叉查找树中删除给定的结点z,分三种情况讨论:

      <1>结点z没有左右子树,则修改其父节点p[z],使其为NULL。删除过程如下图所示:

      

      <2>如果结点z只有一个子树(左子树或者右子树),通过在其子结点与父节点建立一条链来删除z。删除过程如下图所示:

      

      <3>如果z有两个子女,那么找z的后继y(一定在z的右子树中),并让y占据树中z的位置。z的原来右子树部分成为y的新的右子树,并且z的左子树成为y的新的左子树。

      

      《算法导论》中给出了删除过程的伪代码:

     1 TREE_DELETE(T, z)
     2     if left[z] == NULL or right[z] == NULL
     3         then y = z
     4     else  y = TREE_SUCCESSOR(z)
     5 
     6     if left[y] != NULL
     7         then x = left[y]
     8     else  x = right[y]
     9 
    10     if x != NULL
    11         then parent[x] = parent[y]
    12     if p[y] == NULL
    13         then root[T] = x
    14     else if y = left[[prarnt[y]]
    15         then left[parent[y]] = x
    16     else  right[parent[y]] = x
    17 
    18     if y != z
    19         then key[z] = key[y]
    20     copy y's data into z
    21     return y
    View Code

      定理:对高度为h的二叉查找树,动态集合操作INSERT和DELETE的运行时间为O(h)。

    3.5 遍历

      前序遍历

      若二叉树非空,则执行以下操作:
      (1) 访问根结点;
      (2) 先序遍历左子树;
      (3) 先序遍历右子树

      中序遍历

      若二叉树非空,则执行以下操作:
      (1) 中序遍历左子树;
      (2) 访问根结点;
      (3) 中序遍历右子树。

      后序遍历

      若二叉树非空,则执行以下操作:
      (1) 后序遍历左子树;
      (2) 后序遍历右子树;
      (3) 访问根结点。

      看看下面这颗树的各种遍历方式:

      

      对于上面的二叉树而言,
      (1) 前序遍历结果: 3 1 2 5 4 6
      (2) 中序遍历结果: 1 2 3 4 5 6 
      (3) 后序遍历结果: 2 1 4 6 5 3

    4. 二叉查找树实现

      我先定义了一个最基本的类“Tree”如下:

     1 #ifndef TREE_H
     2 #define TREE_H
     3 
     4 #include <iostream>
     5 #include <cassert>
     6 using namespace std;
     7 
     8 template<class T>
     9 class Node
    10 {
    11 public:
    12     Node() : height(0), parent(NULL), left(NULL), right(NULL){};
    13     ~Node(){};
    14 
    15 public:
    16     T key;
    17     T data;
    18     unsigned int height;
    19     Node * parent;
    20     Node * left;
    21     Node * right;
    22 
    23 };
    24 
    25 template<class T>
    26 class Tree
    27 {
    28 public:
    29     typedef Node<T> * NodePointer;
    30 
    31 public:
    32     Tree(){};
    33     virtual ~Tree(){};
    34     //Tree(const Tree& orig){};
    35     //Tree& operator=(const Tree& orig){};
    36     virtual bool isEmpty() = 0;                                  // 判断树是否为空
    37     virtual void creatTree(T * k, T * arr, unsigned len) = 0;    // 初始化树
    38     virtual bool addNode(T k, T val) = 0;                        // 添加节点
    39     virtual bool delNode(T k) = 0;                               // 删除节点
    40 
    41     virtual unsigned int getHeight() = 0;                        // 获得树的高度
    42     //virtual unsigned int getHeight(NodePointer tree) = 0;
    43 
    44     virtual T getMinimum() = 0;                                  // 获取树中的最小值
    45     virtual T getMaxmum() = 0;                                   // 获取树中的最大值
    46 
    47     virtual Node<T> * searchNode(T k) = 0;                       // 搜索key为k的节点
    48     virtual Node<T> * getPredecessor(T k) = 0;                   // 获取某节点(key为k)的前驱节点
    49     virtual Node<T> * getSuccessor(T k) = 0;                     // 获取某节点(key为k)的后继节点
    50 
    51     virtual void preOrder() = 0;                                 //先序遍历
    52     //virtual void preOrder(NodePointer tree) = 0;
    53     virtual void inOrder() = 0;                                  //中序遍历
    54     //virtual void inOrder(NodePointer tree) = 0;
    55     virtual void postOrder() = 0;                                //后序遍历
    56     //virtual void postOrder(NodePointer tree) = 0;
    57 
    58     virtual void destroy() = 0;                                  //释放整棵树
    59     //virtual void destroy(NodePointer tree) = 0;                
    60 
    61 protected:
    62     NodePointer root;
    63 
    64 };
    65 
    66 #endif

      二叉搜索树的类定义为:

     1 #include "tree.h"
     2 
     3 template<class T>
     4 class BSTree : public Tree<T>
     5 {
     6 public:
     7     BSTree();
     8     virtual ~BSTree();
     9     BSTree(const BSTree& orig);
    10     BSTree& operator=(const BSTree& orig);
    11     virtual bool isEmpty();                                    // 判断树是否为空
    12     virtual void creatTree(T * k, T * arr, unsigned len);      // 初始化树
    13     virtual bool addNode(T k, T val);                          // 添加节点
    14     virtual bool delNode(T k);                                 // 删除节点
    15 
    16     virtual unsigned int getHeight();                          // 获得树的高度
    17 
    18     virtual T getMinimum();                                    // 获取树中的最小值
    19     virtual T getMaxmum();                                     // 获取树中的最大值
    20 
    21     virtual Node<T> * searchNode(T k);                         // 搜索key为k的节点
    22     virtual Node<T> * getPredecessor(T k);                     // 获取某节点(key为k)的前驱节点
    23     virtual Node<T> * getSuccessor(T k);                       // 获取某节点(key为k)的后继节点
    24 
    25     virtual void preOrder();                                   // 先序遍历
    26     virtual void inOrder();                                    // 中序遍历
    27     virtual void postOrder();                                  // 后序遍历
    28 
    29     virtual void destroy();                                    // 释放整棵树
    30 
    31 protected:
    32     void preOrder(NodePointer tree);                           // 先序遍历
    33     void inOrder(NodePointer tree);                            // 中序遍历
    34     void postOrder(NodePointer tree);                          // 后序遍历
    35     unsigned int getHeight(NodePointer tree);                  // 获得树的高度
    36     void destroy(NodePointer tree);                            // 释放整棵树
    37 
    38 
    39 // 辅助单元测试
    40 public:
    41     // 单元测试用,模板友元函数
    42     template<class T>
    43     friend T getTestData(const BSTree<T>& tree, int pos);
    44 
    45 private:
    46     int count;
    47     T testData[1024];
    48 
    49 };

      完整实现程序:

      1 // Blog: http://www.cnblogs.com/xiehongfeng100/p/4093815.html 
      2 
      3 
      4 #ifndef BSTREE_H
      5 #define BSTREE_H
      6 
      7 #include "tree.h"
      8 
      9 template<class T>
     10 class BSTree : public Tree<T>
     11 {
     12 public:
     13     BSTree();
     14     virtual ~BSTree();
     15     BSTree(const BSTree& orig);
     16     BSTree& operator=(const BSTree& orig);
     17     virtual bool isEmpty();                    // 判断树是否为空
     18     virtual void creatTree(T * k, T * arr, unsigned len);    // 初始化树
     19     virtual bool addNode(T k, T val);            // 添加节点
     20     virtual bool delNode(T k);                // 删除节点
     21 
     22     virtual unsigned int getHeight();            // 获得树的高度
     23 
     24     virtual T getMinimum();                                 // 获取树中的最小值
     25     virtual T getMaxmum();                    // 获取树中的最大值
     26 
     27     virtual Node<T> * searchNode(T k);                      // 搜索key为k的节点
     28     virtual Node<T> * getPredecessor(T k);                  // 获取某节点(key为k)的前驱节点
     29     virtual Node<T> * getSuccessor(T k);                    // 获取某节点(key为k)的后继节点
     30 
     31     virtual void preOrder();                // 先序遍历
     32     virtual void inOrder();                    // 中序遍历
     33     virtual void postOrder();                // 后序遍历
     34 
     35     virtual void destroy();                    // 释放整棵树
     36 
     37 protected:
     38     void preOrder(NodePointer tree);            // 先序遍历
     39     void inOrder(NodePointer tree);                // 中序遍历
     40     void postOrder(NodePointer tree);            // 后序遍历
     41     unsigned int getHeight(NodePointer tree);        // 获得树的高度
     42     void destroy(NodePointer tree);                // 释放整棵树
     43 
     44 // 辅助单元测试
     45 public:
     46     // 单元测试用,模板友元函数. 需要注意的是友元函数并没有this指针
     47     template<class T>
     48     friend T getTestData(const BSTree<T>& tree, int pos);
     49 
     50 private:
     51     int count;
     52     T testData[1024];
     53 
     54 };
     55 
     56 template<class T>
     57 BSTree<T>::BSTree()
     58 {
     59     root = NULL;
     60 }
     61 
     62 template<class T>
     63 BSTree<T>::~BSTree()
     64 {
     65     destroy(root);
     66     root = NULL; // 以防root成为“野指针”
     67 }
     68 
     69 template<class T>
     70 BSTree<T>::BSTree(const BSTree& orig)
     71 {
     72     // leave blank
     73 }
     74 
     75 
     76 template<class T>
     77 BSTree<T>& BSTree<T>::operator=(const BSTree& orig)
     78 {
     79     // leave blank
     80     return *this;
     81 }
     82 
     83 template<class T>
     84 bool BSTree<T>::isEmpty()
     85 {
     86     return root == NULL;
     87 }
     88 
     89 template<class T>
     90 void BSTree<T>::creatTree(T * k, T * arr, unsigned len)
     91 {
     92     for (int i = 0; i < len; i++)
     93     {
     94         addNode(k[i], arr[i]);
     95     }
     96 }
     97 
     98 template<class T>
     99 unsigned BSTree<T>::getHeight()
    100 {
    101     return getHeight(root);
    102 }
    103 
    104 template<class T>
    105 unsigned BSTree<T>::getHeight(NodePointer tree)
    106 {
    107     if (tree == NULL)
    108     {
    109         return 0;
    110     }
    111     else
    112     {
    113         int m = getHeight(tree->left);
    114         int n = getHeight(tree->right);
    115         return (m > n) ? (m + 1) : (n + 1);
    116     }
    117 
    118 }
    119 
    120 template<class T>
    121 bool BSTree<T>::addNode(T k, T val)
    122 {
    123     bool isSuccess = true;
    124     // to allocate memory
    125     // method 1
    126     NodePointer ptr = new(nothrow) Node<T>();
    127     if (ptr == NULL)
    128     {
    129         return false;
    130     }
    131     // method 2
    132     //NodePointer ptr;
    133     //try
    134     //{
    135     //    ptr = new Node<T>();
    136     //}
    137     //catch (bad_alloc* e)
    138     //{
    139     //    return false;
    140     //}
    141     //catch (exception* e)
    142     //{
    143     //    return false;
    144     //}
    145     ptr->key = k;
    146     ptr->data = val;
    147     if (root == NULL)
    148     {
    149         root = ptr;
    150         root->parent = NULL;
    151     }
    152     else
    153     {
    154         NodePointer tmpPtr = root;
    155         while (tmpPtr != NULL)
    156         {
    157             if (k == tmpPtr->key)
    158             {
    159                 // 如果关键字重复,则添加失败,且释放已经申请到的内存
    160                 isSuccess = false;
    161                 delete ptr;
    162                 break;
    163             }
    164             else if (k < tmpPtr->key)
    165             {
    166                 if (tmpPtr->left == NULL)
    167                 {
    168                     tmpPtr->left = ptr;
    169                     ptr->parent = tmpPtr;
    170                     break;
    171                 }
    172                 else
    173                 {
    174                     tmpPtr = tmpPtr->left;
    175                 }
    176             }
    177             else
    178             {
    179                 if (tmpPtr->right == NULL)
    180                 {
    181                     tmpPtr->right = ptr;
    182                     ptr->parent = tmpPtr;
    183                     break;
    184                 }
    185                 else
    186                 {
    187                     tmpPtr = tmpPtr->right;
    188                 }
    189             }
    190         }
    191     }
    192 
    193     return isSuccess;
    194 }
    195 
    196 template<class T>
    197 bool BSTree<T>::delNode(T k)
    198 {
    199     bool isSuccess = true;
    200     NodePointer delNodePtr = searchNode(k);
    201     if (delNodePtr == NULL)
    202     {
    203         isSuccess = false;
    204     }
    205     else
    206     {
    207         // 删除的节点没有子树
    208         if (delNodePtr->left == NULL && delNodePtr->right == NULL)
    209         {
    210             // 如果是根节点
    211             if (delNodePtr == root)
    212             {
    213                 root = NULL;
    214             }
    215             // 如果不是根节点
    216             else 
    217             {
    218                 NodePointer parentPtr = delNodePtr->parent;
    219                 if (parentPtr->left == delNodePtr)
    220                 {
    221                     parentPtr->left = NULL;
    222                 }
    223                 else
    224                 {
    225                     parentPtr->right = NULL;
    226                 }
    227             }
    228 
    229             delete delNodePtr;
    230             delNodePtr = NULL;
    231         }
    232 
    233         // 删除的节点只有一个子树
    234         else if (delNodePtr->left == NULL || delNodePtr->right == NULL)
    235         {
    236             NodePointer tmp = NULL;
    237             // 如果是根节点
    238             if (delNodePtr == root)
    239             {
    240                 if (delNodePtr->left == NULL)
    241                 {
    242                     tmp = delNodePtr->right;
    243                 }
    244                 else
    245                 {
    246                     tmp = delNodePtr->left;
    247                 }
    248                 tmp->parent = NULL;
    249                 root = tmp;
    250             }
    251             // 如果不是根节点
    252             else
    253             {
    254                 NodePointer parentPtr = delNodePtr->parent;
    255                 if (parentPtr->left == delNodePtr)
    256                 {
    257                     parentPtr->left = (delNodePtr->left == NULL) ? delNodePtr->right : delNodePtr->left;
    258                     tmp = parentPtr->left;
    259                 }
    260                 else
    261                 {
    262                     parentPtr->right = (delNodePtr->left == NULL) ? delNodePtr->right : delNodePtr->left;
    263                     tmp = parentPtr->right;
    264                 }
    265                 tmp->parent = parentPtr;
    266             }
    267 
    268             delete delNodePtr;
    269             delNodePtr = NULL;
    270         }
    271 
    272         // 删除的节点有两个子树
    273         else
    274         {
    275             NodePointer successor = getSuccessor(delNodePtr->data);
    276             if (successor == delNodePtr->right)
    277                 delNodePtr->right = nullptr;
    278             else
    279                 (successor->parent)->left = nullptr;
    280 
    281             successor->right = delNodePtr->right;
    282             successor->left = delNodePtr->left;
    283             (delNodePtr->left)->parent = successor;
    284             if (delNodePtr->right != nullptr)
    285                 (delNodePtr->right)->parent = successor;
    286             
    287             // 如果待删节点是根节点
    288             if (delNodePtr == root)
    289             {
    290                 successor->parent = nullptr;
    291                 root = successor;
    292             }
    293             else
    294             {
    295                 NodePointer parentPtr = delNodePtr->parent;
    296                 // 判断待删节点是其父节点的左节点还是右节点
    297                 if (delNodePtr == parentPtr->left)
    298                     parentPtr->left = successor;
    299 
    300                 else
    301                     parentPtr->right = successor;
    302                 successor->parent = parentPtr;
    303             }
    304             // 释放待删节点内存
    305             delete delNodePtr;
    306             delNodePtr = NULL;
    307         }
    308     }
    309 
    310     return isSuccess;
    311 }
    312 
    313 template<class T>
    314 T BSTree<T>::getMinimum()
    315 {
    316     NodePointer tmpPtr = root, ptr = NULL;
    317     while (tmpPtr != NULL)
    318     {
    319         ptr = tmpPtr;
    320         tmpPtr = tmpPtr->left;
    321     }
    322     return ptr->data;
    323 }
    324 
    325 template<class T>
    326 T BSTree<T>::getMaxmum()
    327 {
    328     NodePointer tmpPtr = root, ptr = NULL;
    329     while (tmpPtr != NULL)
    330     {
    331         ptr = tmpPtr;
    332         tmpPtr = tmpPtr->right;
    333     }
    334     return ptr->data;
    335 }
    336 
    337 template<class T>
    338 Node<T> * BSTree<T>::searchNode(T k)
    339 {
    340     // 优先判断树是否为空
    341     if (root == NULL)
    342     {
    343         return NULL;
    344     }
    345 
    346     NodePointer ptr = NULL, tmpPtr = root;
    347     while (tmpPtr != NULL)
    348     {
    349         if (k == tmpPtr->key)
    350         {
    351             ptr = tmpPtr;
    352             break;
    353         }
    354         else if (k < tmpPtr->key)
    355         {
    356             if (tmpPtr->left == NULL)
    357             {
    358                 break;
    359             }
    360             else
    361             {
    362                 tmpPtr = tmpPtr->left;
    363             }
    364         }
    365         else
    366         {
    367             if (tmpPtr->right == NULL)
    368             {
    369                 break;
    370             }
    371             else
    372             {
    373                 tmpPtr = tmpPtr->right;
    374             }
    375         }
    376     }
    377 
    378     return ptr;
    379 }
    380 
    381 template<class T>
    382 Node<T> * BSTree<T>::getPredecessor(T k)
    383 {
    384     NodePointer tmpPtr = searchNode(k), ptr = NULL;
    385     if (tmpPtr != NULL)
    386     {
    387         if (tmpPtr == root)
    388         {
    389             ptr = NULL;
    390         }
    391         else if (tmpPtr->left != NULL)
    392         {
    393             NodePointer bakPtr = NULL;
    394             ptr = tmpPtr->left;
    395             while (ptr != NULL)
    396             {
    397                 bakPtr = ptr;
    398                 ptr = ptr->right;
    399             }
    400             ptr = bakPtr;
    401         }
    402         else
    403         {
    404             ptr = tmpPtr->parent;
    405         }
    406     }
    407 
    408     return ptr;
    409 }
    410 
    411 template<class T>
    412 Node<T> * BSTree<T>::getSuccessor(T k)
    413 {
    414     NodePointer tmpPtr = searchNode(k), ptr = NULL;
    415     if (tmpPtr != NULL)
    416     {
    417         if (tmpPtr == root && tmpPtr->right == NULL)
    418         {
    419             ptr = NULL;
    420         }
    421         else if (tmpPtr->right != NULL)
    422         {
    423             NodePointer bakPtr = NULL;
    424             ptr = tmpPtr->right;
    425             while (ptr != NULL)
    426             {
    427                 bakPtr = ptr;
    428                 ptr = ptr->left;
    429             }
    430             ptr = bakPtr;
    431         }
    432         else
    433         {
    434             ptr = tmpPtr->parent;
    435             while (ptr->key < tmpPtr->key)
    436             {
    437                 ptr = ptr->parent;
    438                 // 如果找到根节点仍找不到
    439                 if (ptr == root && ptr->key < tmpPtr->key)
    440                 {
    441                     ptr = NULL;
    442                     break;
    443                 }
    444             }
    445         }
    446     }
    447 
    448     return ptr;
    449 }
    450 
    451 template<class T>
    452 void BSTree<T>::preOrder()
    453 {
    454     count = 0;
    455     preOrder(root);
    456 }
    457 
    458 template<class T>
    459 void BSTree<T>::preOrder(NodePointer tree)
    460 {
    461     if (tree != NULL)    // 注意这里不是用while循环
    462     {
    463         // cout << tmpPtr->data << end;
    464         testData[count] = tree->data;
    465         count++;
    466         preOrder(tree->left);
    467         preOrder(tree->right);
    468     }
    469 }
    470 
    471 // 中序遍历的输出是按从小到大的排序的
    472 template<class T>
    473 void BSTree<T>::inOrder()
    474 {
    475     count = 0;
    476     inOrder(root);
    477 }
    478 
    479 template<class T>
    480 void BSTree<T>::inOrder(NodePointer tree)
    481 {
    482     if (tree != NULL)
    483     {
    484         inOrder(tree->left);
    485         // cout << tmpPtr->data << end;
    486         testData[count] = tree->data;
    487         count++;
    488         inOrder(tree->right);
    489     }
    490 }
    491 
    492 template<class T>
    493 void BSTree<T>::postOrder()
    494 {
    495     count = 0;
    496     postOrder(root);
    497 }
    498 
    499 template<class T>
    500 void BSTree<T>::postOrder(NodePointer tree)
    501 {
    502     if (tree != NULL)
    503     {
    504         postOrder(tree->left);
    505         postOrder(tree->right);
    506         // cout << tmpPtr->data << end;
    507         testData[count] = tree->data;
    508         count++;
    509     }
    510 }
    511 
    512 template<class T>
    513 void BSTree<T>::destroy()
    514 {
    515     destroy(root);
    516     root = NULL;
    517 }
    518 
    519 template<class T>
    520 void BSTree<T>::destroy(NodePointer tree)
    521 {
    522     NodePointer leftPtr = NULL, rightPtr = NULL;
    523     if (tree != NULL)
    524     {
    525         leftPtr = tree->left;
    526         rightPtr = tree->right;
    527         delete tree;
    528         tree = NULL;    // 这一句十分重要。因为tree被释放后成为一个
    529                 // “野指针”,即不是NULL指针,因此会让while循环
    530                 // 在释放完所有的内存后再循环一次,而此时tree
    531                 // 已经是一个“野指针”,对它再进行内存释放必然出错
    532         destroy(leftPtr);
    533         destroy(rightPtr);
    534     }
    535 }
    536 
    537 // 模板友元函数
    538 template<class T>
    539 T getTestData(const BSTree<T>& tree, int pos)
    540 {
    541     return tree.testData[pos];
    542 }
    543 
    544 
    545 #endif
    BSTree.hpp

      Boost单元测试程序:

      1 #define BOOST_TEST_MODULE Tree_Test_Module
      2 
      3 #include "stdafx.h"
      4 #include "../AVLTree/BSTree.hpp"
      5 
      6 struct BSTree_Fixture
      7 {
      8 public:
      9     BSTree_Fixture()
     10     {
     11         testBSTree = new BSTree<int>();
     12     }
     13     ~BSTree_Fixture()
     14     {
     15         delete testBSTree;
     16     }
     17 
     18     BSTree<int> * testBSTree;
     19 };
     20 
     21 BOOST_FIXTURE_TEST_SUITE(BSTree_Test_Suite, BSTree_Fixture)
     22 
     23 BOOST_AUTO_TEST_CASE(BSTree_Normal_Test)
     24 {
     25     // isEmpty & getHight-----------------------------
     26     BOOST_REQUIRE(testBSTree->isEmpty() == true);
     27     BOOST_REQUIRE(testBSTree->getHeight() == 0);
     28 
     29     // addNode & searchNode ---------------------------
     30     BOOST_REQUIRE(testBSTree->addNode(1, 1) == true);
     31     BOOST_REQUIRE(testBSTree->searchNode(1) != NULL);
     32     BOOST_REQUIRE((testBSTree->searchNode(1))->data == 1);
     33     BOOST_REQUIRE(testBSTree->isEmpty() == false);
     34     BOOST_REQUIRE(testBSTree->getHeight() == 1);
     35 
     36     BOOST_REQUIRE(testBSTree->addNode(0, 0) == true);
     37     BOOST_REQUIRE(testBSTree->searchNode(0) != NULL);
     38     BOOST_REQUIRE((testBSTree->searchNode(0))->data == 0);
     39     BOOST_REQUIRE(testBSTree->getHeight() == 2);
     40 
     41     BOOST_REQUIRE(testBSTree->addNode(2, 2) == true);
     42     BOOST_REQUIRE(testBSTree->searchNode(2) != NULL);
     43     BOOST_REQUIRE((testBSTree->searchNode(2))->data == 2);
     44     BOOST_REQUIRE(testBSTree->getHeight() == 2);
     45 
     46     BOOST_REQUIRE(testBSTree->addNode(3, 3) == true);
     47     BOOST_REQUIRE(testBSTree->searchNode(3) != NULL);
     48     BOOST_REQUIRE((testBSTree->searchNode(3))->data == 3);
     49     BOOST_REQUIRE(testBSTree->getHeight() == 3);
     50 
     51     // getMinimum & getMaxmum ----------------------
     52     BOOST_REQUIRE(testBSTree->getMinimum() == 0);
     53     BOOST_REQUIRE(testBSTree->getMaxmum() == 3);
     54 
     55     // preOrder ------------------------------------
     56     testBSTree->preOrder();
     57     BOOST_REQUIRE(getTestData(*testBSTree, 0) == 1);
     58     BOOST_REQUIRE(getTestData(*testBSTree, 1) == 0);
     59     BOOST_REQUIRE(getTestData(*testBSTree, 2) == 2);
     60     BOOST_REQUIRE(getTestData(*testBSTree, 3) == 3);
     61 
     62     // inOrder -------------------------------------
     63     testBSTree->inOrder();
     64     BOOST_REQUIRE(getTestData(*testBSTree, 0) == 0);
     65     BOOST_REQUIRE(getTestData(*testBSTree, 1) == 1);
     66     BOOST_REQUIRE(getTestData(*testBSTree, 2) == 2);
     67     BOOST_REQUIRE(getTestData(*testBSTree, 3) == 3);
     68 
     69     // postOrder -----------------------------------
     70     testBSTree->postOrder();
     71     BOOST_REQUIRE(getTestData(*testBSTree, 0) == 0);
     72     BOOST_REQUIRE(getTestData(*testBSTree, 1) == 3);
     73     BOOST_REQUIRE(getTestData(*testBSTree, 2) == 2);
     74     BOOST_REQUIRE(getTestData(*testBSTree, 3) == 1);
     75 
     76     // destroy -------------------------------------
     77     testBSTree->destroy();
     78 
     79     // creatBSTree --------------------------------
     80     int key[] = { 7, 3, 1, 2, 5, 4, 6, 9, 8, 10, 11 };
     81     int value[] = { 7, 3, 1, 2, 5, 4, 6, 9, 8, 10, 11 };
     82     unsigned len = sizeof(key) / sizeof(int);
     83     testBSTree->creatTree(key, value, len);
     84 
     85     // getPredecessor ------------------------------
     86     BOOST_REQUIRE(testBSTree->getPredecessor(7) == NULL);
     87     BOOST_REQUIRE((testBSTree->getPredecessor(2))->data == 1);
     88     BOOST_REQUIRE((testBSTree->getPredecessor(5))->data == 4);
     89 
     90     // getSuccessor --------------------------------
     91     BOOST_REQUIRE(testBSTree->getSuccessor(7)->data == 8);
     92     BOOST_REQUIRE(testBSTree->getSuccessor(6)->data == 7);
     93     BOOST_REQUIRE(testBSTree->getSuccessor(9)->data == 10);
     94     BOOST_REQUIRE(testBSTree->getSuccessor(11) == NULL);
     95 
     96 }
     97 
     98 BOOST_AUTO_TEST_CASE(BSTree_delNode_Test)
     99 {
    100     // creatBSTree --------------------------------
    101     int key[] = { 7, 3, 1, 0, 5, 4, 6, 9, 8, 10, 11 };
    102     int value[] = { 7, 3, 1, 0, 5, 4, 6, 9, 8, 10, 11 };
    103     unsigned len = sizeof(key) / sizeof(int);
    104     testBSTree->creatTree(key, value, len);
    105 
    106     // delNode ----------------------------------
    107     // delete root with two children
    108     Node<int> * treeRoot = testBSTree->searchNode(7);
    109     BOOST_REQUIRE((treeRoot->left)->data == 3);
    110     BOOST_REQUIRE((treeRoot->right)->data == 9);
    111     BOOST_REQUIRE(testBSTree->delNode(7) == true);
    112 
    113     BOOST_REQUIRE(testBSTree->searchNode(7) == NULL);
    114     treeRoot = testBSTree->searchNode(8);
    115     BOOST_REQUIRE((treeRoot->left)->data == 3);
    116     BOOST_REQUIRE((treeRoot->right)->data == 9);
    117      
    118     // delete node (not root) with two children
    119     Node<int> * treeNode = testBSTree->searchNode(3);
    120     BOOST_REQUIRE((treeNode->left)->data == 1);
    121     BOOST_REQUIRE((treeNode->right)->data == 5);
    122     BOOST_REQUIRE(testBSTree->delNode(3) == true);
    123 
    124     treeNode = testBSTree->searchNode(4);
    125     BOOST_REQUIRE((treeNode->left)->data == 1);
    126     BOOST_REQUIRE((treeNode->right)->data == 5);
    127 
    128     // delete node with only one left child
    129     treeNode = testBSTree->searchNode(1);
    130     BOOST_REQUIRE((treeNode->left)->data == 0);
    131     BOOST_REQUIRE(treeNode->right == NULL);
    132     BOOST_REQUIRE(testBSTree->delNode(1) == true);
    133 
    134     BOOST_REQUIRE(testBSTree->searchNode(1) == NULL);
    135     treeNode = testBSTree->searchNode(4);
    136     BOOST_REQUIRE((treeNode->left)->data == 0);
    137     BOOST_REQUIRE((treeNode->right)->data == 5);
    138 
    139     // delete node with two children (right->right, without any left child)
    140     treeNode = testBSTree->searchNode(9);
    141     BOOST_REQUIRE((treeNode->parent)->data == 8);
    142     BOOST_REQUIRE(treeNode->left == NULL);
    143     BOOST_REQUIRE((treeNode->right)->data == 10);
    144     BOOST_REQUIRE(testBSTree->delNode(9) == true);
    145 
    146     treeNode = testBSTree->searchNode(10);
    147     BOOST_REQUIRE((treeNode->parent)->data == 8);
    148     BOOST_REQUIRE(treeNode->left == NULL);
    149     BOOST_REQUIRE((treeNode->right)->data == 11);
    150 
    151     // delete node with only one right child
    152     BOOST_REQUIRE(testBSTree->delNode(10) == true);
    153 
    154     treeNode = testBSTree->searchNode(11);
    155     BOOST_REQUIRE((treeNode->parent)->data == 8);
    156     BOOST_REQUIRE(treeNode->left == NULL);
    157     BOOST_REQUIRE(treeNode->right == NULL);
    158 
    159     BOOST_REQUIRE(testBSTree->delNode(11) == true);
    160 
    161     // delete root with only left tree
    162     treeNode = testBSTree->searchNode(4);
    163     BOOST_REQUIRE((treeNode->parent)->data == 8);
    164     BOOST_REQUIRE(testBSTree->delNode(8) == true);
    165 
    166     treeNode = testBSTree->searchNode(4);
    167     BOOST_REQUIRE(treeNode->parent == NULL);
    168 
    169     // delete other noods
    170     BOOST_REQUIRE(testBSTree->delNode(0) == true);
    171     BOOST_REQUIRE(testBSTree->delNode(5) == true);
    172     BOOST_REQUIRE(testBSTree->delNode(6) == true);
    173 
    174     // delete root with left or right child
    175     treeNode = testBSTree->searchNode(4);
    176     BOOST_REQUIRE(treeNode->left == NULL);
    177     BOOST_REQUIRE(treeNode->right == NULL);
    178     BOOST_REQUIRE(testBSTree->delNode(4) == true);
    179 
    180     BOOST_REQUIRE(testBSTree->searchNode(4) == NULL);
    181 
    182 }
    183 
    184 //BOOST_AUTO_TEST_CASE(BSTree_CopyConstructor_Test)
    185 //{
    186 //    // leave blank
    187 //}
    188 //
    189 //BOOST_AUTO_TEST_CASE(BSTree_EqualOperator_Test)
    190 //{
    191 //    // leave blank
    192 //}
    193 
    194 BOOST_AUTO_TEST_SUITE_END()
    BSTreeUnitTest

      本篇博文的代码均托管到Github.

  • 相关阅读:
    腾讯社招 —— 腾讯游戏后端工程师-电话面试
    乐刷科技-Java工程师社招面试
    平安人寿保险-深圳Java开发工程师社招面试
    字节跳动-后端工程师社招视频一面
    Markdown的常用使用语法
    oracle 表空间大小
    mysql、sqlserver、oracle获取最后一条数据
    mycat 学习
    oracle sql中特殊字符 & 的处理
    map循环
  • 原文地址:https://www.cnblogs.com/xiehongfeng100/p/4093815.html
Copyright © 2011-2022 走看看