根据广义表创建二叉树以及层次遍历

【问题描述】 考研真题:给定一颗二叉树,要求从下至上按层遍历二叉树,每层的访问顺序是从左到右,每一层单独输出一行。

【输入形式】 广义表表示的二叉树,结点元素类型为整型,且都大于0,例如:1( 2( 3 ( 4, 5 ) ), 6( 7, 8( 9, 10 ) ) )

【输出形式】 从下至上,打印每一层的结点元素值,元素间以空格隔开。每层的访问顺序是从左到右,每一层单独输出一行。

【样例输入】 1(2(3(4,5)),6(7,8(9,10))),字符串内没有空格

【样例输出】

4 5 9 10

3 7 8

2 6

1

审题:

1.根据广义表创建一颗二叉树

2.层次遍历这个二叉树

首先解决第一个问题——根据广义表创建二叉树。

题目中给的示例1(2(3(4,5)),6(7,8(9,10))),转化为二叉树如下图所示。

我们可以看到,广义表形式的二叉树其实结构上是_(_( ),_( ))第一个下划线代表双亲结点第二个和第三个下划线代表孩子结点孩子结点有可能不存在。

举个例子图中的1、2、6,在原广义表中是1(2(3(4,5)),6(7,8(9,10)))

又比如图中的3、4、5,在原广义表中是1(2(3(4,5)),6(7,8(9,10)))。

并且,这个结构是层层嵌套的,递归的。

当孩子结点不存在括号的时候,递归结束,也就是3、4、5那种情况。

明白这些之后,那么找到分割左右子树的逗号,就非常重要了。

这里采用栈结构进行括号匹配,如果匹配到逗号时,栈里只有一个左括号,证明这个逗号就是我们要找的逗号。

还有一个值得注意的点是,我们的数据并不全是个位数,所以还要考虑多位数的时候,怎么识别它们。

BiNode* Bitree::create(char *s,int i,int j)//i,j分别指向根节点数字和最后一个右括号
{
    if(i<=j)
    {
        BiNode *r=new BiNode;

        int t=i;
        while(1)
        {
            if(s[t]<'0'||s[t]>'9')
                break;
            t++;
        }

        int sum=0;
        for(int k=i;k<=t-1;k++)
        {
            sum=sum*10+s[k]-'0';//不能写+=
        }

        r->data=sum;

        if(i==j||j==t-1)
        {
            return r;
        }
        else{
            int rr=i+1;
            int flag=0;//判断有无逗号存在
            Stack st;//括号匹配专用栈
            while(rr<=j)//找到分割左右子树的逗号位置
            {
                switch(s[rr])
                {
                    case '(':st.push(s[rr]);break;
                    case ')':st.pop();break;
                }
                if(s[rr]==','&&st.data[st.top]=='('&&st.top==0)
                {
                    flag=1;
                    break;
                }
                rr++;
            }

            if(flag)
            {
                r->lf=create(s,i+2,rr-1);
                r->rt=create(s,rr+1,j-1);
            }

            else
            {
                r->lf=create(s,i+2,rr-2);
                r->rt=NULL;
            }
        }
        return r;
    }
    else
        return NULL;
}

创建之后,层次遍历这个二叉树顾名思义就是一层一层的来

因为题目要求把树的层次倒过来输出,所以我选择首先把这棵树存进二位数组里,再遍历。

所以在层次遍历的同时还要求二叉树的宽度和深度

int tree[N][N]={0};
int width[N]={0};//记录第n层的宽度
int depth=0;//记录深度
void Bitree::bfs()
{
    Queue q;int i=0,j=0;
    q.enterQueue(*root);
    int c=1;//上一层最右侧de后一位
    while(q.len!=0)
    {
        BiNode temp=q.outQueue();
        tree[i][j++]=temp.data;

        if(temp.lf!=NULL)
            q.enterQueue(*temp.lf);
        if(temp.rt!=NULL)
            q.enterQueue(*temp.rt);

        if(q.fr==c)
        {
            c=q.re;
            width[i]=j;
            i++;
            j=0;
        }
    }
    depth=i;
}

void Bitree::output()
{
    for(int i=depth-1;i>=0;i--)
    {
        for(int j=0;j<width[i];j++)
        {
            cout<<tree[i][j]<<' ';
        }
        cout<<endl;
    }
}

最后完整代码如下:

#include <iostream>
#include <cstring>
#define N 50
using namespace std;
//层次遍历二叉树
//根据广义表创建二叉树
class BiNode
{
public:
    BiNode *lf,*rt;
    int data;
    BiNode():lf(NULL),rt(NULL){}
};

class Bitree
{
public:
    BiNode *root;
    Bitree():root(NULL){}
    BiNode* create(char *s,int i,int j);
    void print(BiNode*);
    void bfs();
    void output();
};

class Stack
{
public:
    int top;
    char data[N];
    Stack():top(-1){}
    void push(char ch)
    {
        if(top<N-1)
        {
            data[++top]=ch;
        }
    }
    char pop()
    {
        if(top!=-1)
        {
            return data[top--];
        }
        return '#';
    }
};

class Queue
{
public:
    int fr,re;//队首队尾指针
    int len;//长度
    BiNode data[N];
    Queue():fr(0),re(0){}
    void enterQueue(const BiNode &num)
    {
        if(fr!=re||len==0)
        {
            data[re]=num;
            re=(re+1)%N;
            len++;
        }
    }
    BiNode outQueue()
    {
        if(len!=0)
        {
            BiNode temp=data[fr];
            fr=(fr+1)%N;
            len--;
            return temp;
        }
        return BiNode();
    }
};

BiNode* Bitree::create(char *s,int i,int j)//i,j分别指向根节点数字和最后一个右括号
{
    if(i<=j)
    {
        BiNode *r=new BiNode;

        int t=i;
        while(1)
        {
            if(s[t]<'0'||s[t]>'9')
                break;
            t++;
        }

        int sum=0;
        for(int k=i;k<=t-1;k++)
        {
            sum=sum*10+s[k]-'0';//不能写+=
        }

        r->data=sum;

        if(i==j||j==t-1)
        {
            return r;
        }
        else{
            int rr=i+1;
            int flag=0;//判断有无逗号存在
            Stack st;//括号匹配专用栈
            while(rr<=j)//找到分割左右子树的逗号位置
            {
                switch(s[rr])
                {
                    case '(':st.push(s[rr]);break;
                    case ')':st.pop();break;
                }
                if(s[rr]==','&&st.data[st.top]=='('&&st.top==0)
                {
                    flag=1;
                    break;
                }
                rr++;
            }

            if(flag)
            {
                r->lf=create(s,i+2,rr-1);
                r->rt=create(s,rr+1,j-1);
            }

            else
            {
                r->lf=create(s,i+2,rr-2);
                r->rt=NULL;
            }
        }
        return r;
    }
    else
        return NULL;
}



void Bitree::print(BiNode *p)
{
    if(p!=NULL)
    {
        cout<<p->data;
        print(p->lf);
        print(p->rt);
    }
}

int tree[N][N]={0};
int width[N]={0};//记录第n层的宽度
int depth=0;//记录深度
void Bitree::bfs()
{
    Queue q;int i=0,j=0;
    q.enterQueue(*root);
    int c=1;//上一层最右侧de后一位
    while(q.len!=0)
    {
        BiNode temp=q.outQueue();
        tree[i][j++]=temp.data;

        if(temp.lf!=NULL)
            q.enterQueue(*temp.lf);
        if(temp.rt!=NULL)
            q.enterQueue(*temp.rt);

        if(q.fr==c)
        {
            c=q.re;
            width[i]=j;
            i++;
            j=0;
        }
    }
    depth=i;
}

void Bitree::output()
{
    for(int i=depth-1;i>=0;i--)
    {
        for(int j=0;j<width[i];j++)
        {
            cout<<tree[i][j]<<' ';
        }
        cout<<endl;
    }
}

int main()
{
    char s[N];
    cin.getline(s,N-1);
    //cout<<s<<endl;
    int len=strlen(s);

    Bitree bt;

    bt.root=bt.create(s,0,len-1);
    bt.bfs();
    bt.output();
    return 0;
}

  • 8
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值