标签:des style blog http io color ar os 使用
树是一种数据结构,它是由n(n>=1)个有限节点组成一个具有层次关系的集合。
把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。它具有以下的特点:
(1) 每个节点有零个或多个子节点;
(2) 没有父节点的节点称为根节点;
(3) 每一个非根节点有且只有一个父节点;
(4) 除了根节点外,每个子节点可以分为多个不相交的子树。
若一个结点有子树,那么该结点称为子树根的"双亲",子树的根是该结点的"孩子"。有相同双亲的结点互为"兄弟"。一个结点的所有子树上的任何结点都是该结点的后裔。从根结点到某个结点的路径上的所有结点都是该结点的祖先。
结点的度:结点拥有的子树的数目。
叶子:度为零的结点。
分支结点:度不为零的结点。
树的度:树中结点的最大的度。
层次:根结点的层次为1,其余结点的层次等于该结点的双亲结点的层次加1。
树的高度:树中结点的最大层次。
无序树:如果树中结点的各子树之间的次序是不重要的,可以交换位置。
有序树:如果树中结点的各子树之间的次序是重要的, 不可以交换位置。
森林:0个或多个不相交的树组成。对森林加上一个根,森林即成为树;删去根,树即成为森林。
二叉树是每个节点最多有两个子树的树结构。它有五种基本形态:二叉树可以是空集;根可以有空的左子树或右子树;或者左、右子树皆为空。
二叉树有以下几个性质: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。原命题得证!
定义:高度为h,并且由2{h} –1个结点的二叉树,被称为满二叉树。
定义:一棵二叉树中,只有最下面两层结点的度可以小于2,并且最下一层的叶结点集中在靠左的若干位置上。这样的二叉树称为完全二叉树。
特点:叶子结点只能出现在最下层和次下层,且最下层的叶子结点集中在树的左部。显然,一棵满二叉树必定是一棵完全二叉树,而完全二叉树未必是满二叉树。
定义:二叉查找树(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)。
在实际应用中,二叉查找树的使用比较多。
若二叉树非空,则执行以下操作:
(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
我定义的类如下:
1 template < class T > 2 class BSTNode 3 { 4 public: 5 BSTNode() :left(NULL), right(NULL){ }; 6 ~BSTNode(){ }; 7 8 public: 9 int key; 10 T data; 11 BSTNode * left; 12 BSTNode * right; 13 }; 14 15 template<class T> 16 class BSTree 17 { 18 public: 19 typedef BSTNode<T> * NodePointer; 20 21 public: 22 BSTree(); 23 virtual ~BSTree(); 24 BSTree(const BSTree& orig); 25 BSTree& operator=(const BSTree& orig); 26 bool isEmpty(); 27 void creatBSTree(T * k, T * arr, unsigned len); 28 bool addNode(T k, T val); 29 bool deleteNode(T k); 30 BSTNode<T> * searchNode(T k); 31 void preOrder(); //先序遍历 32 void inOrder(); //中序遍历 33 void postOrder(); //后序遍历 34 void destroy(); // 释放整棵树 35 36 // 单元测试用 37 T getTestData(int pos); 38 39 private: 40 NodePointer root; 41 void destroy(NodePointer parentNode); 42 void preOrder(NodePointer tree); 43 void inOrder(NodePointer tree); 44 void postOrder(NodePointer tree); 45 46 private: 47 // 单元测试用 48 int count; 49 T testData[1024]; 50 51 };
完整实现程序:
1 #include <iostream> 2 #include <cassert> 3 using namespace std; 4 5 template < class T > 6 class BSTNode 7 { 8 public: 9 BSTNode() :left(NULL), right(NULL){ }; 10 ~BSTNode(){ }; 11 12 public: 13 int key; 14 T data; 15 BSTNode * left; 16 BSTNode * right; 17 }; 18 19 template<class T> 20 class BSTree 21 { 22 public: 23 typedef BSTNode<T> * NodePointer; 24 25 public: 26 BSTree(); 27 virtual ~BSTree(); 28 BSTree(const BSTree& orig); 29 BSTree& operator=(const BSTree& orig); 30 bool isEmpty(); 31 void creatBSTree(T * k, T * arr, unsigned len); 32 bool addNode(T k, T val); 33 bool deleteNode(T k); 34 BSTNode<T> * searchNode(T k); 35 void preOrder(); //先序遍历 36 void inOrder(); //中序遍历 37 void postOrder(); //后序遍历 38 void destroy(); // 释放整棵树 39 40 // 单元测试用 41 T getTestData(int pos); 42 43 private: 44 NodePointer root; 45 void destroy(NodePointer parentNode); 46 void preOrder(NodePointer tree); 47 void inOrder(NodePointer tree); 48 void postOrder(NodePointer tree); 49 50 private: 51 // 单元测试用 52 int count; 53 T testData[1024]; 54 55 }; 56 57 template<class T> 58 BSTree<T>::BSTree() 59 { 60 root = NULL; 61 } 62 63 template<class T> 64 BSTree<T>::~BSTree() 65 { 66 destroy(root); 67 root = NULL; // 以防root成为“野指针” 68 } 69 70 template<class T> 71 BSTree<T>::BSTree(const BSTree& orig) 72 { 73 // leave blank 74 } 75 76 77 template<class T> 78 BSTree<T>& BSTree<T>::operator=(const BSTree& orig) 79 { 80 // leave blank 81 return *this; 82 } 83 84 template<class T> 85 bool BSTree<T>::isEmpty() 86 { 87 return root == NULL; 88 } 89 90 template<class T> 91 void BSTree<T>::creatBSTree(T * k, T * arr, unsigned len) 92 { 93 for (int i = 0; i < len; i++) 94 { 95 addNode(k[i], arr[i]); 96 } 97 } 98 99 template<class T> 100 bool BSTree<T>::addNode(T k, T val) 101 { 102 bool isSuccess = true; 103 // to allocate memory 104 // method 1 105 NodePointer ptr = new(nothrow)BSTNode<T>(); 106 if (ptr == NULL) 107 { 108 return false; 109 } 110 // method 2 111 //NodePointer ptr; 112 //try 113 //{ 114 // ptr = new BSTNode<T>(); 115 //} 116 //catch (bad_alloc* e) 117 //{ 118 // return false; 119 //} 120 //catch (exception* e) 121 //{ 122 // return false; 123 //} 124 ptr->key = k; 125 ptr->data = val; 126 if (root == NULL) 127 { 128 root = ptr; 129 } 130 else 131 { 132 NodePointer tmpPtr = root; 133 while (tmpPtr != NULL) 134 { 135 if (k == tmpPtr->key) 136 { 137 isSuccess = false; 138 break; 139 } 140 else if (k < tmpPtr->key) 141 { 142 if (tmpPtr->left == NULL) 143 { 144 tmpPtr->left = ptr; 145 break; 146 } 147 else 148 { 149 tmpPtr = tmpPtr->left; 150 } 151 } 152 else 153 { 154 if (tmpPtr->right == NULL) 155 { 156 tmpPtr->right = ptr; 157 break; 158 } 159 else 160 { 161 tmpPtr = tmpPtr->right; 162 } 163 } 164 } 165 } 166 167 return isSuccess; 168 } 169 170 // 删除某个节点,这时简单地删除包括该节点及其所有儿子 171 template<class T> 172 bool BSTree<T>::deleteNode(T k) 173 { 174 bool isSuccess = true; 175 bool leftOrRight = true; 176 NodePointer ptr = NULL, parentPtr = NULL, tmpPtr = root; 177 while (tmpPtr != NULL) 178 { 179 if (k == tmpPtr->key) 180 { 181 ptr = tmpPtr; 182 break; 183 } 184 else if (k < tmpPtr->key) 185 { 186 if (tmpPtr->left == NULL) 187 { 188 isSuccess = false; 189 break; 190 } 191 else 192 { 193 parentPtr = tmpPtr; 194 tmpPtr = tmpPtr->left; 195 } 196 } 197 else 198 { 199 if (tmpPtr->right == NULL) 200 { 201 isSuccess = false; 202 break; 203 } 204 else 205 { 206 parentPtr = tmpPtr; 207 leftOrRight = false; 208 tmpPtr = tmpPtr->right; 209 } 210 } 211 } 212 213 // 内存释放 214 if (ptr != NULL) 215 { 216 if (ptr == root) 217 { 218 destroy(root); 219 root = NULL; // 以防root成为“野指针” 220 } 221 else 222 { 223 if (leftOrRight) 224 { 225 parentPtr->left = NULL; 226 } 227 else 228 { 229 parentPtr->right = NULL; 230 } 231 destroy(ptr); 232 ptr = NULL; // 以防ptr成为“野指针” 233 } 234 } 235 236 return isSuccess; 237 } 238 239 template<class T> 240 BSTNode<T> * BSTree<T>::searchNode(T k) 241 { 242 NodePointer ptr = NULL, tmpPtr = root; 243 while (tmpPtr != NULL) 244 { 245 if (k == tmpPtr->key) 246 { 247 ptr = tmpPtr; 248 break; 249 } 250 else if (k < tmpPtr->key) 251 { 252 if (tmpPtr->left == NULL) 253 { 254 break; 255 } 256 else 257 { 258 tmpPtr = tmpPtr->left; 259 } 260 } 261 else 262 { 263 if (tmpPtr->right == NULL) 264 { 265 break; 266 } 267 else 268 { 269 tmpPtr = tmpPtr->right; 270 } 271 } 272 } 273 274 return ptr; 275 } 276 277 template<class T> 278 void BSTree<T>::preOrder() 279 { 280 count = 0; 281 preOrder(root); 282 } 283 284 template<class T> 285 void BSTree<T>::preOrder(NodePointer tree) 286 { 287 if (tree != NULL) // 注意这里不是用while循环 288 { 289 // cout << tmpPtr->data << end; 290 testData[count] = tree->data; 291 count++; 292 preOrder(tree->left); 293 preOrder(tree->right); 294 } 295 } 296 297 template<class T> 298 void BSTree<T>::inOrder() 299 { 300 count = 0; 301 inOrder(root); 302 } 303 304 template<class T> 305 void BSTree<T>::inOrder(NodePointer tree) 306 { 307 if (tree != NULL) 308 { 309 inOrder(tree->left); 310 // cout << tmpPtr->data << end; 311 testData[count] = tree->data; 312 count++; 313 inOrder(tree->right); 314 } 315 } 316 317 template<class T> 318 void BSTree<T>::postOrder() 319 { 320 count = 0; 321 postOrder(root); 322 } 323 324 template<class T> 325 void BSTree<T>::postOrder(NodePointer tree) 326 { 327 if (tree != NULL) 328 { 329 postOrder(tree->left); 330 postOrder(tree->right); 331 // cout << tmpPtr->data << end; 332 testData[count] = tree->data; 333 count++; 334 } 335 } 336 337 template<class T> 338 void BSTree<T>::destroy() 339 { 340 destroy(root); 341 root = NULL; 342 } 343 344 template<class T> 345 void BSTree<T>::destroy(NodePointer parentNode) 346 { 347 NodePointer leftPtr = NULL, rightPtr = NULL; 348 if (parentNode != NULL) 349 { 350 leftPtr = parentNode->left; 351 rightPtr = parentNode->right; 352 delete parentNode; 353 parentNode = NULL; // 这一句十分重要。因为parentNode被释放后成为一个 354 // “野指针”,即不是NULL指针,因此会让while循环 355 // 在释放完所有的内存后再循环一次,而此时parentNode 356 // 已经是一个“野指针”,对它再进行内存释放必然出错 357 destroy(leftPtr); 358 destroy(rightPtr); 359 } 360 361 } 362 363 template<class T> 364 T BSTree<T>::getTestData(int pos) 365 { 366 return testData[pos]; 367 }
Boost单元测试程序:
1 #define BOOST_TEST_MODULE BinaryTree_Test_Module 2 3 #include "stdafx.h" 4 #include "../BSTree/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(BinTree_Test_Suite, BSTree_Fixture) 22 23 BOOST_AUTO_TEST_CASE( BinTree_Nomal_Test ) 24 { 25 // isEmpty ------------------------------------- 26 BOOST_REQUIRE(testBSTree->isEmpty() == true); 27 28 // addNode & searchNode --------------------------- 29 BOOST_REQUIRE(testBSTree->addNode(1, 1) == true); 30 BOOST_REQUIRE(testBSTree->searchNode(1) != NULL); 31 BOOST_REQUIRE((testBSTree->searchNode(1))->data == 1); 32 BOOST_REQUIRE(testBSTree->isEmpty() == false); 33 34 BOOST_REQUIRE(testBSTree->addNode(0, 0) == true); 35 BOOST_REQUIRE(testBSTree->searchNode(0) != NULL); 36 BOOST_REQUIRE((testBSTree->searchNode(0))->data == 0); 37 38 BOOST_REQUIRE(testBSTree->addNode(2, 2) == true); 39 BOOST_REQUIRE(testBSTree->searchNode(2) != NULL); 40 BOOST_REQUIRE((testBSTree->searchNode(2))->data == 2); 41 42 BOOST_REQUIRE(testBSTree->addNode(3, 3) == true); 43 BOOST_REQUIRE(testBSTree->searchNode(3) != NULL); 44 BOOST_REQUIRE((testBSTree->searchNode(3))->data == 3); 45 46 // deleteNode ---------------------------------- 47 BOOST_REQUIRE(testBSTree->deleteNode(0) == true); 48 BOOST_REQUIRE(testBSTree->searchNode(0) == NULL); 49 BOOST_REQUIRE(testBSTree->searchNode(1)->data == 1); 50 BOOST_REQUIRE(testBSTree->searchNode(2)->data == 2); 51 BOOST_REQUIRE(testBSTree->searchNode(3)->data == 3); 52 53 BOOST_REQUIRE(testBSTree->deleteNode(3) == true); 54 BOOST_REQUIRE(testBSTree->searchNode(3) == NULL); 55 BOOST_REQUIRE(testBSTree->searchNode(1)->data == 1); 56 BOOST_REQUIRE(testBSTree->searchNode(2)->data == 2); 57 58 BOOST_REQUIRE(testBSTree->deleteNode(1) == true); 59 BOOST_REQUIRE(testBSTree->searchNode(1) == NULL); 60 BOOST_REQUIRE(testBSTree->searchNode(2) == NULL); 61 62 // creatBSTree -------------------------------- 63 int key[] = { 1, 0, 2, 3 }; 64 int value[] = { 1, 0, 2, 3 }; 65 unsigned len = sizeof(key) / sizeof(int); 66 testBSTree->creatBSTree(key, value, len); 67 68 // preOrder ------------------------------------ 69 testBSTree->preOrder(); 70 BOOST_REQUIRE(testBSTree->getTestData(0) == 1); 71 BOOST_REQUIRE(testBSTree->getTestData(1) == 0); 72 BOOST_REQUIRE(testBSTree->getTestData(2) == 2); 73 BOOST_REQUIRE(testBSTree->getTestData(3) == 3); 74 75 // inOrder ------------------------------------- 76 testBSTree->inOrder(); 77 BOOST_REQUIRE(testBSTree->getTestData(0) == 0); 78 BOOST_REQUIRE(testBSTree->getTestData(1) == 1); 79 BOOST_REQUIRE(testBSTree->getTestData(2) == 2); 80 BOOST_REQUIRE(testBSTree->getTestData(3) == 3); 81 82 // postOrder ----------------------------------- 83 testBSTree->postOrder(); 84 BOOST_REQUIRE(testBSTree->getTestData(0) == 0); 85 BOOST_REQUIRE(testBSTree->getTestData(1) == 3); 86 BOOST_REQUIRE(testBSTree->getTestData(2) == 2); 87 BOOST_REQUIRE(testBSTree->getTestData(3) == 1); 88 89 // destroy ------------------------------------- 90 testBSTree->destroy(); 91 92 } 93 94 BOOST_AUTO_TEST_CASE(BinTree_CopyConstructor_Test) 95 { 96 // leave blank 97 } 98 99 BOOST_AUTO_TEST_CASE(BinTree_EqualOperator_Test) 100 { 101 // leave blank 102 } 103 104 BOOST_AUTO_TEST_SUITE_END()
另一可参考程序:http://www.2cto.com/kf/201311/259072.html
本篇博文的代码均托管到Taocode : http://code.taobao.org/p/datastructureandalgorithm/src/.
标签:des style blog http io color ar os 使用
原文地址:http://www.cnblogs.com/xiehongfeng100/p/4093815.html