题目信息
给出二叉树的中序遍历序列和后序遍历序列,编程还原该二叉树。
输入
第1行:二叉树的中序遍历序列
第2行:二叉树的后序遍历序列
输出
二叉树的按层遍历序列
测试样例
测试样例1
badcfeg
bdfgeca
abcdefg
测试样例2
cbdafeg
cbdfgea
adebfgc
测试样例3
edcba
edcba
abcde
解答
#include <iostream>
#include <queue>
#include <stack>
#include <string>
using namespace std;
struct BTreeNode
{
char data;
BTreeNode *Left;
BTreeNode *Right;
};
class BTree
{
public:
//传参需要注意,二叉树是指针类型的,节点本身就是一个指针:*node。所以需要二级指针才能改变二叉树的内容
void Create(BTreeNode *Node)
{//按层创建二叉树
queue<BTreeNode *> que;
que.push(Node);
while (!que.empty())
{
char ch;
ch = getchar();
BTreeNode *node = que.front();
que.pop();
if (ch == '\n')
{
break;
}
node->data = ch;
node->Left = new BTreeNode;
node->Left->data = '\0';
que.push(node->Left);
node->Right = new BTreeNode;
node->Right->data = '\0';
que.push(node->Right);
}
}
void DisPlay(BTreeNode *Node, int depth)
{
if (Node->data != '#' && Node->data != '\0')
{//既不是空也不是虚节点
for (int i = 0; i < depth; i++)
{
cout << " ";
}
cout << Node->data << endl;
depth++;
DisPlay(Node->Left, depth);
DisPlay(Node->Right, depth);
}
}
void preorderTree(BTreeNode *Node)
{//前序遍历(根左右)
if (Node->data != '#' && Node->data != '\0')
{
cout << Node->data;
preorderTree(Node->Left);
preorderTree(Node->Right);
}
}
void inorderTree(BTreeNode *Node)
{//中序遍历(左中右)
if (Node->data != '#' && Node->data != '\0')
{
inorderTree(Node->Left);
cout << Node->data;
inorderTree(Node->Right);
}
}
void postorderTree(BTreeNode *Node)
{ //后序遍历(左右中)
if (Node->data != '#' && Node->data != '\0')
{
postorderTree(Node->Left);
postorderTree(Node->Right);
cout << Node->data;
}
}
void levelTree(BTreeNode *Node)
{//层序遍历
queue<BTreeNode *> que;
if (Node == NULL) return;
else
{
que.push(Node);
while (!que.empty())
{
BTreeNode *node = que.front();
cout << node->data;
que.pop();
if (node->Left->data != '#' && node->Left->data != '\0')
{
que.push(node->Left);
}
if (node->Right->data != '#' && node->Right->data != '\0')
{
que.push(node->Right);
}
}
}
}
int depthOfTree(BTreeNode *Node)
{//二叉树深度
if (Node->data != '#' && Node->data != '\0')
{
return max(depthOfTree(Node->Left), depthOfTree(Node->Right)) + 1;
}
else
{
return 0;
}
}
int getNodeNum(BTreeNode *Node)
{//返回节点总数目
if (Node->data != '#' && Node->data != '\0')
{
return 1 + getNodeNum(Node->Left) + getNodeNum(Node->Right);
}
else
{
return 0;
}
}
int getLeafNum(BTreeNode *Node)
{//返回叶子节点
if (Node->data == '#' || Node->data == '\0')
{
return 0;
}
else if ((Node->Left->data == '#' || Node->Left->data == '\0') &&
(Node->Right->data == '#' || Node->Right->data == '\0'))
{
return 1;
}
else
{
return getLeafNum(Node->Left) + getLeafNum(Node->Right);
}
}
void SwapTree(BTreeNode *Node)
{
if (Node->data != '#' && Node->data != '\0')
{
swap(Node->Left, Node->Right);
SwapTree(Node->Left);
SwapTree(Node->Right);
}
return;
}
BTreeNode *restore(string mid, string back, int length)
{//根据中序和后序两个字符串来建立完整的二叉树
if (length == 0)
{
return NULL;
}
BTreeNode *node = new BTreeNode;//先构建一个节点
node->data = back[length - 1];//使节点值为back中最后一个,因为那个一定是根节点的数值
int rootIndex;
for (rootIndex = 0; rootIndex < length; rootIndex++)
{//找到根节点在中序中的位置
if (mid[rootIndex] == back[length - 1])
{
break;
}
}
node->Left = restore(mid, back, rootIndex);
if (node->Left == NULL)
{
node->Left = new BTreeNode;
node->Left->data = '#';
}
string backmid(mid, rootIndex + 1);
string backback(back, rootIndex);
node->Right = restore(backmid, backback, length - rootIndex - 1);
if (node->Right == NULL)
{//加入是空指针的话,也为其开上内存,但其值存为#即可
node->Right = new BTreeNode;
node->Right->data = '#';
}
return node;
}
};
int main()
{
//freopen("/Users/zhj/Downloads/test.txt", "r", stdin);
string mid, back;
cin >> mid >> back;
BTreeNode *Root = new BTreeNode;
BTree bTree;
Root = bTree.restore(mid, back, back.length());
bTree.levelTree(Root);
cout << endl;
return 0;
}
想法
本题在仍然使用之前的类的基础上做了一个函数的扩充,故需同时满足之前对于空二叉树的判定,其判定条件为data值为#
或者是\0
.
相关题目
二叉树的建立与基本操作
二叉树最近的公共祖先
二叉树先序,中序,后序,层序遍历还原
二叉树遍历序列还原·已知中序遍历和层序遍历