数据结构和算法理解很简单,深感算法导论的介绍更是精辟而无累赘。
例如:1. 直接切入二叉搜索树,而不是从树开始介绍各种繁琐的表示方式,最后的重点结果还是二叉搜索和几种平衡树,算法导论介绍知识的时候数学性虽强,但应用性也十足,它的 应用性不在于给你代码,而在于给你应用的场景,告诉你各种结构的优劣和代价,这才是学习数据结构和算法应该掌握的精华,而不在一些教材上展示的可以称之为垃圾的代 码上,实际上,关于数据结构的实现代码,工业级的STL源码可以给你最高屋建瓴的精华。
2. 遍历方法仅重点分析中序遍历,为何?因为按照二叉搜索树的性质其中序即使orderd,其它序也有作用,比如某一道习题提到的位二叉树,其pre-order才是orderd,但 比上来让你实现几个遍历,滚瓜烂熟之后也不知在何处用(只会用来display数据除外);
3. 不止一次在网上看到人们评价算导的数据结构部分过于简单,又跑回去啃严版教材,实乃买椟还珠,为何他们觉得简单,我简单分析一下,认为他们一不做或者不思考习题, 对于二叉搜索树而言,最难的(其实也不难)地方在于迭代遍历(pre,in,post),算法导论的习题中不仅有,而且还提出一种使用stack模拟,另一种不借助stack,要求 读者独立完成。倘使不做,自然无法得其中奥义,只能回去啃别人代码,一读便懂,回头即忘。
所以就我个人阅读感受而言,算法导论一书造诣颇高,比大多数相关书籍不知道高明多少,十分推荐。
我在以前只学习数据结构的时候就已经用模板实现了二叉搜索树,但是看完算法导论再加之一些STL源码的阅读体验,感觉之前的代码臭不可闻,接口错乱,实现冗杂,实乃错误之典范,究其根本还在于理解了但是不明白用来干嘛。当然,我偶然搜索了一下,发现大多数学习者在互相抄袭,完全相同的代码和用词出现在了好多的博文上,而其抄袭的代码本身也不是什么优秀之作。既然是学习,不管好与坏,自己做得才有进步,复制粘贴就。。。
所以最近得空重新实现一下,虽然还是有诸多不满之处,但比之前要好很多了。
下面在代码中分析一下:(设置为虚函数的函数是要做red-black tree中重新给出实现的操作)
算法的部分不难,理解之后还有很多设计上的问题,即接口和实现的分离、node类和tree类之间的耦合和内聚等等。
自己从头撸一个,还是有一些好处的。
1 #include<iostream> 2 using namespace std; 3 4 //结点类 5 template<typename T> 6 class TreeNode 7 { 8 //声明为二叉搜索树的友元类 9 template<class T> friend class BinarySearchTree; 10 //方便<<操作符访问结点成员 11 template<typename T> friend ostream& operator<<(ostream &os, BinarySearchTree<T>&BST); 12 13 private: 14 T value; 15 TreeNode<T>* lchild; 16 TreeNode<T>* rchild; 17 TreeNode<T>* parent;//带parent结点要方便的多 18 19 TreeNode<T>* _increase();//自增,即中序下的后继 20 TreeNode<T>* _decrease();//自减,即中序下的前驱 21 public: 22 //三个构造函数 23 TreeNode() :value(0), lchild(NULL), rchild(NULL),parent(NULL){} 24 TreeNode(T v) :value(v), lchild(NULL), rchild(NULL),parent(NULL){} 25 TreeNode(TreeNode<T> &node) :value(node.value), lchild(node.lchild), rchild(node.rchild),parent(node.parent){} 26 virtual ~TreeNode(){} //析构函数设置为虚函数 27 void _test_display() //此函数只是测试使用,应该删去 28 { 29 cout << "value: " << this->value<<" "; 30 if (this->lchild!=NULL) 31 cout <<"lchild: "<< this->lchild->value<<" "; 32 else cout << "lchild: NULL"<<" "; 33 if (this->rchild != NULL) 34 cout << "rchild: " << this->rchild->value << " "; 35 else cout << "rchild: NULL" << " "; 36 if (this->parent != NULL) 37 cout << "parent: " << this->parent->value << " "; 38 else cout << "parent: NULL" << " "; 39 cout << endl; 40 } 41 42 }; 43 44 //二叉搜索树类 45 template<typename T> 46 class BinarySearchTree 47 { 48 49 private: 50 TreeNode<T> *root; //根节点 51 int size; //结点数量 52 53 TreeNode<T>* _copy(TreeNode<T> *node,TreeNode<T>* q); //私有函数,node表示复制以node为根节点的树,参数q实际上指向node的父节点,是实现的小技巧 54 TreeNode<T>* _mininum(TreeNode<T>* node); //私有函数,找到以node为根节点的树中的最小结点 55 TreeNode<T>* _maxinum(TreeNode<T>* node); 56 57 virtual TreeNode<T>* _insert(T& value,TreeNode<T>* node);//私有函数,用于实现Insert操作 58 virtual void _delete(TreeNode<T>* _delete_node,TreeNode<T>* node);//私有函数,用于实现Delete操作 59 TreeNode<T>* _search(T& value, TreeNode<T>* node); //私有函数,用于实现Search操作 60 virtual void _init(T* array,int length); //通过数组初始化二叉搜索树 61 virtual void _clear(TreeNode<T>* node); //清空node为根节点的树 62 63 64 65 public: 66 //构造和析构函数 67 BinarySearchTree() :root(NULL), size(0){} 68 BinarySearchTree(T* array, int length) { _init(array, length); } 69 BinarySearchTree(BinarySearchTree<T> &tree){ root = _copy(tree.root, NULL); size = tree.size; } 70 virtual ~BinarySearchTree() { _clear(root); size = 0; } 71 //赋值操作符的重载 72 virtual BinarySearchTree<T>& operator=(BinarySearchTree<T> &tree){ _clear(root); root = _copy(tree.root, NULL); size = tree.size; return *this; } 73 //判断树是否为空 74 bool isEmpty() { return size == 0; } 75 //返回树中结点个数 76 int Size() { return size; } 77 //基本操作,Insert、Delete、Search 78 virtual TreeNode<T>* Insert(T& value){ return _insert(value, root); } 79 virtual void Delete(TreeNode<T>* node){ return _delete(node, root); } 80 TreeNode<T>* Search(T& value){ return _search(value, root); } 81 82 //返回树中value最大和最小的结点的value 83 T& mininum(){ return _mininum(root)->value; } 84 T& maxinum(){ return _maxinum(root)->value; } 85 //返回某个节点的parent 86 TreeNode<T>* parent(TreeNode<T> *node){ return node->parent; } 87 //<<操作符必须设置为友元,不可以是成员 88 template<typename T> friend ostream& operator<<(ostream &os, BinarySearchTree<T>&BST); 89 90 //一个测试函数 91 void __test(){ cout << "测试_ decrease" << --(this->root->rchild->lchild->lchild)->value << endl; }; 92 93 }; 94 95 template<typename T> 96 TreeNode<T>* BinarySearchTree<T>::_copy(TreeNode<T>* node,TreeNode<T>* q) 97 { 98 //这里q保存node的父节点,调用时初始化为NULL(root的parent为NULL) 99 100 if (node == NULL) 101 return NULL; 102 103 TreeNode<T>* p = new TreeNode<T>(node->value); 104 p->parent = q; 105 p->lchild = _copy(node->lchild,p);//递归复制 106 p->rchild = _copy(node->rchild,p); 107 return p; 108 } 109 110 111 template<typename T> 112 TreeNode<T>* BinarySearchTree<T>::_mininum(TreeNode<T>* node)//最左端结点为最小 113 { 114 TreeNode<T> * p = node; 115 TreeNode<T>* q=NULL; 116 while (p != NULL) 117 { 118 q = p; 119 p = p->lchild; 120 } 121 return q; 122 } 123 template<typename T> 124 TreeNode<T>* BinarySearchTree<T>::_maxinum(TreeNode<T>* node)//最右端结点为最大 125 { 126 TreeNode<T>* p = node; 127 TreeNode<T>* q = NULL; 128 while(p != NULL) 129 { 130 q= p; 131 p = p->rchild; 132 } 133 return q; 134 } 135 template<typename T> 136 TreeNode<T>* TreeNode<T>::_increase() 137 { 138 if (this == NULL) 139 return NULL; 140 else 141 { 142 if (this->rchild != NULL) //当前结点如果有右孩子,则后继为右子树中最小的结点 143 { 144 TreeNode<T> * p = this->rchild; 145 TreeNode<T>* q=p; 146 while (p != NULL) 147 { 148 q= p; 149 p = p->lchild; 150 } 151 152 return q; 153 } 154 else //否则,则向上回溯,直到第一次出现 q 是 p 的左孩子结点为止 155 { 156 TreeNode<T> *q = this; 157 TreeNode<T> *p = this->parent; 158 //cout<<"parent:" << p->value << endl; 159 //cout <<"cur: "<< q->value << endl; 160 while(q != p->lchild) 161 { 162 q = p; 163 p = p->parent; 164 if (p == NULL) 165 break; 166 } 167 //cout << "parent: " << p->value << endl; 168 169 return p; 170 } 171 } 172 173 } 174 template<typename T> 175 TreeNode<T>* TreeNode<T>::_decrease() 176 { 177 if (this == NULL) 178 return NULL; 179 else 180 { 181 if (this->lchild != NULL) //当前结点如果有左孩子,则后继为右子树中最大的结点 182 { 183 TreeNode<T> *p = this->lchild; 184 TreeNode<T> *q = p; 185 while (p != NULL) 186 { 187 q = p; 188 p = p->rchild; 189 } 190 return q; 191 } 192 else //否则,则向上回溯,直到第一次出现 q 是 p 的右孩子结点为止 193 { 194 TreeNode<T> *q = this; 195 TreeNode<T> *p = this->parent; 196 while (q != p->rchild) 197 { 198 q = p; 199 p = p->parent; 200 if (p == NULL) 201 break; 202 } 203 return p; 204 } 205 } 206 207 } 208 209 template<typename T> 210 TreeNode<T>* BinarySearchTree<T>::_insert(T& value, TreeNode<T>* node) //insert操作的返回值为指向插入结点的指针 211 { 212 TreeNode<T> *p = new TreeNode<T>(value); 213 TreeNode<T> *parent_node = NULL; 214 215 while (node != NULL) 216 { 217 if (p->value < node->value) 218 { 219 parent_node = node; 220 node = node->lchild; 221 } 222 else 223 { 224 parent_node = node; 225 node = node->rchild; 226 } 227 } 228 // 找到待插入结点parent_node 229 if (parent_node != NULL) 230 { 231 p->parent = parent_node; 232 if (p->value < parent_node->value) 233 { 234 parent_node->lchild = p; 235 } 236 else 237 { 238 parent_node->rchild = p; 239 } 240 } 241 else //当前树为空 242 { 243 root=p; 244 } 245 return p; 246 247 } 248 template<typename T> 249 void BinarySearchTree<T>::_delete(TreeNode<T>* _delete_node, TreeNode<T>* node) 250 { 251 TreeNode<T> *y, *x; 252 if (_delete_node->lchild == NULL || _delete_node->rchild == NULL) //如果待删除结点有一个孩子或者没有孩子,那么要被移除的结点就是它自己 253 y = _delete_node; 254 else y = _delete_node->_increase(); //如果有两个结点,那么要移除的结点就是它的后继(然后把它的后继的value赋值给它) 255 256 if (y->lchild != NULL) 257 x = y->lchild; //如果y的左孩子不空的话,赋值给x 258 else x = y->rchild; //否则,无论是右孩子空不空,都赋值给x 259 260 TreeNode<T> *parent_of_y = parent(y); 261 262 if (y != _delete_node) 263 { 264 _delete_node->value = y->value; 265 x->parent = parent_of_y; 266 if (y == parent_of_y->lchild) 267 parent_of_y->lchild = x; 268 else 269 parent_of_y->rchild = x; 270 delete y; 271 } 272 else 273 { 274 x->parent = parent_of_y; 275 if (parent_of_y == NULL) 276 { 277 node = x; 278 279 delete y; 280 } 281 else 282 { 283 if (parent_of_y->lchild == y) 284 parent_of_y->lchild = x; 285 else 286 parent_of_y->rchild = x; 287 delete y; 288 } 289 } 290 291 } 292 template<typename T> 293 TreeNode<T>* BinarySearchTree<T>::_search(T& value, TreeNode<T>* node) //search是其最擅长的操作,返回值为找到结点的指针 294 { 295 TreeNode<T>* p = node; 296 while (p != NULL) 297 { 298 if (value < p->value) 299 p = p->lchild; 300 else if (value > p->value) 301 p = p->rchild; 302 else return p; 303 } 304 return NULL; 305 } 306 template<typename T> 307 void BinarySearchTree<T>::_init(T* array,int length) //反复调用insert操作来初始化,并且增大size 308 { 309 310 for (int i = 0; i < length; ++i) 311 { 312 _insert(array[i], root); 313 ++size; 314 } 315 } 316 317 template<typename T> 318 void BinarySearchTree<T>::_clear(TreeNode<T>* node) //递归调用来删除 319 { 320 if (node == NULL) 321 return; 322 323 TreeNode<T>* p = node->lchild; 324 TreeNode<T>* q = node->rchild; 325 delete node; 326 _clear(p); 327 _clear(q); 328 } 329 330 template<typename T> 331 ostream& operator<<(ostream &os, BinarySearchTree<T>& BST) //这里其实是一个迭代版(不用辅助stack)的方法 332 { 333 TreeNode<T>* node = BST.root; 334 while (true) 335 { 336 if (node->lchild != NULL) //一直访问到当前最左边结点 337 node = node->lchild; 338 else 339 { 340 os << node->value << " "; //输出当前结点的value 341 while (node->rchild == NULL) //如果无右孩子,则访问其后继,注意这里是循环 342 { 343 344 node=node->_increase(); 345 346 if (node != NULL) 347 os << node->value << " "; 348 else break; 349 } 350 if (node !=NULL) //如果有右孩子,访问其右孩子(这里是一个尾递归优化而来的迭代,容易理解) 351 { 352 node = node->rchild; 353 } 354 else break; 355 356 } 357 358 } 359 return os; 360 } 361 int main() 362 { 363 const int length = 9; 364 int array[length] = { 13,9,17,5,12,15,18,2,19}; 365 //检测_init _insert operator<< _increase 366 BinarySearchTree<int> BST(array, length); 367 cout <<"BST: "<< BST << endl; 368 int v = 14; 369 BST.Insert(v); 370 cout<<"BST insert one node with value 14: " << BST << endl; 371 372 373 //检测_copy,okay 374 BinarySearchTree<int> Bst(BST); 375 cout << Bst << endl; 376 377 //检测operator=,okay 378 BinarySearchTree<int> bst,bsT; 379 bsT= bst = Bst; 380 cout <<"!"<< bst<<endl; 381 cout <<"!"<< bsT << endl; 382 383 //检测_mininum _maxinum,okay 384 cout << "maxinum" << BST.maxinum()<<endl; 385 cout << "mininum" << BST.mininum()<<endl; 386 387 //检测 _decrease,okay 388 BST.__test(); 389 390 //检测_search,okay 391 TreeNode<int> *p=BST.Search(array[0]); 392 p->_test_display(); 393 p = BST.Search(array[7]); 394 p->_test_display(); 395 p = BST.Search(array[8]); 396 p->_test_display(); 397 398 399 //检测_delete,okay 400 p = BST.Search(array[2]); 401 BST.Delete(p); 402 cout << "delete the node with value 17"<<endl; 403 cout << BST << endl; 404 405 //测试size 406 cout <<"BST size: "<< BST.Size() << endl; 407 cout <<"bsT size: "<< bsT.Size() << endl; 408 system("pause"); 409 410 }
BinarySearchTree示例——C++模板实现