C语言版:数据结构中的二叉树,先序遍历,中序遍历,后序遍历,以及它们的逆序。
文章目录
- 二叉树的遍历
- 一、栈的运用
- 二、遍历方式
- 1.先序遍历
- 2.中序遍历
- 3.后序遍历
- 代码实现
二叉树的遍历
二叉树的遍历方式:先序遍历:头左右,中序遍历:左头右, 后序遍历:左右头 的规则, 下面是本篇文章的二叉树的图。
提示:以下是本篇文章正文内容,下面案例可供参考
一、栈的运用
栈的操作规则:先进后出,比如说进制转化也是栈的应用,前面文章有介绍关于进制转化,二叉树的逆序可以运用栈。
二、遍历方式
1.先序遍历
代码如下(示例):
//正序
void perorder(RTreeNode* p)
{
if (p != NULL)
{
printf("->%c", p->data);
perorder(p->lchild);
perorder(p->rchild);
}//先序遍历
}
//逆序
void sperorder(RStack* S, RTreeNode* p)
{
if (p != NULL)
{
push(S, p->data);//进栈
sperorder(S, p->lchild);
sperorder(S, p->rchild);
}
}//树的遍历都需要进行递归,而结束递归的条件就是p指向空时候
//打印逆序的结果
void treeout(RStack p)
{
while (!empty(&p))
{
printf("->%c", pop(&p));
}
}
2.中序遍历
代码如下(示例):
//正序
void perorder(RTreeNode* p)
{
if (p != NULL)
{
perorder(p->lchild);
printf("->%c", p->data);
perorder(p->rchild);
}//先序遍历
}
//逆序
void sperorder(RStack* S, RTreeNode* p)
{
if (p != NULL)
{
sperorder(S, p->lchild);
push(S, p->data);//进栈
sperorder(S, p->rchild);
}
}//树的遍历都需要进行递归,而结束递归的条件就是p指向空时候
//打印逆序的结果
void treeout(RStack p)
{
while (!empty(&p))
{
printf("->%c", pop(&p));
}
}
3.后序遍历
//正序
void perorder(RTreeNode* p)
{
if (p != NULL)
{
perorder(p->lchild);
perorder(p->rchild);
printf("->%c", p->data);
}//先序遍历
}
//逆序
void sperorder(RStack* S, RTreeNode* p)
{
if (p != NULL)
{
sperorder(S, p->lchild);
sperorder(S, p->rchild);
push(S, p->data);//进栈
}
}//树的遍历都需要进行递归,而结束递归的条件就是p指向空时候
//打印逆序的结果
void treeout(RStack p)
{
while (!empty(&p))
{
printf("->%c", pop(&p));
}
}
代码实现
//后续遍历的正序和逆序为例子
//
// Created by xhh on 2021/6/30.
//
#include<stdio.h>
#include<stdlib.h>
#include<process.h>
#include<string>
#define MAX 50
typedef struct TreeNode
{
struct TreeNode* lchild, * rchild; //左右子树指针
char data; //结点内的元素
}RTreeNode;
//初始化一个树
RTreeNode* initnode(char x, RTreeNode* lchild, RTreeNode* rchild)
{
RTreeNode* SS;
SS = (struct TreeNode*)malloc(sizeof(struct TreeNode));
SS->data = x;
SS->lchild = lchild;
SS->rchild = rchild;
return SS;
}
//定义一个栈
typedef struct Stack
{
int top; //整形变量便于加减,移动方便
char sa[MAX]; //栈的最大空间
}RStack;
//初始化一个栈
RStack init()
{
RStack* SS;
SS = (struct Stack*)malloc(sizeof(struct Stack)); //动态分配内存空间
SS->top = 0;
return *SS;
}
//进栈
void push(RStack *S, char x)
{
if (S->top == MAX)
{
printf("the stack is full");
exit(0);
}
S->sa[S->top] = x; //top指向空栈,所以之间进入它指向的位置
S->top++;
}
//出栈
char pop(RStack* S)
{
if (S->top == 0) //是否为空栈
{
printf("栈空了");
exit(0);
}
return S->sa[--S->top];
}
//判断栈空
int empty(RStack* S)
{
if (S->top == 0)
{
return 1;
}
return 0;
}
//清空栈元素
void clear(RStack* S)
{
S->top = 0;
}
//生成一棵树
RTreeNode* inittree()
{
RTreeNode* root, * b, * c, * d, * e, * f;
d = initnode('D', NULL, NULL);
e = initnode('E', NULL, NULL);
f = initnode('F', NULL, NULL);
b = initnode('B', d, NULL);
c = initnode('C', e, f);
root = initnode('A', b, c); //只有唯一的跟结点,且放在最后
return(root);
}
//正序
void perorder(RTreeNode* p)
{
if (p != NULL)
{
perorder(p->lchild);
perorder(p->rchild);
printf("->%c", p->data);
}//先序遍历
}
//逆序
void sperorder(RStack* S, RTreeNode* p)
{
if (p != NULL)
{
sperorder(S, p->lchild);
sperorder(S, p->rchild);
push(S, p->data);//进栈
}
}//树的遍历都需要进行递归,而结束递归的条件就是p指向空时候
void treeout(RStack p)
{
while (!empty(&p))
{
printf("->%c", pop(&p));
}
}
int main()
{
RTreeNode* tree;
tree = inittree(); //生成一颗树
RStack SS;
SS = init(); //生成了一个栈
perorder(tree);
printf("\n");
sperorder(&SS, tree);
treeout(SS);
return 0;
}
后续遍历结果为:
正序:
->D->B->E->F->C->A
逆序:
->A->C->F->E->B->D
总结:先序,中序,后序遍历的方式只需要将printf函数和递归遍历换一下即可,逆序也是同样如此。