二叉树的详细实现 (C++)
二叉树的定义
二叉树的性质
二叉树的数组存储方式
遇到空子树,应在编号时假定有此子树进行编号,而在顺序存储时当作有此子树那样把位置留出来。这样才能反映二叉树结点之间的相互关系,由其存储位置找到它的父结点、子女、兄弟结点的位置。但这样做有可能会消耗大量的存储空间。例如:单支二叉树,会浪费很多空间。
二叉树的链表存储表示
二叉树结点类型的定义
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.根据已知的前序遍历和中序遍历创建二叉树
根据前序遍历,先找到这棵树的根节点,也就是数组受中第一个结点的位置,创建根节点。
然后在中序遍历中找到根的值所在的下标,切出左右子树的前序和中序
注意:如果前序遍历的数组长度为0,说明是一棵空树。
举例:
首先可以确定A是这棵树的根节点,然后根据中序遍历切出A的左右子树,得到BCD属于A的左子树,E属于A的右子树,如下图:
接着以B为根节点,在中序遍历中再次切出B的左右子树,得到CD为B的左子树,右子树为空。
再以C为根节点,结合中序遍历,得到D为C的右子树,左子树为空。
创建好的二叉树如下图所示:
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 }
后续遍历
2、判断上一次出栈节点是否是当前栈顶结点的右节点(就是右叶子结点,如: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 };