分析
很典型、常见的一道题目,二叉树的前序、中序、后续遍历以及转换,实现二叉树的数据结构,二叉树的层序遍历等,都是算法题几乎必考、必须掌握的基本技能。这里又碰到了,再写一遍加深印象。
代码分解
二叉树的数据结构
struct Node
{
Node* lchild;
Node* rchild;
int c;
}Tree[50];
节点的创建、空间分配
有一个全局变量loc,它记录着我们的Tree[50]使用到第几个单元空间。返回新创建节点的地址。
Node *create()
{
Tree[loc].lchild = Tree[loc].rchild = NULL;
return &Tree[loc++];
}
层序遍历(栈)
从根节点开始,如果当前节点有左儿子,左儿子入栈,如果有右儿子,右儿子入栈,打印当前节点,然后从栈中弹出。栈不为空时,一直对栈顶元素做这样的处理。根据栈先入先出的特点,可以确定这样操作得到的是层序遍历,有广度优先搜索的思想。
void levelOrder(Node* T)
{
queue<Node*> q;
if (T->lchild != NULL)
{
q.push(T->lchild);
}
if (T->rchild != NULL)
{
q.push(T->rchild);
}
printf("%d", T->c);
while (q.empty() == false)
{
Node* tmp = q.front();
printf(" %d", tmp->c);
if (tmp->lchild != NULL)
{
q.push(tmp->lchild);
}
if (tmp->rchild != NULL)
{
q.push(tmp->rchild);
}
q.pop();
}
}
根据后序、中序遍历构造树
后序和中序遍历结果保存在整型数组中。函数参数意义:后序遍历结果由post[s1]到post[e1],中序遍历结果由in[s1]到in[e1]。首先为该段树的树根节点申请空间,可以得知该段树的根节点为post[e1](后序遍历的最后一个节点),然后遍历中序遍历结果,查找该根节点在中序遍历中的位置,用rootIdx记录。中序遍历中,rootIdx之前为左子树的中序遍历,rootIdx之后为右子树的中序遍历。再根据左、右子树的节点数量推断出左、右子树在后序遍历中各自的起止位置。若左子树不为空,递归还原左子树;若右子树不为空,递归还原右子树。
这题的重点在于递归时起止位置的书写,很容易出错。
Node *build(int s1, int e1, int s2, int e2)
{
Node* ret = create();
ret->c = post[e1];
int rootIdx;
for (int i = s2; i <= e2; i++)
{
if (in[i] == post[e1])
{
rootIdx = i;
break;
}
}
if (rootIdx != s2)
{
ret->lchild = build(s1, s1 + (rootIdx - s2) - 1, s2, rootIdx - 1);
}
if (rootIdx != e2)
{
ret->rchild = build(s1 + rootIdx - s2, e1 - 1, rootIdx + 1, e2);
}
return ret;
}
代码
最后贴上整体的代码。我的代码风格可能不是很好,欢迎各位小伙伴批评指正呀!!!
祝大家PAT都能顺利满分喔!!!
#include<stdio.h>
#include<queue>
using namespace std;
struct Node
{
Node* lchild;
Node* rchild;
int c;
}Tree[50];
int loc = 0;
int post[50], in[50];
int N;
Node *create()
{
Tree[loc].lchild = Tree[loc].rchild = NULL;
return &Tree[loc++];
}
void levelOrder(Node* T)
{
queue<Node*> q;
if (T->lchild != NULL)
{
q.push(T->lchild);
}
if (T->rchild != NULL)
{
q.push(T->rchild);
}
printf("%d", T->c);
while (q.empty() == false)
{
Node* tmp = q.front();
printf(" %d", tmp->c);
if (tmp->lchild != NULL)
{
q.push(tmp->lchild);
}
if (tmp->rchild != NULL)
{
q.push(tmp->rchild);
}
q.pop();
}
}
Node *build(int s1, int e1, int s2, int e2)
{
Node* ret = create();
ret->c = post[e1];
int rootIdx;
for (int i = s2; i <= e2; i++)
{
if (in[i] == post[e1])
{
rootIdx = i;
break;
}
}
if (rootIdx != s2)
{
ret->lchild = build(s1, s1 + (rootIdx - s2) - 1, s2, rootIdx - 1);
}
if (rootIdx != e2)
{
ret->rchild = build(s1 + rootIdx - s2, e1 - 1, rootIdx + 1, e2);
}
return ret;
}
int main()
{
scanf("%d", &N);
for (int i = 0; i < N; i++)
{
scanf("%d", &post[i]);
}
for (int i = 0; i < N; i++)
{
scanf("%d", &in[i]);
}
Node* T = build(0, N - 1, 0, N - 1);
levelOrder(T);
return 0;
}