数据结构之二叉树来实现四种遍历(进阶版)(C语言实现版)

前面有一期是关于二叉树的三种遍历方式实现代码,那是属于简单版,结合二叉树的顺序存储。而这期文章是结合二叉树的链式存储来解决四种遍历(包括前面因为复杂麻烦没说的层次遍历),这主要结合队列的知识来实现层次遍历代码。下面一起来看看代码吧。

完整代码:

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

struct tree_node //定义树结点
{
    char id;
    struct tree_node* left;
    struct tree_node* right;
};

struct queue_node //定义队列结点
{
    struct tree_node* treenode;
    struct queue_node* next;
};

struct queue //定义队列结构类型
{
    struct queue_node* front;
    struct queue_node* rear;
};
//几个自定义
typedef struct tree_node TreeNode;
typedef struct tree_node* Tree;
typedef struct queue_node QueueNode;
typedef struct queue Queue;

void CreateTree(Tree*);
int GetHeight(Tree);
int MaxOfTwo(int, int);
int GetNodeNumber(Tree);
void PreShow(Tree);
void MidShow(Tree);
void BackShow(Tree);
void LevelShow(Tree);
void InitQueue(Queue*);
bool IsQueueEmpty(Queue*);
void InQueue(Queue*, QueueNode*);
void OutQueue(Queue*, QueueNode**);
void ClearTree(Tree*);
bool IsTreeEmpty(Tree);


//创建二叉树
void CreateTree(Tree* T)
{
    char ch;

    scanf_s("%c", &ch,250);
    if (ch == '*')//第一个根节点不能为空,之后若为空,就创建右子树
    {
        *T = NULL;
    }
    else
    {
        *T = (Tree)malloc(sizeof(TreeNode)); // 注意第一个元素是做根节点
        (*T)->id = ch;
        CreateTree(&(*T)->left);//创建左子树,从上到下依次为输入的顺序,
        CreateTree(&(*T)->right);//创建右子树
    }
}
//两数较大值
int MaxOfTwo(int a, int b)
{
    if (a >= b)
    {
        return a;
    }
    else
    {
        return b;
    }
}
//获得二叉树的高度
int GetHeight(Tree T)
{
    if (T)
    {
        return MaxOfTwo(GetHeight(T->left), GetHeight(T->right)) + 1;
    }
    else
    {
        return 0;
    }
}

//获得二叉树的节点数
int GetNodeNumber(Tree T)
{
    if (T)
    {
        return GetNodeNumber(T->left) + GetNodeNumber(T->right) + 1;//+1是加上根节点
    }
    else
    {
        return 0;
    }
}

//前序遍历
void PreShow(Tree T)
{
    if (!T)
    {
        return;
    }
    printf("%c ", T->id);
    PreShow(T->left);
    PreShow(T->right);
}

//中序遍历
void MidShow(Tree T)
{
    if (!T)
    {
        return;
    }

    MidShow(T->left);
    printf("%c ", T->id);
    MidShow(T->right);
}

//后序遍历
void BackShow(Tree T)
{
    if (!T)
    {
        return;
    }

    BackShow(T->left);
    BackShow(T->right);
    printf("%c ", T->id);
}
//初始化队列
void InitQueue(Queue* q)
{
    q->front = NULL;
    q->rear = NULL;
}

//队列是否为空
bool IsQueueEmpty(Queue* q)
{
    if (q->front)
    {
        return false;
    }
    else
    {
        return true;
    }
}

//进队
void InQueue(Queue* q, QueueNode* p)
{
    if (IsQueueEmpty(q))//若为空,则头指针和尾指针都指向p
    {
        q->front = p;
        q->rear = p;
    }
    else//链式进入队列
    {
        q->rear->next = p;
        q->rear = p;
    }
}

//出队
void OutQueue(Queue* q, QueueNode** p)
{
    *p = q->front;

    if (q->front == q->rear) //只有1个节点
    {
        q->front = NULL;
        q->rear = NULL;
    }
    else
    {
        q->front = q->front->next;
    }
}

//层序遍历
void LevelShow(Tree T)
{
    if (!T)
    {
        return;
    }
    Queue m_queue;
    Queue* Q;
    QueueNode* p, * q;
    Q = &m_queue;
    InitQueue(Q); //队列初始化
    p = (QueueNode*)malloc(sizeof(QueueNode));
    p->next = NULL;
    p->treenode = T;
    InQueue(Q, p); //根节点进队
    while (!IsQueueEmpty(Q))
    {
        OutQueue(Q, &q); //当前队首节点出队
        printf("%c ", q->treenode->id);
        //按照先左后右的顺序,这里并不用到递归
        if (q->treenode->left) //左孩子非空,则左孩子进队
        {
            p = (QueueNode*)malloc(sizeof(QueueNode));
            p->next = NULL;
            p->treenode = q->treenode->left;
            InQueue(Q, p);
        }
        if (q->treenode->right) //右孩子非空,则右孩子进队
        {
            p = (QueueNode*)malloc(sizeof(QueueNode));
            p->next = NULL;
            p->treenode = q->treenode->right;
            InQueue(Q, p);
        }
    }
}
//清除二叉树
void ClearTree(Tree* T)
{
    if (!*T)
    {
        return;
    }

    ClearTree(&(*T)->left);
    ClearTree(&(*T)->right);
    free(*T);
    *T = NULL;
}

//二叉树是否为空
bool IsTreeEmpty(Tree T)
{
    if (T)
    {
        return false;
    }
    else
    {
        return true;
    }
}
int main(void)
{
    Tree t;

    printf("输入二叉树的前序遍历序列,用*代替空节点:\n");
    CreateTree(&t);

    printf("\n二叉树创建完毕,高度为%d,节点数为%d。", GetHeight(t), GetNodeNumber(t));

    printf("\n\n前序遍历:");
    PreShow(t);

    printf("\n\n中序遍历:");
    MidShow(t);

    printf("\n\n后序遍历:");
    BackShow(t);

    printf("\n\n层序遍历:");
    LevelShow(t);

    ClearTree(&t);
    if (IsTreeEmpty(t))
    {
        printf("\n\n二叉树已经删除。");
    }
    printf("\n\n");

    return 0;
}

程序执行图:

只要大家去好好理解一下层次遍历,会发现其实一点都不难,都没用到递归,只是结合到队列的知识从而程序代码量多了点。

本贴为博主亲手整理。如有错误,请评论区指出,一起进步。谢谢大家的浏览.


 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值