# 二叉树三种遍历方式，有先序，中序或者后序，中序恢复二叉树等操作

//头文件
//BinaryTreeNode.h
#ifndef BINARYTREENODE_H
#define BINARYTREENODE_H
template<typename T>
class BinaryTreeNode{
public:
T data;
BinaryTreeNode<T>* leftChild;
BinaryTreeNode<T>* rightChild;
BinaryTreeNode(){

}
BinaryTreeNode(const T& val, BinaryTreeNode<T>* str, BinaryTreeNode<T>* ptr) :data(val), leftChild(str), rightChild(ptr){

}
};
#endif
//BinaryTree.h
#ifndef BINARYTREE_H
#define BINARYTREE_H
#include"BinaryTreeNode.h"
#include<iostream>
#include<queue>
#include<stack>
#include<cstring>
using namespace std;
template<typename T>
class BinaryTree{
private:
BinaryTreeNode<T>* root;
public:
BinaryTree();
~BinaryTree();
//一下为二叉树的基本操作
void creat();
bool isEmpty();
BinaryTreeNode<T>* getRoot();
T reValue(BinaryTreeNode<T>* str)const;
void reSet(BinaryTreeNode<T>* str, const T& val);
void Deep()const;
//输出操作
void PrintInOrder(BinaryTreeNode<T>* str);
void PrintLevelOrder();
void PrintPostOrder(BinaryTreeNode<T>* str);
//该函数是模拟先序，中序和后序，中序恢复出二叉树的操作
void simulate();
private:
//有中序序列和先序序列确定二叉树,递归形式的算法
void DefineBinaryTree(BinaryTreeNode<T>* &str,char* preOrder,char* midOrder,int length);
void DefineBinaryTree(char* preOrder, char* midOrder);
//有后序序列，中序序列确定二叉树
void DefineBinaryTreePost(BinaryTreeNode<T>* &str,char* postOrder,char* midOrder,int length);
void DefineBinaryTreePost(char* postOrder, char* midOrder);
//清空树
void makeEmpty(BinaryTreeNode<T>* &str);
private:
int deep(BinaryTreeNode<T>* str)const;
void CreatBiTree(BinaryTreeNode<T>* &str);
//非递归方法求树的深度
int deepPrivate()const;
private:
//该函数是用非递归方法，在给出先序和后序数列时，求出二叉树,该函数是为void DefineBinaryTree(char* preOrder, char* midOrder);
//函数服务的
int posChar(char ch, char* str);
};
template<typename T>
int BinaryTree<T>::posChar(char ch, char* str)
{
if (strlen(str) == 0)
{
cout << "the char* is empty" << endl;
exit(true);
}
int i = 0;
while (str[i] != '\0')
{
if (ch == str[i])
{
return i;
}
i++;
}
return -1;
}
template<typename T>
void BinaryTree<T>::DefineBinaryTree(char* preOrder, char* midOrder)
{
if (strlen(preOrder) == 0 || strlen(midOrder) == 0)
{
this->root = NULL;
return;
}
//记录每个与先序中节点对应的后序中的节点的位置
int pos;
//position,node两个栈存放的是pos,和生成的每个节点
stack<int>position;
stack<BinaryTreeNode<T>*>node;
//str,ptr用于生成节点
BinaryTreeNode<T>* str = NULL;
BinaryTreeNode<T>* ptr = NULL;
str = new BinaryTreeNode<T>(preOrder[0], NULL, NULL);
this->root = str;
pos = posChar(preOrder[0], midOrder);
position.push(pos);
node.push(str);
int i = 1;
while (preOrder[i] != '\0')
{
pos = posChar(preOrder[i], midOrder);
if (pos == -1)
{
cout << "the match is error" << endl;
exit(true);
}
str = new BinaryTreeNode<T>(preOrder[i], NULL, NULL);
if (pos < position.top())
{
//当num < position.top()时，则该节点是左节点
ptr = node.top();
ptr->leftChild = str;
node.push(str);
position.push(pos);
}
else
{
while (!position.empty() && pos > position.top())
{
ptr = node.top();
position.pop();
node.pop();
}
ptr->rightChild = str;
node.push(str);
position.push(pos);
}
i++;
}
}
template<typename T>
void BinaryTree<T>::simulate()
{
/*char preOrder[100];*/
char postOrder[100];
char midOrder[100];
cout << "input the postOrder: ";
/*cin >> preOrder;*/
cin >> postOrder;
//在这里对后序序列进行处理，将整个字符数组的顺序颠倒过来
char str[100];
int j = 0;
int count = strlen(postOrder);
for (int i = 0; i < count; j++, i++)
{
str[j] = postOrder[i];
}
str[j] = '\0';
int i = 0;
for (j = strlen(str) - 1; i < count, j >= 0; j--, i++)
{
postOrder[i] = str[j];
}
postOrder[i] = '\0';
cout << "input the midOrder: ";
cin >> midOrder;
int length = strlen(midOrder);
/*this->DefineBinaryTree(this->root,preOrder,midOrder,length);*/
/*this->DefineBinaryTree(preOrder, midOrder);*/
/*this->DefineBinaryTreePost(this->root, postOrder, midOrder,length);*/
this->DefineBinaryTreePost(postOrder, midOrder);
}
template<typename T>
void BinaryTree<T>::DefineBinaryTree(BinaryTreeNode<T>* &str, char* preOrder, char* midOrder, int length)
{
if (length == 0)
{
str = NULL;
return;
}
str = new BinaryTreeNode<T>(*preOrder, NULL, NULL);
char* pStr = strchr(midOrder, str->data);
if (pStr == NULL)
{
cout << "the midOrder string is wrong" << endl;
exit(true);
}
int leftTreeLength = strlen(midOrder) - strlen(pStr);
int rightTreeLength = length - leftTreeLength - 1;
DefineBinaryTree(str->leftChild, preOrder + 1, midOrder, leftTreeLength);
DefineBinaryTree(str->rightChild, preOrder + leftTreeLength + 1, pStr + 1, rightTreeLength);
}
template<typename T>
void BinaryTree<T>::DefineBinaryTreePost(BinaryTreeNode<T>* &str, char* postOrder, char* midOrder, int length)
{
if (length==0)
{
str = NULL;
return;
}
str = new BinaryTreeNode<T>(*postOrder, NULL, NULL);
char* pStr = strchr(midOrder, str->data);
if (pStr == NULL)
{
cout << "the midOrder is wrong" << endl;
exit(true);
}
//这里的字符串处理有错误
int leftLength = strlen(midOrder) - strlen(pStr);
int rightLength = length - leftLength - 1;
DefineBinaryTreePost(str->leftChild, postOrder + rightLength + 1, midOrder, leftLength);
DefineBinaryTreePost(str->rightChild, postOrder + 1, midOrder + leftLength + 1, rightLength);
}
template<typename T>
void BinaryTree<T>::DefineBinaryTreePost(char* postOrder, char* midOrder)
{
//在该函数中的postOrder序列是顺序已经被颠倒之后的序列
if (strlen(postOrder) == 0 || strlen(midOrder) == 0)
{
this->root = NULL;
return;
}
int pos;
stack<int>position;
stack<BinaryTreeNode<T>*>node;
BinaryTreeNode<T>* str = NULL;
BinaryTreeNode<T>* ptr = NULL;
str = new BinaryTreeNode<T>(postOrder[0], NULL, NULL);
this->root = str;
pos = posChar(str->data, midOrder);
node.push(str);
position.push(pos);
int i = 1;
while (postOrder[i] != '\0')
{
pos = posChar(postOrder[i], midOrder);
if (pos == -1)
{
cout << "the midOrder is error" << endl;
exit(true);
}
str = new BinaryTreeNode<T>(postOrder[i], NULL, NULL);
if (pos < position.top())
{
ptr = node.top();
ptr->leftChild = str;
node.push(str);
position.push(pos);
}
else
{
while (!position.empty() && pos>position.top())
{
ptr = node.top();
node.pop();
position.pop();
}
ptr->rightChild = str;
node.push(str);
position.push(pos);
}
i++;
}
}
template<typename T>
int BinaryTree<T>::deepPrivate()const
{
if (this->root == NULL)
return 0;
BinaryTreeNode<T>* p = this->root;
queue<BinaryTreeNode<T>*>que;
que.push(p);
int deepth = 0;
while (!que.empty())
{
deepth++;
//每次在循环开始之前，都要获得cur=0,和curQueSize的值
//curQueSize记录了每一层中的节点数目，当所有的这一层的节点的左右孩子全部都进入
//队列后退出循环
int cur = 0;
int curQueSize = que.size();
while (cur < curQueSize)
{
cur++;
//每次都要保证在队列中的节点为同一层的节点
p = que.front();
que.pop();
if (p->leftChild)
que.push(p->leftChild);
if (p->rightChild)
que.push(p->rightChild);
}
}
return deepth;
}
template<typename T>
void BinaryTree<T>::Deep()const
{
cout << "the deep is " << this->deepPrivate() << " of the tree" << endl;
}
template<typename T>
int BinaryTree<T>::deep(BinaryTreeNode<T>* str)const
{
if (str == NULL)
return 0;
int h1, h2;
h1 = deep(str->leftChild);
h2 = deep(str->rightChild);
return h1 > h2 ? h1 + 1 : h2 + 1;
}
template<typename T>
bool BinaryTree<T>::isEmpty()
{
if (this->root == NULL)
return true;
return false;
}
template<typename T>
BinaryTree<T>::BinaryTree()
{
this->root = NULL;
}
template<typename T>
BinaryTree<T>::~BinaryTree()
{
this->makeEmpty(this->root);
}
template<typename T>
BinaryTreeNode<T>* BinaryTree<T>::getRoot()
{
if (this->isEmpty())
{
cout << "the tree is empty" << endl;
exit(true);
}
return this->root;
}
template<typename T>
T BinaryTree<T>::reValue(BinaryTreeNode<T>* str)const
{
if (str == NULL)
{
cout << "the point is null" << endl;
exit(true);
}
return str->data;
}
template<typename T>
void BinaryTree<T>::reSet(BinaryTreeNode<T>* str, const T& val)
{
if (str == NULL)
{
cout << "the point is null" << endl;
exit(true);
}
str->data = val;
}
template<typename T>
void BinaryTree<T>::makeEmpty(BinaryTreeNode<T>* &str)
{
if (str)
{
makeEmpty(str->leftChild);
makeEmpty(str->rightChild);
delete str;
}
str = NULL;
}
template<typename T>
void BinaryTree<T>::creat()
{
this->CreatBiTree(root);
}
template<typename T>
void BinaryTree<T>::CreatBiTree(BinaryTreeNode<T>* &str)
{
T value;
if (root == NULL)
{
cout << "the root data is: ";
}
cin >> value;
if (value == '#')
{
str = NULL;
return;
}
else
{
str = new BinaryTreeNode<T>(value, NULL, NULL);
cout << "input the " << str->data << " leftchild: ";
CreatBiTree(str->leftChild);
cout << "input the " << str->data << " rightchild: ";
CreatBiTree(str->rightChild);
}
}
template<typename T>
void BinaryTree<T>::PrintInOrder(BinaryTreeNode<T>* str)
{
if (str != NULL)
{
PrintInOrder(str->leftChild);
cout << str->data << " ";
PrintInOrder(str->rightChild);
}
else
return;
}
template<typename T>
void BinaryTree<T>::PrintLevelOrder()
{
BinaryTreeNode<T>* p = this->root;
queue<BinaryTreeNode<T>*>nodeQue;
if (p != NULL)
nodeQue.push(p);
while (!nodeQue.empty())
{
p = nodeQue.front();
nodeQue.pop();
cout << p->data << " ";
if (p->leftChild)
nodeQue.push(p->leftChild);
if (p->rightChild)
nodeQue.push(p->rightChild);
}
cout << endl;
}
template<typename T>
void BinaryTree<T>::PrintPostOrder(BinaryTreeNode<T>* str)
{
if (str != NULL)
{
PrintPostOrder(str->leftChild);
PrintPostOrder(str->rightChild);
cout << str->data << " ";
}
}
#endif
//主函数
#include"BinaryTree.h"
int main(int argc, char argv[])
{
BinaryTree<char>tree;
tree.creat();
tree.PrintInOrder(tree.getRoot());
cout << endl;
tree.PrintLevelOrder();
tree.PrintPostOrder(tree.getRoot());
cout << endl;
tree.Deep();
tree.simulate();
tree.PrintPostOrder(tree.getRoot());
cout << endl;
tree.Deep();
return 0;
}


• 本文已收录于以下专栏：

## 根据前序和中序遍历还原二叉树后序遍历（hihocoder 1049）

• Z_zhangyinqian
• 2015年12月02日 10:55
• 775

## 根据二叉树前序、中序遍历还原二叉树

• w823626691
• 2014年04月07日 14:02
• 1444

## 从前序+中序或者后序+中序序列中恢复二叉树过程

• dalong277
• 2016年04月26日 11:18
• 1652

## 如何根据前序、中序、后序遍历还原二叉树

• yanerhao
• 2015年04月21日 20:49
• 5272

## 根据二叉树的中序和后序还原二叉树

P：终点时要明白二叉树的几种遍历方法以及规律； 先序：中左右。 中序：左中右。 后序：左右中。 上面的左右皆为中的子树，所以优势具有二叉树的特性，那么我们就可以递归还原树了； 这里是一个二叉树还原及求...
• KIJamesQi
• 2015年09月20日 10:47
• 819

## 数据结构与算法简记：通过前序中序或中序后序构建二叉树

• liuhe688
• 2016年07月08日 12:10
• 1980

## 通过先序和中序或后序和中序画出二叉树

• whoamiyang
• 2016年03月13日 08:59
• 754

## 根据先序和中序还原(重建)一个二叉树

package tree.BinaryTree;import java.util.Arrays;/** * 根据先序和中序还原一个二叉树 * * @author yuzhiyun * */...
• yuzhiyun3536
• 2016年12月05日 16:06
• 481

## 二叉树前序,中序转后序

• wu_cai_
• 2016年09月17日 11:24
• 539

## 二叉树前序、中序、后序遍历的相互求法

• u014536527
• 2016年03月30日 02:45
• 5775

举报原因： 您举报文章：二叉树三种遍历方式，有先序，中序或者后序，中序恢复二叉树等操作 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)