"《算法导论》之‘树’":二叉查找树

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

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.

 

posted @ 2014-11-12 23:18  峰子_仰望阳光  阅读(659)  评论(0编辑  收藏  举报