二叉树建树与前序、中序、后序、层次遍历实现(C语言)

该博客主要介绍用C语言实现二叉树的建树与遍历。实现思路包括构造辅助队列层次建树,前、中、后序遍历采用递归思想,复用队列代码简化层次遍历。练习部分实现了二叉树层次建树,并进行前序、中序、后序、层序遍历,最后打印结果并测试。

实现思路:

1. 构造辅助队列以实现层次建树。实现二叉树的链式表示时,先申请新结点再将结点入队列,各结点依次出队列并放入合适的左右孩子处。

2. 前序、中序、后序遍历时采用递归思想。

3. 可复用前面实现队列时所写的代码,使用头文件简化代码。层次遍历时采用了这一写法。

练习:

实现二叉树层次建树,进行前序遍历、中序遍历、后序遍历、层序遍历并打印输出。

1. function.h头文件
#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;


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 elem);
//出队
void DeQueue(LinkQueue &q,ElemType &element);
2. queue.cpp文件(代码复用)
#include "function.h"
//队列初始化,使用带头结点的链表
void InitQueue(LinkQueue &q){
    q.front =q.rear=(LinkNode*)malloc(sizeof(LinkNode));//头和尾指向同一个结点
    q.front->next = NULL;//头结点的next指针 为NULL
}
//判断队列是否为空
bool IsEmpty(LinkQueue &q){
    if(q.front == q.rear){
        return true;
    }else{
        return false;
    }
}
//入队
void EnQueue(LinkQueue &q,ElemType elem){
    LinkNode *pnew = (LinkNode*)malloc(sizeof(LinkNode));
    pnew->data=elem;
    pnew->next=NULL;//初始化next,链表结束标志,不能忘!!!
    q.rear->next=pnew;//尾部入队,尾指针指向pnew
    q.rear=pnew;//更新尾指针
}
//出队
void DeQueue(LinkQueue &q,ElemType &element){
    if(IsEmpty(q)){//判空
//        printf("DeQueue false\n");
        return;
    }
    LinkNode *p=q.front->next;//拿到第一个结点,存入p
    element=p->data;//获取要出队的元素值
    q.front->next=p->next;//让第一个结点断链
    if(q.rear==p){
        q.rear=q.front;
    }
    free(p);
//    printf("DeQueue element %d\n", element);
}
3. 前序遍历
//前序遍历,先序遍历,深度优先遍历,递归思想
void PreOrder(BiTree p){
    if(NULL != p) {
        printf("%c", p->c);
        PreOrder(p->lchild);//打印左子树
        PreOrder(p->rchild);//打印右子树
    }
}
4. 中序遍历
//中序遍历
void InOrder(BiTree p){
    if(NULL != p) {
        InOrder(p->lchild);
        printf("%c", p->c);
        InOrder(p->rchild);
    }
}
5. 后序遍历
//后序遍历
void PostOrder(BiTree p){
    if(NULL != p) {
        PostOrder(p->lchild);
        PostOrder(p->rchild);
        printf("%c", p->c);
    }
}
6. 层序遍历
//层次遍历,层序遍历,广度优先遍历
void LevelOrder(BiTree T){
    LinkQueue Q;
    InitQueue(Q);
    BiTree 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);
        }
    }
}
7. 主函数,包括二叉树建树与遍历结果打印
int main() {
    BiTree pnew;//申请一个树的新结点
    BiTree tree=NULL;//代表树,指向树根,不分带不带头结点
    char c;
    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;//tree指向树的根结点
            phead=listpnew;//第一个结点是队列头,也是队列尾
            ptail=listpnew;
            pcur=listpnew;//pcur指向要进入树的父亲元素
        }else{
            //让元素先入队列
            ptail->pnext=listpnew;
            ptail=listpnew;
            //将结点放入树中
            if(NULL == pcur->p->lchild){
                pcur->p->lchild=pnew;//pcur->p左孩子为空,放入左孩子
            }else if(NULL == pcur->p->rchild){
                pcur->p->rchild=pnew;//pcur->p右孩子为空,放入右孩子
                pcur=pcur->pnext;//当前结点左右孩子都有了,pcur指向下一个结点
            }
        }
    }
    printf("PreOrder:\t");
    PreOrder(tree);
    printf("\nInOrder:\t");
    InOrder(tree);
    printf("\nPostOrder:\t");
    PostOrder(tree);
    printf("\nLevelOrder:\t");
    LevelOrder(tree);
    printf("\n");
    return 0;
}
8. 测试

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

多多想

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

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

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

打赏作者

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

抵扣说明:

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

余额充值