二叉树基础--创建、遍历方法(前序/中序/后序/层序、递归/非递归)
【作者:Dillonn 出处: http://www.cnblogs.com/Dillonn/p/4226929.html 欢迎转载,请务必保留本行】
二叉树的创建及遍历是很多二叉树问题的基础,递归遍历逻辑清晰,代码简约漂亮,然则效率低下(所有递归方案的通病,非不得已不用递归);
非递归遍历高效,却不是能信手写出来的,特别是后续非递归遍历,相信很多资深码工也有这样的经历:
5年前学习了二叉树的非递归遍历,一个月前复习了并达到能熟练写出的程度,在不参考任何资料的情况下,今天却怎样也写不出来。
如果你也有过这种经历,恭喜,这说明你是一个正常人类……
另一方面市面上有些国人写的教材,各种语法、逻辑错误层出不起,不知祸害了多少未来的码工,深感痛心。
印象比较深刻的有清华大学出版社出版的《数据结果(C++版)》 王红梅、胡明、王涛编著。
如书中第163页后序非递归遍历方法,短短不到30行代码各种语法、逻辑错误如下:
1 template <typename T> 2 void BiTree::PostOrder(BiNode<T> * root)//错误一:正确的写法为void BiTree<T>::PostOrder(BiNode<T> * root) 3 { 4 top = -1; 5 //错误二:应该在这里定义下文用到的栈s(书中说这是具体的代码,不是伪代码)。 6 wihle(root != NULL || top != -1) 7 { 8 while(root != NULL) 9 { 10 top++; 11 s[top].ptr = root; 12 s[top].flag = 1; 13 root = root -> lchild; 14 } 15 while(top != -1 && s[top].flag ==2) 16 { 17 root = s[top--].ptr; 18 cout << root->data; 19 } 20 if(top != -1) 21 { 22 s[top].flag = 2; 23 root = s[top].ptr->rchild; 24 } 25 //错误三:致命逻辑错误,栈空时,遍历结束,退出外层循环或函数返回,否则将进入死循环,应该加上如下一行代码。 26 else break;//书中没有这一行 27 } 28 }
下面咱们来实现一个二叉树Class,在Class中实现以下方法:
1.创建一颗二叉树;
2.销毁一颗二叉树;
3.递归前序遍历方法;
4.非递归前序遍历方法;
5.递归中序遍历方法;
6.非递归中序遍历方法;
7.递归后序遍历方法;
8.非递归后序遍历方法;
9.层序遍历方法(这个应该就没有递归的方法)。
要点:非递归遍历用栈辅助(深度优先),层序遍历用队列辅助(广度优先)。
二叉树节点定义:
1 template <typename T> 2 struct BiNode 3 { 4 T data; 5 BiNode<T> *pLeft; 6 BiNode<T> *pRight; 7 };
二叉树Class定义:
要点:1.数据成员申明为私有;
2. 公有成员方法如PreOrder1()为对外接口,调用私有成员方法PreOrderRecursive(BiNode<T> * root)实现其具体功能。
1 template <typename T> 2 class BiTree 3 { 4 public: 5 BiTree(); 6 ~BiTree(); 7 void PreOrder1();//递归 8 void PreOrder2();//非递归 9 void InOrder1();//递归 10 void InOrder2();//非递归 11 void PostOrder1();//递归 12 void PostOrder2();//非递归 13 void LevelOrder(); 14 private: 15 BiNode<T> * root; 16 void CreateBiTree(BiNode<T> * &root); 17 void ReleaseBiTree(BiNode<T> * root); 18 19 void PreOrderRecursive(BiNode<T> * root); 20 void PreOrderNonRecursive(BiNode<T> * root); 21 22 void InOrderRecursive(BiNode<T> * root); 23 void InOrderNonRecursive(BiNode<T> * root); 24 25 void PostOrderRecursive(BiNode<T> * root); 26 void PostOrderNonRecursive(BiNode<T> * root); 27 28 void LevelOrder(BiNode<T> * root); 29 };
创建二叉树:
1 template <typename T> 2 void BiTree<T>::CreateBiTree( BiNode<T> * &root)// 根据前序遍历次序创建二叉树 3 { 4 T data; 5 cin>>data; 6 if(data == INVALID) 7 { 8 root = NULL; 9 } 10 else 11 { 12 root = new BiNode<T>; 13 root->data = data; 14 CreateBiTree(root->pLeft); 15 CreateBiTree(root->pRight); 16 } 17 } 18 19 20 template <typename T> 21 BiTree<T>::BiTree():root(NULL) 22 { 23 CreateBiTree(root); 24 }
销毁二叉树:
1 template <typename T> 2 void BiTree<T>::ReleaseBiTree(BiNode<T> * root) 3 { 4 if(root != NULL) 5 { 6 ReleaseBiTree(root->pLeft); 7 ReleaseBiTree(root->pRight); 8 delete root; 9 } 10 } 11 12 13 template <typename T> 14 BiTree<T>::~BiTree() 15 { 16 ReleaseBiTree(root); 17 }
前序递归遍历:
1 template <typename T> 2 void BiTree<T>::PreOrderRecursive(BiNode<T> * root) 3 { 4 if(root != NULL) 5 { 6 cout<<root->data<<" "; 7 PreOrderRecursive(root->pLeft); 8 PreOrderRecursive(root->pRight); 9 } 10 } 11 12 13 14 template <typename T> 15 void BiTree<T>::PreOrder1() 16 { 17 PreOrderRecursive(root); 18 cout<<endl; 19 }
中序递归遍历:
1 template <typename T> 2 void BiTree<T>::InOrderRecursive(BiNode<T> * root) 3 { 4 if(root != NULL) 5 { 6 InOrderRecursive(root->pLeft); 7 cout<<root->data<<" "; 8 InOrderRecursive(root->pRight); 9 } 10 } 11 12 13 template <typename T> 14 void BiTree<T>::InOrder1() 15 { 16 InOrderRecursive(root); 17 cout<<endl; 18 }
后序递归遍历:
1 template <typename T> 2 void BiTree<T>::PostOrderRecursive(BiNode<T> * root) 3 { 4 if(root != NULL) 5 { 6 PostOrderRecursive(root->pLeft); 7 PostOrderRecursive(root->pRight); 8 cout<<root->data<<" "; 9 } 10 } 11 12 13 template <typename T> 14 void BiTree<T>::PostOrder1() 15 { 16 PostOrderRecursive(root); 17 cout<<endl; 18 }
层序遍历:
1 template <typename T> 2 void BiTree<T>::LevelOrder(BiNode<T> * root) 3 { 4 BiNode<T> * p; 5 queue<BiNode<T> *> q; 6 if(root == NULL) 7 return; 8 q.push(root); 9 while(!q.empty()) 10 { 11 p = q.front(); 12 cout << p->data<<" "; 13 q.pop(); 14 if(p->pLeft != NULL) q.push(p->pLeft); 15 if(p->pRight != NULL) q.push(p->pRight); 16 } 17 } 18 19 template <typename T> 20 void BiTree<T>::LevelOrder() 21 { 22 LevelOrder(root); 23 cout<<endl; 24 }
前序非递归遍历:
1 template <typename T> 2 void BiTree<T>:: PreOrderNonRecursive(BiNode<T> * root) 3 { 4 stack<BiNode<T> *> s; 5 while(root != NULL || !s.empty()) 6 { 7 while(root != NULL) 8 { 9 cout<<root->data<<" "; 10 s.push(root); 11 root = root->pLeft; 12 } 13 if(!s.empty()) 14 { 15 root = s.top(); 16 s.pop(); 17 root = root->pRight; 18 } 19 } 20 21 } 22 23 24 25 26 template <typename T> 27 void BiTree<T>::PreOrder2() 28 { 29 PreOrderNonRecursive(root); 30 cout<<endl; 31 }
中序非递归遍历:
1 template <typename T> 2 void BiTree<T>::InOrderNonRecursive(BiNode<T> * root) 3 { 4 stack<BiNode<T> *> s; 5 while(root != NULL || !s.empty()) 6 { 7 while(root != NULL) 8 { 9 s.push(root); 10 root = root->pLeft; 11 } 12 if(!s.empty()) 13 { 14 root = s.top(); 15 s.pop(); 16 cout<<root->data<<" "; 17 root = root->pRight; 18 } 19 } 20 21 } 22 23 24 25 template <typename T> 26 void BiTree<T>::InOrder2() 27 { 28 InOrderNonRecursive(root); 29 cout<<endl; 30 }
后序非递归遍历:
1 template <typename T> 2 void BiTree<T>::PostOrderNonRecursive(BiNode<T> * root) 3 { 4 5 stack<BiNode<T> *> s1; 6 stack<int> s2;//s2辅助记录s1相应位置的元素的状态:s1、s2保持同步。 7 8 while(root != NULL || !s1.empty()) 9 { 10 while(root != NULL) 11 { 12 s1.push(root); 13 s2.push(1); 14 root = root->pLeft; 15 } 16 if(!s1.empty()) 17 { 18 if(s2.top()==1) 19 { 20 s2.pop(); 21 s2.push(2); 22 root = s1.top()->pRight; 23 } 24 else 25 { 26 root = s1.top(); 27 s1.pop(); 28 s2.pop(); 29 cout<<root->data<<" "; 30 root = NULL; 31 } 32 } 33 34 } 35 36 } 37 38 39 40 template <typename T> 41 void BiTree<T>::PostOrder2() 42 { 43 PostOrderNonRecursive(root); 44 cout<<endl; 45 }
假定我们创建的二叉树形状如下:
1 /* 2 假定所创建的二叉树如下图所示 3 A 4 / \ 5 B C 6 / \ / 7 D E F 8 \ 9 G 10 11 12 创建二叉树的文件:《BiTree.txt》内容如下: 13 A B D # # E # G # # C F # # # 14 15 */ 16 const char *preorder = "A B D E G C F"; 17 const char *inorder = "D B E G A F C"; 18 const char *postorder = "D G E B F C A"; 19 const char *levelorder= "A B C D E F G";
main函数:
1 int main() 2 { 3 ifstream fin("BiTree.txt");// 输入文件 4 ofstream fout("out.txt"); //输出文件 5 6 streambuf *cinbackup; 7 streambuf *coutbackup; 8 9 cinbackup= cin.rdbuf(fin.rdbuf()); //用 rdbuf() 重新定向 10 coutbackup= cout.rdbuf(fout.rdbuf()); //用 rdbuf() 重新定向 11 12 BiTree<char> *pbitree = new BiTree<char>;//创建一颗二叉树 13 14 cout << "*preorder = " << preorder << endl; 15 cout << " PreOrder1(): "; 16 pbitree->PreOrder1(); 17 cout << " PreOrder2(): "; 18 pbitree->PreOrder2(); 19 cout<<endl; 20 21 cout << "*inorder = " << inorder << endl; 22 cout << " inorder1(): "; 23 pbitree->InOrder1(); 24 cout << " InOrder2(): "; 25 pbitree->InOrder2(); 26 cout<<endl; 27 28 cout << "*postorder = " << postorder << endl; 29 cout << " PostOrder1(): "; 30 pbitree->PostOrder1(); 31 cout << " PostOrder2(): "; 32 pbitree->PostOrder2(); 33 cout<<endl; 34 35 cout << "*levelorder = " << levelorder << endl; 36 cout << " LevelOrder(): "; 37 pbitree->LevelOrder(); 38 39 delete pbitree; 40 cin.rdbuf(cinbackup); // 取消,恢复键盘输入 41 cout.rdbuf(coutbackup); //取消,恢复屏幕输出 42 return 0; 43 }
MVS2005上的运行结果如下图:
完整的代码:
1 #include <iostream> 2 #include <fstream> 3 #include <stack> 4 #include <queue> 5 6 using namespace std; 7 8 9 /* 10 假定所创建的二叉树如下图所示 11 A 12 / \ 13 B C 14 / \ / 15 D E F 16 \ 17 G 18 19 20 创建二叉树的文件:《BiTree.txt》内容如下: 21 A B D # # E # G # # C F # # # 22 23 */ 24 const char *preorder = "A B D E G C F"; 25 const char *inorder = "D B E G A F C"; 26 const char *postorder = "D G E B F C A"; 27 const char *levelorder= "A B C D E F G"; 28 29 const char INVALID = '#';//INVALID在CreateBiTree()函数中表示空节点,类型适配 template <typename T> 30 31 template <typename T> 32 struct BiNode 33 { 34 T data; 35 BiNode<T> *pLeft; 36 BiNode<T> *pRight; 37 // BiNode():data(0){cout<<"BiNode Constructor"<<endl;}; 38 // ~BiNode(){cout<<"BiNode Destructor"<<endl;}; 39 }; 40 41 template <typename T> 42 class BiTree 43 { 44 public: 45 BiTree(); 46 ~BiTree(); 47 void PreOrder1();//递归 48 void PreOrder2();//非递归 49 void InOrder1();//递归 50 void InOrder2();//非递归 51 void PostOrder1();//递归 52 void PostOrder2();//非递归 53 void LevelOrder(); 54 private: 55 BiNode<T> * root; 56 void CreateBiTree(BiNode<T> * &root); 57 void ReleaseBiTree(BiNode<T> * root); 58 59 void PreOrderRecursive(BiNode<T> * root); 60 void PreOrderNonRecursive(BiNode<T> * root); 61 62 void InOrderRecursive(BiNode<T> * root); 63 void InOrderNonRecursive(BiNode<T> * root); 64 65 void PostOrderRecursive(BiNode<T> * root); 66 void PostOrderNonRecursive(BiNode<T> * root); 67 68 void LevelOrder(BiNode<T> * root); 69 }; 70 71 72 template <typename T> 73 void BiTree<T>::CreateBiTree( BiNode<T> * &root)// 根据前序遍历次序创建二叉树 74 { 75 T data; 76 cin>>data; 77 if(data == INVALID) 78 { 79 root = NULL; 80 } 81 else 82 { 83 root = new BiNode<T>; 84 root->data = data; 85 CreateBiTree(root->pLeft); 86 CreateBiTree(root->pRight); 87 } 88 } 89 90 91 template <typename T> 92 void BiTree<T>::ReleaseBiTree(BiNode<T> * root) 93 { 94 if(root != NULL) 95 { 96 ReleaseBiTree(root->pLeft); 97 ReleaseBiTree(root->pRight); 98 delete root; 99 } 100 } 101 102 103 template <typename T> 104 BiTree<T>::BiTree():root(NULL) 105 { 106 CreateBiTree(root); 107 } 108 109 110 template <typename T> 111 BiTree<T>::~BiTree() 112 { 113 ReleaseBiTree(root); 114 } 115 116 117 template <typename T> 118 void BiTree<T>::PreOrderRecursive(BiNode<T> * root) 119 { 120 if(root != NULL) 121 { 122 cout<<root->data<<" "; 123 PreOrderRecursive(root->pLeft); 124 PreOrderRecursive(root->pRight); 125 } 126 } 127 128 129 template <typename T> 130 void BiTree<T>:: PreOrderNonRecursive(BiNode<T> * root) 131 { 132 stack<BiNode<T> *> s; 133 while(root != NULL || !s.empty()) 134 { 135 while(root != NULL) 136 { 137 cout<<root->data<<" "; 138 s.push(root); 139 root = root->pLeft; 140 } 141 if(!s.empty()) 142 { 143 root = s.top(); 144 s.pop(); 145 root = root->pRight; 146 } 147 } 148 149 } 150 151 152 template <typename T> 153 void BiTree<T>::PreOrder1() 154 { 155 PreOrderRecursive(root); 156 cout<<endl; 157 } 158 159 160 template <typename T> 161 void BiTree<T>::PreOrder2() 162 { 163 PreOrderNonRecursive(root); 164 cout<<endl; 165 } 166 167 168 template <typename T> 169 void BiTree<T>::InOrderRecursive(BiNode<T> * root) 170 { 171 if(root != NULL) 172 { 173 InOrderRecursive(root->pLeft); 174 cout<<root->data<<" "; 175 InOrderRecursive(root->pRight); 176 } 177 } 178 179 180 template <typename T> 181 void BiTree<T>::InOrderNonRecursive(BiNode<T> * root) 182 { 183 stack<BiNode<T> *> s; 184 while(root != NULL || !s.empty()) 185 { 186 while(root != NULL) 187 { 188 s.push(root); 189 root = root->pLeft; 190 } 191 if(!s.empty()) 192 { 193 root = s.top(); 194 s.pop(); 195 cout<<root->data<<" "; 196 root = root->pRight; 197 } 198 } 199 200 } 201 202 203 template <typename T> 204 void BiTree<T>::InOrder1() 205 { 206 InOrderRecursive(root); 207 cout<<endl; 208 } 209 210 211 template <typename T> 212 void BiTree<T>::InOrder2() 213 { 214 InOrderNonRecursive(root); 215 cout<<endl; 216 } 217 218 219 template <typename T> 220 void BiTree<T>::PostOrderRecursive(BiNode<T> * root) 221 { 222 if(root != NULL) 223 { 224 PostOrderRecursive(root->pLeft); 225 PostOrderRecursive(root->pRight); 226 cout<<root->data<<" "; 227 } 228 } 229 230 231 template <typename T> 232 void BiTree<T>::PostOrderNonRecursive(BiNode<T> * root) 233 { 234 235 stack<BiNode<T> *> s1; 236 stack<int> s2;//s2辅助记录s1相应位置的元素的状态:s1、s2保持同步。 237 238 while(root != NULL || !s1.empty()) 239 { 240 while(root != NULL) 241 { 242 s1.push(root); 243 s2.push(1); 244 root = root->pLeft; 245 } 246 if(!s1.empty()) 247 { 248 if(s2.top()==1) 249 { 250 s2.pop(); 251 s2.push(2); 252 root = s1.top()->pRight; 253 } 254 else 255 { 256 root = s1.top(); 257 s1.pop(); 258 s2.pop(); 259 cout<<root->data<<" "; 260 root = NULL; 261 } 262 } 263 264 } 265 266 } 267 268 269 template <typename T> 270 void BiTree<T>::PostOrder1() 271 { 272 PostOrderRecursive(root); 273 cout<<endl; 274 } 275 276 277 template <typename T> 278 void BiTree<T>::PostOrder2() 279 { 280 PostOrderNonRecursive(root); 281 cout<<endl; 282 } 283 284 285 template <typename T> 286 void BiTree<T>::LevelOrder(BiNode<T> * root) 287 { 288 BiNode<T> * p; 289 queue<BiNode<T> *> q; 290 if(root == NULL) 291 return; 292 q.push(root); 293 while(!q.empty()) 294 { 295 p = q.front(); 296 cout << p->data<<" "; 297 q.pop(); 298 if(p->pLeft != NULL) q.push(p->pLeft); 299 if(p->pRight != NULL) q.push(p->pRight); 300 } 301 } 302 303 304 template <typename T> 305 void BiTree<T>::LevelOrder() 306 { 307 LevelOrder(root); 308 cout<<endl; 309 } 310 311 312 313 int main() 314 { 315 316 317 ifstream fin("BiTree.txt");// 输入文件 318 ofstream fout("out.txt"); //输出文件 319 320 streambuf *cinbackup; 321 streambuf *coutbackup; 322 323 cinbackup= cin.rdbuf(fin.rdbuf()); //用 rdbuf() 重新定向 324 coutbackup= cout.rdbuf(fout.rdbuf()); //用 rdbuf() 重新定向 325 326 BiTree<char> *pbitree = new BiTree<char>;//创建一颗二叉树 327 328 cout << "*preorder = " << preorder << endl; 329 cout << " PreOrder1(): "; 330 pbitree->PreOrder1(); 331 cout << " PreOrder2(): "; 332 pbitree->PreOrder2(); 333 cout<<endl; 334 335 cout << "*inorder = " << inorder << endl; 336 cout << " inorder1(): "; 337 pbitree->InOrder1(); 338 cout << " InOrder2(): "; 339 pbitree->InOrder2(); 340 cout<<endl; 341 342 cout << "*postorder = " << postorder << endl; 343 cout << " PostOrder1(): "; 344 pbitree->PostOrder1(); 345 cout << " PostOrder2(): "; 346 pbitree->PostOrder2(); 347 cout<<endl; 348 349 cout << "*levelorder = " << levelorder << endl; 350 cout << " LevelOrder(): "; 351 pbitree->LevelOrder(); 352 353 delete pbitree; 354 cin.rdbuf(cinbackup); // 取消,恢复键盘输入 355 cout.rdbuf(coutbackup); //取消,恢复屏幕输出 356 return 0; 357 }
【作者:Dillonn 出处: http://www.cnblogs.com/Dillonn/p/4226929.html 欢迎转载,请务必保留本行】