二叉树的层序遍历 (层次遍历 广度优先遍历)

#include <stdio.h>
#include <stdlib.h>

typedef char BiElemType;
typedef struct BiTNode{
    BiElemType c;
    struct BiTNode *lchild;
    struct BiTNode *rchild;
}BiTNode,*BiTree;

//tag结构体是辅助队列使用的 队列是由链表实现的
typedef struct tag{
    BiTree p;//树的某一个结点的地址值
    struct tag *pnext;
}tag_t,*ptag_t;//这个链表结构体类型tag_t 为什么和结构体名不一致

//辅助队列 的结构体
typedef BiTree ElemType;
typedef struct LinkNode{
    ElemType data;//
    struct LinkNode *next;
}LinkNode;
typedef struct{//队列结构体
    LinkNode *front,*rear;//链表头 链表尾 可以称为队头 队尾
}LinkQueue;//先进先出


void InitQueue(LinkQueue &Q);
//入队

bool IsEmpty(LinkQueue Q);

void EnQueue(LinkQueue &Q,ElemType x);//不修改故不引用
//出队
bool DeQueue(LinkQueue &Q,ElemType &x);//出队后有可能发生real指向头指针 Q有可能发生改变 所以引用

//队列的初始化,使用的是带头结点的链表来实现的
void InitQueue(LinkQueue &Q)
{
    Q.front=Q.rear=(LinkNode*)malloc(sizeof(LinkNode));
    Q.front->next==NULL;
}

//判断队列是否为空
bool IsEmpty(LinkQueue Q)
{
    return Q.rear==Q.front;
}

//入队
void EnQueue(LinkQueue &Q,ElemType x)//不修改故不引用
{
    LinkNode *pnew=(LinkNode*)malloc(sizeof(LinkNode));
    pnew->data=x;
    pnew->next=NULL;//要让next为NULL
    Q.rear->next=pnew;//尾指针的next指向pnew,因为从尾部入队
    Q.rear=pnew;//rear要指向新的尾部

}

//出队
bool DeQueue(LinkQueue &Q,ElemType &x)//出队后有可能发生real指向头指针 Q有可能发生改变 所以引用
{
    if(Q.rear==Q.front)//队列为空
    {
        return false;
    }
    LinkNode* q=Q.front->next;//拿到第一个结点,存入q
    x=q->data;
    Q.front->next=q->next;//让第一个结点断链
    if(Q.rear==q)//链表只剩余一个结点时,被删除后,要改变rear
    {
        Q.rear=Q.front;
    }
    free(q);
    return true;

}


//前序遍历函数,也叫先序遍历,也是深度优先遍历
void PreOrder(BiTree p)//只是遍历 即只是读,不会改变树根
{//这个p的类型是 树的结构体 不是之前的p指针
    if(p!=NULL)
    {
        printf("%c", p->c);
        PreOrder(p->lchild);//函数嵌套 打印左子树
        PreOrder(p->rchild);//函数嵌套 打印右子树
    }
}
//中序遍历
void InOrder(BiTree p)//只是遍历 即只是读,不会改变树根
{//这个p的类型是 树的结构体 不是之前的p指针
    if(p!=NULL)
    {
        InOrder(p->lchild);//函数嵌套 打印左子树
        printf("%c", p->c);
        InOrder(p->rchild);//函数嵌套 打印右子树
    }
}
//后续遍历
void PostOrder(BiTree p)//只是遍历 即只是读,不会改变树根
{//这个p的类型是 树的结构体 不是之前的p指针
    if(p!=NULL)
    {
        PostOrder(p->lchild);//函数嵌套 打印左子树
        PostOrder(p->rchild);//函数嵌套 打印右子树
        printf("%c", p->c);
    }
}

//层序遍历
//层次遍历 层序遍历 广度优先遍历
void LevelOrder(BiTree T)//树的结构体指针 有左孩子和有孩子
{
    LinkQueue Q;//定义一个队列Q
    InitQueue(Q);//初始化队列Q 队头等于队尾  next指针指向NULL
    BiTree p;//存储出队的结点 p为一个树的结构体指针
    EnQueue(Q,T);//把根入队
    while(!IsEmpty(Q))//队列不为空才进入到循环当中
    {
        DeQueue(Q,p);
        putchar(p->c);//等价于printf("%c",c);
        if(p->lchild)
        {
            EnQueue(Q,p->lchild);//左孩子不为空 入队左孩子
        }
        if(p->rchild)
        {
            EnQueue(Q,p->rchild);
        }
    }


}

int main() {
    BiTree pnew;//用来指向新申请的树结点 结构体指针类型
    BiTree tree=NULL;//tree是指向树根的,代表树
    char c;
    //定义队列 phead是队列头ptail是队列尾 listpnew指向新结点 pcur是指向当前父结点
    ptag_t phead=NULL,ptail=NULL,listpnew=NULL,pcur;
    //输入abcdefghij
    while(scanf("%c",&c))
    {
        if(c=='\n')
        {
            break;//读取换行结束
        }
        //calloc申请的空间大小是两个参数直接相乘,并对空间进行初始化,赋值为0
        pnew= (BiTree)calloc(1,sizeof(BiTNode));
        pnew->c=c;//数据放进去
        listpnew= (ptag_t)calloc(1,sizeof(tag_t));//给队列结点申请空间
        listpnew->p=pnew;
        if(NULL==tree)//如果树为空 放进去即为树根
        {
            tree=pnew;//树的根
            phead=listpnew;//队列头
            ptail=listpnew;//队列尾
            pcur=listpnew;
            continue;
        } else{
            ptail->pnext=listpnew;//新结点放入链表 通过尾插法
            ptail=listpnew;//ptail指向队列尾部
        }//pcur始终指向要插入的结点的位置
        if(NULL==pcur->p->lchild)
        {
            pcur->p->lchild=pnew;//把新结点放到要插入结点的左边
        } else if(NULL==pcur->p->rchild)
        {
            pcur->p->rchild=pnew;//把新结点放到要插入结点的右边
            pcur=pcur->pnext;//左右都放了结点后,pcur指向队列下一个
        }
    }

 //14.5二叉树的前序中序后续遍历
    printf("------------PreOrder------------\n");
    PreOrder(tree);
    printf("\n------------InOrder------------\n");
    InOrder(tree);
    printf("\n------------PostOrder------------\n");
    PostOrder(tree);
    printf("\n------------LevelOrder------------\n");
    LevelOrder(tree);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陆小果不会写代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值