开天辟地的卷毛 2022-11-19 21:37 采纳率: 83.7%
浏览 5
已结题

二叉树按层遍历,传参问题


//binary tree
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>

//bt树节点数据类型
typedef struct btnode
{
    char  btdata;//数据域
    struct btnode* plch;//定义指向结构体左孩子的指针
    struct btnode* prch;//定义指向结构体右孩子的指针
}BTND, * PBTND;

//设计队列节点结构体
typedef struct qnode
{
    PBTND data;         //数据域存放b树节点的地址,所以定义为指向树结构的指针
    struct qnode* next;//指向下一个同类型的结构体,
}QND, * PQND;

//设计管理链式队列的数据类型
typedef struct link_queue
{
    PQND front;//队头指针 
    PQND rear;//队尾指针
}QUE, * PQUE;
//新建二叉树

bool is_empty(PQUE queue);

PBTND init_btree(void)
{
    PBTND pa = (PBTND)malloc(sizeof(BTND));
    if (pa == NULL)
        return pa;
    PBTND pb = (PBTND)malloc(sizeof(BTND));
    if (pb == NULL)
        return pb;
    PBTND pc = (PBTND)malloc(sizeof(BTND));
    if (pc == NULL)
        return pc;
    PBTND pd = (PBTND)malloc(sizeof(BTND));
    if (pd == NULL)
        return pd;
    PBTND pe = (PBTND)malloc(sizeof(BTND));
    if (pe == NULL)
        return pe;
    PBTND pf = (PBTND)malloc(sizeof(BTND));
    if (pf == NULL)
        return pf;
    PBTND pg = (PBTND)malloc(sizeof(BTND));
    if (pg == NULL)
        return pg;
    PBTND ph = (PBTND)malloc(sizeof(BTND));
    if (ph == NULL)
        return ph;
    //根节点左右孩子
    pa->plch = pb;
    pa->prch = pc;
    //b节点左右孩子
    pb->plch = pd;
    pb->prch = pe;
    //c节点左右孩子
    pc->plch = pf;
    pc->prch = NULL;
    //d节点左右孩子
    pd->plch = pd->prch = NULL;
    //e节点左右孩子
    pe->plch = pe->prch = NULL;
    //f节点的左右孩子
    pf->plch = pg;
    pf->prch = ph;
    //g节点的左右孩子
    pg->plch = pg->prch = NULL;
    //h节点的左右孩子
    ph->plch = ph->prch = NULL;

    //存入数据
    pa->btdata = 'a';
    pb->btdata = 'b';
    pc->btdata = 'c';
    pd->btdata = 'd';
    pe->btdata = 'e';
    pf->btdata = 'f';
    pg->btdata = 'g';
    ph->btdata = 'h';
    return pa;
}

PQUE initqueue(void)
{
    //建立管理结构体queue。申请结构体空间大小为LQ类型,返回值类型为管理结构体指针
    //类型
    PQUE queue = (PQUE)malloc(sizeof(QUE));
    if (queue == NULL)
        return queue;
    //建立头节点phead.申请结构体空间大小类型为OD类型,返回值类型为节点结构体指针
    //类型
    PQND phead = (PQND)malloc(sizeof(QND));
    if (phead == NULL)
    {
        printf("malloc fail\n");
        free(queue);
        return NULL;
    }
    queue->front = queue->rear = phead;
    phead->next = NULL;
    return queue;
}

//入队,链式队列没有队满的状态
bool enqueue(PQUE queue, PBTND d)
{
    //建立新节点,申请空间1个OD类型大小(也就是它本身)。
    PQND pnew = (PQND)malloc(sizeof(QND));
    if (pnew == NULL)
        return false;
    //将树节点赋值给pnew的数据域,完成入队
    pnew->data = d;
    //新节点的next为空
    pnew->next = NULL;

    queue->rear->next = pnew;//将rear的next指向新节点,完成队列连接
    queue->rear = pnew;      //pnew赋值给rear,将rear指针移至新节点,保证rear始终在队尾
    return true;
}

//出队,形参为结构体指针queue,与节点结构体指针re_val,此形参存储结构体变量地址.
bool dequeue(PQUE queue, PBTND ret_val)
{
    if (is_empty(queue))
    {
        printf("the lqueue is empty\n");
        return false;
    }
    //将即将出队的节点存储起来.ret_val指向的是即将出队的树节点的地址
    ret_val = queue->front->next->data;
    //定义临时节点结构体指针,存储头指针的next,方便后续出队操作
    PQND ptamp = queue->front->next;

    queue->front->next = ptamp->next;
    /*首先要考虑所有节点出队之后, 尾指针必须要归位指向头节点, 判断方法是当front
    的next位空时,此时队列就没有节点了,所以将rear赋值为front,也相当于指向头节点*/
    if (queue->front->next == NULL)
        queue->rear = queue->front;
    ptamp->next = NULL;
    free(ptamp);
    return true;
}

//判空
bool is_empty(PQUE queue)
{
    if (queue->front == queue->rear)
        return true;
    else
        return false;
}

//按层遍历
void level_show(PBTND proot)
{
    //建立管理结构体
    PQUE queue = initqueue();
    PBTND de_val=(PBTND)malloc(sizeof(BTND)); //定义队列节点结构体变量de_val,用来存储出队的树的节点
    if (de_val == NULL)
        return;
    //定义临时变量,拷贝proot的地址
    PBTND ptmp = proot;
    enqueue(queue, ptmp);//根节点入队
    while (!is_empty(queue))//判断队列不为空,则进入while循环
    {
        dequeue(queue, de_val);//把队列queue指针,de_val的地址作为实参传入函数
        if (de_val != NULL)
        {
            printf("%c\t", de_val->btdata);//将出队的树节点打印出来
            //判断此时出队的树节点是否有左孩子,有就左孩子入队
            if (de_val->plch != NULL)
                enqueue(queue, de_val->plch);
            //判断此时出队的的树节点是否有右孩子,有就右孩子入队
            if (ptmp->prch != NULL)
                enqueue(queue, de_val->prch);
        }
    }
    return;
}
int main(void)
{
    PBTND proot = init_btree();
    pre_show(proot);
    printf("\n");
    mid_show(proot);
    printf("\n");
    last_show(proot);
    printf("\n");
    level_show(proot);
    return 0;
}


//先序遍历:先访问根节点,然后先序遍历左子树,最后先序遍历右子树.
//中序遍历:先中序遍历左子树,然后访问根节点,最后中序遍历右子树.
//后序遍历:先后序遍历左子树,然后后序遍历右子树,最后访问根节点

问题,在按层遍历的函数里为什么最后printf出来是乱码。dequeue里的ret_val明明赋值,但是回到按层遍历的时候,不能将de_val打印出来

  • 写回答

0条回答 默认 最新

    报告相同问题?

    问题事件

    • 系统已结题 11月27日
    • 创建了问题 11月19日

    悬赏问题

    • ¥15 Android studio AVD启动不了
    • ¥15 陆空双模式无人机怎么做
    • ¥15 想咨询点问题,与算法转换,负荷预测,数字孪生有关
    • ¥15 C#中的编译平台的区别影响
    • ¥15 软件供应链安全是跟可靠性有关还是跟安全性有关?
    • ¥15 电脑蓝屏logfilessrtsrttrail问题
    • ¥20 关于wordpress建站遇到的问题!(语言-php)(相关搜索:云服务器)
    • ¥15 【求职】怎么找到一个周围人素质都很高不会欺负他人,并且未来月薪能够达到一万以上(技术岗)的工作?希望可以收到写有具体,可靠,已经实践过了的路径的回答?
    • ¥15 Java+vue部署版本反编译
    • ¥100 对反编译和ai熟悉的开发者。