二叉樹的定義

二叉樹的性質

二叉樹的數組存儲方式

遇到空子樹,應在編號時假定有此子樹進行編號,而在順序存儲時看成有此子樹那樣把位置留出來。這樣才能反映二叉樹結點之間的相互關係,由其存儲位置找到它的父結點、子女、兄弟結點的位置。但這樣作有可能會消耗大量的存儲空間。例如:單支二叉樹,會浪費不少空間。算法

二叉樹的鏈表存儲表示

二叉樹結點類型的定義
1 template<typename T> 2 struct BinTreeNode 3 { 4 T data; //結點中存儲的數據 5 BinTreeNode<T> *leftChild, *rightChild; //左子樹和右子樹 6 BinTreeNode() :leftChild(NULL), rightChild(NULL) {} //無參構造函數 7 BinTreeNode(T x, BinTreeNode<T> *l = NULL, BinTreeNode<T> *r = NULL) :data(x), leftChild(l), rightChild(r) {} //帶默認值的有參構造參數 8 };
二叉樹的基本框架
//二叉樹 //結點類型 template <typename T> struct BinTreeNode { T data; //結點中存儲的數據 BinTreeNode<T> *leftChild, *rightChild; //左子樹和右子樹 BinTreeNode() : leftChild(NULL), rightChild(NULL) {} //無參構造函數 BinTreeNode(T x, BinTreeNode<T> *l = NULL, BinTreeNode<T> *r = NULL) : data(x), leftChild(l), rightChild(r) {} //帶默認值的有參構造參數 }; //二叉樹類 template <typename T> class BinaryTree { public: //==========二叉樹構造與析構==========// //構造函數 BinaryTree() : root(NULL) {} //指定結束標誌的構造函數 BinaryTree(T value) : RefValue(value), root(NULL) {} //析構函數 ~BinaryTree() { Destroy(root); } //==========二叉樹的建立==========// //使用廣義表建立二叉樹,以'#'字符表明結束 void CreateBinTree() { CreateBinTree(root); } //前序遍歷建立二叉樹(前序遍歷的應用),用#表示空結點 void CreateBinTree_PreOrder() { CreateBinTree_PreOrder(root); } //使用先序遍歷和中序遍歷建立二叉樹 void CreateBinTreeBy_Pre_In(const char *pre, const char *in) { int n = strlen(pre); CreateBinTreeBy_Pre_In(root, pre, in, n); } //使用後序遍歷和中序遍歷建立二叉樹 void CreateBinTreeBy_Post_In(const char *post, const char *in) { int n = strlen(post); CreateBinTreeBy_Post_In(root, post, in, n); } //==========二叉樹的遍歷==========// //先序遍歷(遞歸) void PreOrder() { PreOrder(root); } //中序遍歷(遞歸) void InOrder() { InOrder(root); } //後序遍歷(遞歸) void PostOrder() { PostOrder(root); } //先序遍歷(非遞歸) void PreOrder_NoRecurve() { PreOrder_NoRecurve(root); } //中序遍歷(非遞歸) void InOrder_NoRecurve() { InOrder_NoRecurve(root); } //後序遍歷(非遞歸) void PostOrder_NoRecurve() { PostOrder_NoRecurve(root); } //層次遍歷(非遞歸) void LevelOrder() { LevelOrder(root); } //==========獲取結點==========// //獲取二叉樹的根節點 BinTreeNode<T> *getRoot() const { return root; } //獲取current結點的父節點 BinTreeNode<T> *Parent(BinTreeNode<T> *current) { return (root == NULL || root == current) ? NULL : Parent(root, current); //若是沒有根節點或current結點就是root結點,就沒有父節點 } //獲取current結點的左結點 BinTreeNode<T> *LeftChild(BinTreeNode<T> *current) { return (current != NULL) ? current->leftChild : NULL; } //獲取current結點的右結點 BinTreeNode<T> *RightChild(BinTreeNode<T> *current) { return (current != NULL) ? current->rightChild : NULL; } //==========成員函數==========// //銷燬函數 void Destroy() { Destroy(root); } //拷貝二叉樹(前序遍歷的應用) BinaryTree(BinaryTree<T> &s) { root = Copy(s.getRoot()); } //判斷兩顆二叉樹是否相等(前序遍歷的應用) bool operator==(BinaryTree<T> &s) { return (equal(this->getRoot(), s.getRoot())); } //計算二叉樹的結點的個數(後序遍歷的應用) int Size() { return Size(root); } //計算二叉樹的高度(後序遍歷的應用) int Height() { return Height(root); } //判斷二叉樹是否爲空 bool Empty() { return (root == NULL) ? true : false; } //以廣義表的形式輸出二叉樹(前序遍歷的應用) void PrintBinTree() { PrintBinTree(root); } private: BinTreeNode<T> *root; //根節點 T RefValue; //數據輸入中止的標誌,須要一個構造函數 };
二叉樹的建立
1.使用廣義表建立

1 //使用廣義表建立二叉樹函數,這裏以「字符」建立二叉樹,以'#'字符表明結束 2 void CreateBinTree(BinTreeNode<T>* &BT) 3 { 4 stack< BinTreeNode<T>* > s; 5 BT = NULL; 6 BinTreeNode<T> *p, *t; //p用來記住當前建立的節點,t用來記住棧頂的元素 7 int k; //k是處理左、右子樹的標記 8 T ch; 9 cin >> ch; 10 11 while (ch != RefValue) 12 { 13 switch (ch) 14 { 15 case '(': //對(作處理 16 s.push(p); 17 k = 1; 18 break; 19 20 case ')': //對)作處理 21 s.pop(); 22 break; 23 24 case ',': //對,作處理 25 k = 2; 26 break; 27 28 default: 29 p = new BinTreeNode<T>(ch); //構造一個結點 30 if (BT == NULL) //若是頭節點是空 31 { 32 BT = p; 33 } 34 else if (k == 1) //鏈入*t的左孩子 35 { 36 t = s.top(); 37 t->leftChild = p; 38 } 39 else //鏈入*t的右孩子 40 { 41 t = s.top(); 42 t->rightChild = p; 43 } 44 } 45 cin >> ch; 46 } 47 }
2.使用已知的二叉樹的前序遍歷建立數組

1 //建立二叉樹(利用已知的二叉樹的前序遍歷建立)用#表示空結點 2 void CreateBinTree_PreOrder(BinTreeNode<T>* &subTree) 3 { 4 T item; 5 if (cin >> item) 6 { 7 if (item != RefValue) 8 { 9 subTree = new BinTreeNode<T>(item); //構造結點 10 if (subTree == NULL) 11 { 12 cout << "空間分配錯誤!" << endl; 13 exit(1); 14 } 15 CreateBinTree_PreOrder(subTree->leftChild); //遞歸建立左子樹 16 CreateBinTree_PreOrder(subTree->rightChild); //遞歸建立右子樹 17 } 18 else 19 { 20 subTree == NULL; 21 } 22 } 23 }
3.根據已知的前序遍歷和中序遍歷建立二叉樹框架
根據前序遍歷,先找到這棵樹的根節點,也就是數組受中第一個結點的位置,建立根節點。函數
而後在中序遍歷中找到根的值所在的下標,切出左右子樹的前序和中序post
注意:若是前序遍歷的數組長度爲0,說明是一棵空樹。this
舉例:spa
首先能夠肯定A是這棵樹的根節點,而後根據中序遍歷切出A的左右子樹,獲得BCD屬於A的左子樹,E屬於A的右子樹,以下圖:指針
接着以B爲根節點,在中序遍歷中再次切出B的左右子樹,獲得CD爲B的左子樹,右子樹爲空。code
再以C爲根節點,結合中序遍歷,獲得D爲C的右子樹,左子樹爲空。blog
建立好的二叉樹以下圖所示:
1 //使用先序遍歷和中序遍歷建立二叉樹 2 void CreateBinTreeBy_Pre_In(BinTreeNode<T> *&cur, const char *pre, const char *in, int n) 3 { 4 if (n <= 0) 5 { 6 cur = NULL; 7 return; 8 } 9 int k = 0; 10 while (pre[0] != in[k]) //再中序中找到pre[0]的值 11 { 12 k++; 13 } 14 cur = new BinTreeNode<T>(in[k]); //建立結點 15 CreateBinTreeBy_Pre_In(cur->leftChild, pre + 1, in, k); 16 CreateBinTreeBy_Pre_In(cur->rightChild, pre + k + 1, in + k + 1, n - k - 1); 17 }
4.根據已知的後續遍歷和中序遍歷建立二叉樹
根據後序遍歷,先找到這棵樹的根節點的值,也就是數組中最後一個節點(數組長度-1)的位置,由此建立根節點。
而後在中序遍歷中找到根的值所在的下標,切出左右子樹的後續和中序。
注意:若是後序遍歷的數組長度爲0,說明是一棵空樹。
舉例:
由後序遍歷能夠肯定A是這棵樹的根節點,而後根據中序遍歷切出A的左右子樹,獲得CDB屬於A的左子樹,E屬於A的右子樹,以下圖:
接着以B爲根節點,在中序遍歷中再次切出B的左右子樹,獲得CD爲B的左子樹,右子樹爲空。

建立好的二叉樹以下圖所示:
1 //使用後序遍歷和中序遍歷建立二叉樹 2 void CreateBinTreeBy_Post_In(BinTreeNode<T> *&cur, const char *post, const char *in, int n) 3 { 4 if (n == 0) 5 { 6 cur = NULL; 7 return; 8 } 9 10 char r = *(post + n - 1); //根結點值 11 cur = new BinTreeNode<T>(r); //構造當前結點 12 13 int k = 0; 14 const char *p = in; 15 while (*p != r) 16 { 17 k++; 18 p++; 19 } 20 CreateBinTreeBy_Post_In(cur->leftChild, post, in, k); 21 CreateBinTreeBy_Post_In(cur->rightChild, post + k, p + 1, n - k - 1); 22 }
二叉樹的遞歸遍歷
先序遍歷:根->左->右
1 //二叉樹的先序遍歷 2 void PreOrder(BinTreeNode<T> *&subTree) 3 { 4 if (subTree != NULL) 5 { 6 cout << subTree->data << " "; 7 PreOrder(subTree->leftChild); 8 PreOrder(subTree->rightChild); 9 } 10 }
中序遍歷:左->根->右
1 //二叉樹的中序遍歷 2 void InOrder(BinTreeNode<T> *&subTree) 3 { 4 if (subTree != NULL) 5 { 6 InOrder(subTree->leftChild); 7 cout << subTree->data << " "; 8 InOrder(subTree->rightChild); 9 } 10 }
後續遍歷:左->右->根
1 //二叉樹的後序遍歷 2 void PostOrder(BinTreeNode<T> *&subTree) 3 { 4 if (subTree != NULL) 5 { 6 PostOrder(subTree->leftChild); 7 PostOrder(subTree->rightChild); 8 cout << subTree->data << " "; 9 } 10 }
二叉樹的非遞歸遍歷
先序遍歷

利用棧實現前序遍歷的過程。每次訪問一個結點後,在向左子樹遍歷下去以前,利用這個棧記錄該結點的右子女(若是有的話)結點的地址,以便在左子樹退回時能夠直接從棧頂取得右子樹的根結點,繼續其右子樹的前序遍歷。
1 //二叉樹先序遍歷(非遞歸1) 2 void PreOrder_NoRecurve1(BinTreeNode<T> *p) 3 { 4 stack<BinTreeNode<T>*> S; 5 S.push(NULL); //最早push一個NULL,到最後一個結點沒有左右子樹時,棧裏只有一個NULL了,令指針p指向這個NULL,再判斷就會結束循環 6 while (p!=NULL) 7 { 8 cout << p->data << " "; 9 if(p->rightChild!=NULL) //預留右子樹指針在棧中 10 { 11 S.push(p->rightChild); 12 } 13 14 if (p->leftChild!=NULL) //進左子樹 15 { 16 p = p->leftChild; 17 } 18 else //左子樹爲空 19 { 20 p = S.top(); 21 S.pop(); 22 } 23 } 24 }
另外一種前序遍歷的方法。爲了保證先左子樹後右子樹的順序,在進棧時是先進右子女結點地址,後進左子女結點地址,出棧時正好相反。
1 //二叉樹先序遍歷(非遞歸2) 2 void PreOrder_NoRecurve2(BinTreeNode<T> *p) 3 { 4 stack<BinTreeNode<T>*> S; 5 BinTreeNode<T>* t; 6 S.push(p); //根節點進棧 7 while (!S.empty()) //當棧不爲空 8 { 9 t = S.top(); //p先記住棧頂元素,而後棧頂出棧 10 S.pop(); 11 cout << t->data << " "; //訪問元素 12 if (t->rightChild != NULL) //右孩子不爲空,右孩子近棧 13 { 14 S.push(t->rightChild); 15 } 16 if (t->leftChild != NULL) //左孩子不爲空,左孩子進棧 17 { 18 S.push(t->leftChild); 19 } 20 } 21 }
中序遍歷

1 //二叉樹的中序遍歷(非遞歸) 2 void InOrder_NoRecurve(BinTreeNode<T>* p) 3 { 4 stack<BinTreeNode<T>*> S; 5 do 6 { 7 while (p!=NULL) 8 { 9 S.push(p); 10 p = p->leftChild; 11 } 12 if (!S.empty()) 13 { 14 p = S.top(); 15 S.pop(); 16 cout << p->data << " "; 17 p = p->rightChild; 18 } 19 } 20 while (p!=NULL||!S.empty()); 21 }
後續遍歷

二、判斷上一次出棧節點是不是當前棧頂結點的右節點(就是右葉子結點,如:g,f結點),或者當前棧頂結點不存在右結點(如:g,f,a結點),將當前節點輸出,並出棧。不然將當前棧頂結點右孩子節點壓棧,再進入第1步
1 //後序遍歷(非遞歸) 2 void PostOrder_NoRecurve(BinTreeNode<T> *p) 3 { 4 if (root == NULL) 5 return; 6 stack<BinTreeNode<T> *> s; 7 s.push(p); 8 BinTreeNode<T> *lastPop = NULL; 9 while (!s.empty()) 10 { 11 while (s.top()->leftChild != NULL) 12 s.push(s.top()->leftChild); 13 while (!s.empty()) 14 { 15 //右葉子結點 || 沒有右結點 16 if (lastPop == s.top()->rightChild || s.top()->rightChild == NULL) 17 { 18 cout << s.top()->data << " "; 19 lastPop = s.top(); 20 s.pop(); 21 } 22 else if (s.top()->rightChild != NULL) 23 { 24 s.push(s.top()->rightChild); 25 break; 26 } 27 } 28 } 29 }
層次遍歷

1 //二叉樹的層次遍歷(非遞歸遍歷) 2 void LevelOrder(BinTreeNode<T> *p) 3 { 4 queue<BinTreeNode<T>*> Q; 5 Q.push(p); //根節點進隊 6 BinTreeNode<T>* t; 7 while (!Q.empty()) 8 { 9 t = Q.front(); //t先記住隊頭,再將隊頭出隊 10 Q.pop(); 11 cout << t->data << " "; //訪問隊頭元素的數據 12 13 if (t->leftChild != NULL) 14 { 15 Q.push(t->leftChild); 16 } 17 18 if (t->rightChild != NULL) 19 { 20 Q.push(t->rightChild); 21 } 22 } 23 }
二叉樹的結點個數
1 //計算二叉樹以subTree爲根的結點的個數 2 int Size(BinTreeNode<T> *subTree) const 3 { 4 if (subTree == NULL) //遞歸結束,空樹結點個數爲0 5 { 6 return 0; 7 } 8 return 1 + Size(subTree->leftChild) + Size(subTree->rightChild); 9 }
二叉樹的高度
1 //計算二叉數以subTree爲根的高度 2 int Height(BinTreeNode<T> *subTree) 3 { 4 if (subTree == NULL) //遞歸結束,空樹高度爲0 5 { 6 return 0; 7 } 8 int i = Height(subTree->leftChild); 9 int j = Height(subTree->rightChild); 10 return i < j ? j + 1 : i + 1; 11 }
以廣義表的形式輸出二叉樹
1 void PrintBinTree(BinTreeNode<T> *BT) 2 { 3 if (BT != NULL) //樹爲空時結束遞歸 4 { 5 cout << BT->data; 6 if (BT->leftChild != NULL || BT->rightChild != NULL) 7 { 8 cout << '('; 9 if (BT->leftChild!=NULL) 10 { 11 PrintBinTree(BT->leftChild); 12 } 13 cout << ','; 14 if (BT->rightChild != NULL) 15 { 16 PrintBinTree(BT->rightChild); 17 } 18 cout << ')'; 19 } 20 } 21 }
求二叉樹某結點的父節點
1 //從結點subTree開始,搜索結點current的父節點,找到返回父節點的地址,找不到返回NULL 2 BinTreeNode<T>* Parent(BinTreeNode<T>* subTree, BinTreeNode<T>* current) 3 { 4 if (subTree == NULL) 5 { 6 return NULL; 7 } 8 if (subTree->leftChild == current || subTree->rightChild == current) //若是找到,返回父節點subTree 9 { 10 return subTree; 11 } 12 BinTreeNode<T>* p; 13 if (p = Parent(subTree->leftChild, current) != NULL) //遞歸在左子樹中搜索 14 { 15 return p; 16 } 17 else 18 { 19 return Parent(subTree->rightChild, current); //遞歸右子樹中搜索 20 } 21 }
二叉樹的銷燬
1 //二叉樹的銷燬函數 2 void Destroy(BinTreeNode<T> *&subTree) 3 { 4 if (subTree != NULL) 5 { 6 Destroy(subTree->leftChild); 7 Destroy(subTree->rightChild); 8 delete subTree; 9 subTree = NULL; 10 } 11 }
判斷兩顆二叉樹是否相等
1 //判斷兩顆二叉樹是否相等 2 bool equal(BinTreeNode<T> *a, BinTreeNode<T> *b) 3 { 4 if (a == NULL&&b == NULL) //二者都爲空 5 { 6 return true; 7 } 8 if (a != NULL&&b != NULL&&a->data == b->data&&equal(a->leftChild, b->leftChild) && equal(a->rightChild, b->rightChild)) //二者都不爲空,且二者的結點數據相等,且二者的左右子樹的結點都相等 9 { 10 return true; 11 } 12 return false; 13 }
1 //結點類型 2 template <typename T> 3 struct BinTreeNode 4 { 5 T data; //結點中存儲的數據 6 BinTreeNode<T> *leftChild, *rightChild; //左子樹和右子樹 7 BinTreeNode() : leftChild(NULL), rightChild(NULL) {} //無參構造函數 8 BinTreeNode(T x, BinTreeNode<T> *l = NULL, BinTreeNode<T> *r = NULL) : data(x), leftChild(l), rightChild(r) {} //帶默認值的有參構造參數 9 }; 10 11 //二叉樹類 12 template <typename T> 13 class BinaryTree 14 { 15 public: 16 17 //==========二叉樹構造與析構==========// 18 19 //構造函數 20 BinaryTree() : root(NULL) {} 21 22 //指定結束標誌的構造函數 23 BinaryTree(T value) : RefValue(value), root(NULL) {} 24 25 //析構函數 26 ~BinaryTree() { Destroy(root); } 27 28 //==========二叉樹的建立==========// 29 30 //使用廣義表建立二叉樹,以'#'字符表明結束 31 void CreateBinTree() { CreateBinTree(root); } 32 33 //前序遍歷建立二叉樹(前序遍歷的應用),用#表示空結點 34 void CreateBinTree_PreOrder() { CreateBinTree_PreOrder(root); } 35 36 //使用先序遍歷和中序遍歷建立二叉樹 37 void CreateBinTreeBy_Pre_In(const char *pre, const char *in) 38 { 39 int n = strlen(pre); 40 CreateBinTreeBy_Pre_In(root, pre, in, n); 41 } 42 43 //使用後序遍歷和中序遍歷建立二叉樹 44 void CreateBinTreeBy_Post_In(const char *post, const char *in) 45 { 46 int n = strlen(post); 47 CreateBinTreeBy_Post_In(root, post, in, n); 48 } 49 50 //==========二叉樹的遍歷==========// 51 52 //先序遍歷(遞歸) 53 void PreOrder() { PreOrder(root); } 54 55 //中序遍歷(遞歸) 56 void InOrder() { InOrder(root); } 57 58 //後序遍歷(遞歸) 59 void PostOrder() { PostOrder(root); } 60 61 //先序遍歷(非遞歸) 62 void PreOrder_NoRecurve() { PreOrder_NoRecurve(root); } 63 64 //中序遍歷(非遞歸) 65 void InOrder_NoRecurve() { InOrder_NoRecurve(root); } 66 67 //後序遍歷(非遞歸) 68 void PostOrder_NoRecurve() { PostOrder_NoRecurve(root); } 69 70 //層次遍歷(非遞歸) 71 void LevelOrder() { LevelOrder(root); } 72 73 //==========獲取結點==========// 74 75 //獲取二叉樹的根節點 76 BinTreeNode<T> *getRoot() const 77 { 78 return root; 79 } 80 81 //獲取current結點的父節點 82 BinTreeNode<T> *Parent(BinTreeNode<T> *current) 83 { 84 return (root == NULL || root == current) ? NULL : Parent(root, current); //若是沒有根節點或current結點就是root結點,就沒有父節點 85 } 86 87 //獲取current結點的左結點 88 BinTreeNode<T> *LeftChild(BinTreeNode<T> *current) 89 { 90 return (current != NULL) ? current->leftChild : NULL; 91 } 92 93 //獲取current結點的右結點 94 BinTreeNode<T> *RightChild(BinTreeNode<T> *current) 95 { 96 return (current != NULL) ? current->rightChild : NULL; 97 } 98 99 //==========成員函數==========// 100 101 //銷燬函數 102 void Destroy() { Destroy(root); } 103 104 //拷貝二叉樹(前序遍歷的應用) 105 BinaryTree(BinaryTree<T> &s) 106 { 107 root = Copy(s.getRoot()); 108 } 109 110 //判斷兩顆二叉樹是否相等(前序遍歷的應用) 111 bool operator==(BinaryTree<T> &s) 112 { 113 return (equal(this->getRoot(), s.getRoot())); 114 } 115 116 //計算二叉樹的結點的個數(後序遍歷的應用) 117 int Size() { return Size(root); } 118 119 //計算二叉樹的高度(後序遍歷的應用) 120 int Height() { return Height(root); } 121 122 //判斷二叉樹是否爲空 123 bool Empty() { return (root == NULL) ? true : false; } 124 125 //以廣義表的形式輸出二叉樹(前序遍歷的應用) 126 void PrintBinTree() { PrintBinTree(root); } 127 128 protected: 129 130 //使用廣義表建立二叉樹函數,這裏以「字符」建立二叉樹,以'#'字符表明結束 131 void CreateBinTree(BinTreeNode<T> *&BT) 132 { 133 stack<BinTreeNode<T> *> s; 134 BT = NULL; 135 BinTreeNode<T> *p, *t; //p用來記住當前建立的節點,t用來記住棧頂的元素 136 int k; //k是處理左、右子樹的標記 137 T ch; 138 cin >> ch; 139 140 while (ch != RefValue) 141 { 142 switch (ch) 143 { 144 case '(': //對(作處理 145 s.push(p); 146 k = 1; 147 break; 148 149 case ')': //對)作處理 150 s.pop(); 151 break; 152 153 case ',': //對,作處理 154 k = 2; 155 break; 156 157 default: 158 p = new BinTreeNode<T>(ch); //構造一個結點 159 if (BT == NULL) //若是頭節點是空 160 { 161 BT = p; 162 } 163 else if (k == 1) //鏈入*t的左孩子 164 { 165 t = s.top(); 166 t->leftChild = p; 167 } 168 else //鏈入*t的右孩子 169 { 170 t = s.top(); 171 t->rightChild = p; 172 } 173 } 174 cin >> ch; 175 } 176 } 177 178 //建立二叉樹(利用已知的二叉樹的前序遍歷建立)用#表示空結點 179 void CreateBinTree_PreOrder(BinTreeNode<T> *&subTree) 180 { 181 T item; 182 if (cin >> item) 183 { 184 if (item != RefValue) 185 { 186 subTree = new BinTreeNode<T>(item); //構造結點 187 if (subTree == NULL) 188 { 189 cout << "空間分配錯誤!" << endl; 190 exit(1); 191 } 192 CreateBinTree_PreOrder(subTree->leftChild); //遞歸建立左子樹 193 CreateBinTree_PreOrder(subTree->rightChild); //遞歸建立右子樹 194 } 195 else 196 { 197 subTree == NULL; 198 } 199 } 200 } 201 202 //使用先序遍歷和中序遍歷建立二叉樹 203 void CreateBinTreeBy_Pre_In(BinTreeNode<T> *&cur, const char *pre, const char *in, int n) 204 { 205 if (n <= 0) 206 { 207 cur = NULL; 208 return; 209 } 210 int k = 0; 211 while (pre[0] != in[k]) //再中序中找到pre[0]的值 212 { 213 k++; 214 } 215 cur = new BinTreeNode<T>(in[k]); //建立結點 216 CreateBinTreeBy_Pre_In(cur->leftChild, pre + 1, in, k); 217 CreateBinTreeBy_Pre_In(cur->rightChild, pre + k + 1, in + k + 1, n - k - 1); 218 } 219 //使用後序遍歷和中序遍歷建立二叉樹 220 void CreateBinTreeBy_Post_In(BinTreeNode<T> *&cur, const char *post, const char *in, int n) 221 { 222 if (n == 0) 223 { 224 cur = NULL; 225 return; 226 } 227 228 char r = *(post + n - 1); //根結點值 229 cur = new BinTreeNode<T>(r); //構造當前結點 230 231 int k = 0; 232 const char *p = in; 233 while (*p != r) 234 { 235 k++; 236 p++; 237 } 238 CreateBinTreeBy_Post_In(cur->leftChild, post, in, k); 239 CreateBinTreeBy_Post_In(cur->rightChild, post + k, p + 1, n - k - 1); 240 } 241 242 //先序遍歷(遞歸) 243 void PreOrder(BinTreeNode<T> *&subTree) 244 { 245 if (subTree != NULL) 246 { 247 cout << subTree->data << " "; 248 PreOrder(subTree->leftChild); 249 PreOrder(subTree->rightChild); 250 } 251 } 252 253 //中序遍歷(遞歸) 254 void InOrder(BinTreeNode<T> *&subTree) 255 { 256 if (subTree != NULL) 257 { 258 InOrder(subTree->leftChild); 259 cout << subTree->data << " "; 260 InOrder(subTree->rightChild); 261 } 262 } 263 264 //後序遍歷(遞歸) 265 void PostOrder(BinTreeNode<T> *&subTree) 266 { 267 if (subTree != NULL) 268 { 269 PostOrder(subTree->leftChild); 270 PostOrder(subTree->rightChild); 271 cout << subTree->data << " "; 272 } 273 } 274 275 //先序遍歷(非遞歸) 276 void PreOrder_NoRecurve(BinTreeNode<T> *p) 277 { 278 stack<BinTreeNode<T> *> S; 279 BinTreeNode<T> *t; 280 S.push(p); //根節點進棧 281 while (!S.empty()) //當棧不爲空 282 { 283 t = S.top(); //p先記住棧頂元素,而後棧頂出棧 284 S.pop(); 285 cout << t->data << " "; //訪問元素 286 if (t->rightChild != NULL) //右孩子不爲空,右孩子近棧 287 { 288 S.push(t->rightChild); 289 } 290 if (t->leftChild != NULL) //左孩子不爲空,左孩子進棧 291 { 292 S.push(t->leftChild); 293 } 294 } 295 } 296 297 //中序遍歷(非遞歸) 298 void InOrder_NoRecurve(BinTreeNode<T> *root) 299 { 300 if (root == NULL) 301 return; 302 stack<BinTreeNode<T> *> s; 303 s.push(root); 304 while (!s.empty()) 305 { 306 while (s.top()->leftChild != NULL) //將左結點依次入棧 307 { 308 s.push(s.top()->leftChild); 309 } 310 while (!s.empty()) 311 { 312 BinTreeNode<T> *cur = s.top(); 313 cout << cur->data << " "; 314 s.pop(); 315 if (cur->rightChild != NULL) 316 { 317 s.push(cur->rightChild); 318 break; 319 } 320 } 321 } 322 } 323 324 //後序遍歷(非遞歸) 325 void PostOrder_NoRecurve(BinTreeNode<T> *p) 326 { 327 if (root == NULL) 328 return; 329 stack<BinTreeNode<T> *> s; 330 s.push(p); 331 BinTreeNode<T> *lastPop = NULL; 332 while (!s.empty()) 333 { 334 while (s.top()->leftChild != NULL) 335 s.push(s.top()->leftChild); 336 while (!s.empty()) 337 { 338 //右葉子結點 || 沒有右結點 339 if (lastPop == s.top()->rightChild || s.top()->rightChild == NULL) 340 { 341 cout << s.top()->data << " "; 342 lastPop = s.top(); 343 s.pop(); 344 } 345 else if (s.top()->rightChild != NULL) 346 { 347 s.push(s.top()->rightChild); 348 break; 349 } 350 } 351 } 352 } 353 354 //層次遍歷(非遞歸) 355 void LevelOrder(BinTreeNode<T> *p) 356 { 357 queue<BinTreeNode<T> *> Q; 358 Q.push(p); //根節點進隊 359 BinTreeNode<T> *t; 360 while (!Q.empty()) 361 { 362 t = Q.front(); //t先記住隊頭,再將隊頭出隊 363 Q.pop(); 364 cout << t->data << " "; //訪問隊頭元素的數據 365 366 if (t->leftChild != NULL) 367 { 368 Q.push(t->leftChild); 369 } 370 371 if (t->rightChild != NULL) 372 { 373 Q.push(t->rightChild); 374 } 375 } 376 } 377 378 //從結點subTree開始,搜索結點current的父節點,找到返回父節點的地址,找不到返回NULL 379 BinTreeNode<T> *Parent(BinTreeNode<T> *subTree, BinTreeNode<T> *current) 380 { 381 if (subTree == NULL) 382 { 383 return NULL; 384 } 385 if (subTree->leftChild == current || subTree->rightChild == current) //若是找到,返回父節點subTree 386 { 387 return subTree; 388 } 389 BinTreeNode<T> *p; 390 if (p = Parent(subTree->leftChild, current) != NULL) //遞歸在左子樹中搜索 391 { 392 return p; 393 } 394 else 395 { 396 return Parent(subTree->rightChild, current); //遞歸右子樹中搜索 397 } 398 } 399 400 //二叉樹的銷燬 401 void Destroy(BinTreeNode<T> *&subTree) 402 { 403 if (subTree != NULL) 404 { 405 Destroy(subTree->leftChild); 406 Destroy(subTree->rightChild); 407 delete subTree; 408 subTree = NULL; 409 } 410 } 411 412 //複製二叉樹函數,返回一個指針,給出一個以originNode爲根複製的二叉樹的副本 413 BinTreeNode<T> *Copy(BinTreeNode<T> *originNode) 414 { 415 if (originNode == NULL) 416 { 417 return NULL; 418 } 419 BinTreeNode<T> *temp = new BinTreeNode<T>; //建立根結點 420 temp->data = originNode->data; 421 temp->leftChild = Copy(originNode->leftChild); 422 temp->rightChild = Copy(originNode->rightChild); 423 return temp; 424 } 425 426 //判斷兩顆二叉樹是否相等 427 bool equal(BinTreeNode<T> *a, BinTreeNode<T> *b) 428 { 429 if (a == NULL && b == NULL) //二者都爲空 430 { 431 return true; 432 } 433 if (a != NULL && b != NULL && a->data == b->data && equal(a->leftChild, b->leftChild) && equal(a->rightChild, b->rightChild)) //二者都不爲空,且二者的結點數據相等,且二者的左右子樹的結點都相等 434 { 435 return true; 436 } 437 return false; 438 } 439 440 //計算二叉樹以subTree爲根的結點的個數 441 int Size(BinTreeNode<T> *subTree) const 442 { 443 if (subTree == NULL) //遞歸結束,空樹結點個數爲0 444 { 445 return 0; 446 } 447 return 1 + Size(subTree->leftChild) + Size(subTree->rightChild); 448 } 449 450 //計算二叉數以subTree爲根的高度 451 int Height(BinTreeNode<T> *subTree) 452 { 453 if (subTree == NULL) //遞歸結束,空樹高度爲0 454 { 455 return 0; 456 } 457 int i = Height(subTree->leftChild); 458 int j = Height(subTree->rightChild); 459 return i < j ? j + 1 : i + 1; 460 } 461 462 //以廣義表的形式輸出二叉樹 463 void PrintBinTree(BinTreeNode<T> *BT) 464 { 465 if (BT != NULL) //樹爲空時結束遞歸 466 { 467 cout << BT->data; 468 if (BT->leftChild != NULL || BT->rightChild != NULL) 469 { 470 cout << '('; 471 if (BT->leftChild != NULL) 472 { 473 PrintBinTree(BT->leftChild); 474 } 475 cout << ','; 476 if (BT->rightChild != NULL) 477 { 478 PrintBinTree(BT->rightChild); 479 } 480 cout << ')'; 481 } 482 } 483 } 484 485 private: 486 BinTreeNode<T> *root; //根節點 487 T RefValue; //數據輸入中止的標誌,須要一個構造函數 488 };
