浙大 PAT 甲级 1020 Tree Traversals C++ 树的层序遍历

 

 

 

分析

很典型、常见的一道题目,二叉树的前序、中序、后续遍历以及转换,实现二叉树的数据结构,二叉树的层序遍历等,都是算法题几乎必考、必须掌握的基本技能。这里又碰到了,再写一遍加深印象。

代码分解

二叉树的数据结构

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;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值