【做者:Dillonn 出處: http://www.cnblogs.com/Dillonn/p/4226929.html 歡迎轉載,請務必保留本行】html
二叉樹的建立及遍歷是不少二叉樹問題的基礎,遞歸遍歷邏輯清晰,代碼簡約漂亮,然則效率低下(全部遞歸方案的通病,非不得已不用遞歸);ios
非遞歸遍歷高效,卻不是能信手寫出來的,特別是後續非遞歸遍歷,相信不少資深碼工也有這樣的經歷:ide
5年前學習了二叉樹的非遞歸遍歷,一個月前複習了並達到能熟練寫出的程度,在不參考任何資料的狀況下,今天卻怎樣也寫不出來。函數
若是你也有過這種經歷,恭喜,這說明你是一個正常人類……post
另外一方面市面上有些國人寫的教材,各類語法、邏輯錯誤層出不起,不知禍害了多少將來的碼工,深感痛心。學習
印象比較深入的有清華大學出版社出版的《數據結果(C++版)》 王紅梅、胡明、王濤編著。spa
如書中第163頁後序非遞歸遍歷方法,短短不到30行代碼各類語法、邏輯錯誤以下: code
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中實現如下方法:htm
1.建立一顆二叉樹;blog
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相應位置的元素的狀態:s一、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相應位置的元素的狀態:s一、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 歡迎轉載,請務必保留本行】