二叉树的遍历(先序、中序、后序和层次遍历)

最近发现一个不错的项目,Github上数据结构所有算法源码实现:《数据结构》-严蔚敏.吴伟民-教材源码与习题解析

1.采用二叉链表结构实现二叉树

并以递归遍历思想实现二叉树的创建、二叉树的遍历(先序、中序、后序和层次遍历)、二叉树叶子节点统计、二叉树深度统计的算法;同时,结合课件和实例代码,实现二叉树的中序非递归遍历算法。存储结构和操作接口定义如下:

/*①二叉树的二叉链表存储结构定义*/

typedef struct BiTNode
{
	ElemType data;
	struct BiTNode *lchild, *rchild;      //左右孩子指针
}BiTNode, *BiTree;

/*栈的顺序存储结构定义*/
typedef BiTree SElemType;
typedef struct
{
	SElemType  *base;
	SElemType  *top;
	int  stacksize;
}SqStack;

/*②二叉树操作接口定义*/

//1-创建二叉树
/*初始化操作, 建立一个二叉数 */
void InitTree(BiTree* T);
/*若二叉树存在, 插入值e */
void InsertTree(BiTree* T, char e);
/*判断二叉树是否为空, 空返回true, 否则false */
bool TreeEmpty(BiTree T);
//2-先序遍历二叉树(递归算法)
//先序遍历二叉树T的递归算法
void PreOrderTraverse(BiTree T);
//3-中序遍历二叉树(递归算法)
//中序遍历二叉树T的递归算法
void InOrderTraverse(BiTree T);
//4-后序遍历二叉树(递归算法)
//后序遍历二叉树T的递归算法
void PostOrderTraverse(BiTree T);
//5-中序遍历二叉树(非递归算法)
//中序遍历二叉树T的递归算法,对每个数据元素调用函数Visit,非递归算法,
//采用栈作为辅助结构,注意栈中存储的数据类型是指向树结点的指针
Status InOrderTraverse1(BiTree T, Status(*Visit)(ElemType));
//6-层次遍历二叉树
//层次遍历二叉树T的递归算法,对每个数据元素调用函数Visit,采用队列作为辅助结构
Status LevelOrderTraverse(BiTree T, Status(*Visit)(ElemType));
//7-统计树的叶子结点个数
int CountLeafs(BiTree T);
//8-统计树的层次数
int CountLevels(BiTree T);
//打印元素
Status PrintElement(BiTree T);
//构造一个空栈
Status InitStack(SqStack &S);
//进栈
Status Push(SqStack &S, SElemType e);
//退栈
Status Pop(SqStack &S, SElemType &e);
//判断栈是否为空
Status StackEmpty(SqStack S);

2.测试例子

测试二叉树为:

 其叶子结点:4;深度:4

先序:ABDHEICFG

中序:HDBIEAFCG

后序:HDIEBFGCA

层次:ABCDEFGHI

验证结果(完整代码在下一节):

 结果完全一致!!!!!

推荐理解二叉树遍历的视频:

三分钟无脑学会二叉树遍历手工算法_哔哩哔哩_bilibili

无脑秒解!已知先/后序遍历与中序遍历,求后/先序遍历。_哔哩哔哩_bilibili

3.完整代码(复制就能运行):

#include "stdafx.h"
#include<stdlib.h>
#include<stdio.h>
#define TRUE   1
#define FALSE  0
#define OK 1
#define ERROR 0
#define OVERFLOW -1
typedef  int Status;
typedef  char ElemType;
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
/*①二叉树的二叉链表存储结构定义*/
typedef struct BiTNode
{
	ElemType data;
	struct BiTNode *lchild, *rchild;      //左右孩子指针
}BiTNode, *BiTree;

/*栈的顺序存储结构定义*/
typedef BiTree SElemType;
typedef struct
{
	SElemType  *base;
	SElemType  *top;
	int  stacksize;
}SqStack;

//1-创建二叉树
/*初始化操作, 建立一个二叉数 */
void InitTree(BiTree* T);
/*若二叉树存在, 插入值e */
void InsertTree(BiTree* T, char e);
/*判断二叉树是否为空, 空返回true, 否则false */
bool TreeEmpty(BiTree T);
//2-先序遍历二叉树(递归算法)
//先序遍历二叉树T的递归算法
void PreOrderTraverse(BiTree T);
//3-中序遍历二叉树(递归算法)
//中序遍历二叉树T的递归算法
void InOrderTraverse(BiTree T);
//4-后序遍历二叉树(递归算法)
//后序遍历二叉树T的递归算法
void PostOrderTraverse(BiTree T);
//5-中序遍历二叉树(非递归算法)
//中序遍历二叉树T的递归算法,对每个数据元素调用函数Visit,非递归算法,
//采用栈作为辅助结构,注意栈中存储的数据类型是指向树结点的指针
Status InOrderTraverse1(BiTree T, Status(*Visit)(ElemType));
//6-层次遍历二叉树
//层次遍历二叉树T的递归算法,对每个数据元素调用函数Visit,采用队列作为辅助结构
Status LevelOrderTraverse(BiTree T, Status(*Visit)(ElemType));
//7-统计树的叶子结点个数
int CountLeafs(BiTree T);
//8-统计树的层次数
int CountLevels(BiTree T);
//打印元素
Status PrintElement(BiTree T);
//构造一个空栈
Status InitStack(SqStack &S);
//进栈
Status Push(SqStack &S, SElemType e);
//退栈
Status Pop(SqStack &S, SElemType &e);
//判断栈是否为空
Status StackEmpty(SqStack S);

#pragma region 1.创建二叉树
//1-创建二叉树
/*初始化操作, 建立一个二叉数 */
void InitTree(BiTree* T)
{
	*T = NULL;
}

BiTree FindElem(BiTree T, char e)
{
	if (T->data == e)
		return T;

	if (T->data < e)
	{
		if (T->rchild == NULL)
			return T;
		return FindElem(T->rchild, e);
	}

	if (T->data > e)
	{
		if (T->lchild == NULL)
			return T;
		return FindElem(T->lchild, e);
	}

	return NULL;
}

//创建结点
BiTree CreateNode(char value)
{
	BiTree new_node = (BiTNode *)calloc(1, sizeof(BiTNode));
	new_node->data = value;
	new_node->lchild = NULL;
	new_node->rchild = NULL;
	return new_node;
}

/*若二叉树不存在, 创建二叉树并把e赋给根结点,否则平衡插入值e */
void InsertTree(BiTree* T, char e)
{
	BiTree o = (BiTNode *)calloc(1, sizeof(BiTNode));
	o->data = e;

	if (*T == NULL)
	{
		*T = o;
		return;
	}

	BiTree root = FindElem(*T, e);
	if (root == NULL)
		return;

	if (root->data < e)
	{
		root->rchild = o;
	}
	else if (root->data > e)
	{
		root->lchild = o;
	}
	else
	{
		printf("结点已经存在了\n", e);
		free(o);
		o = NULL;
		return;
	}
}

// 按先序次序输入二叉树中结点的值(一个字符),空格字符表示空树,
// 构造二叉链表表示的二叉树T。
Status CreateBiTree(BiTree &T)
{
	ElemType ch;
	ch = getchar();
	if (ch == ' ') T = NULL;
	else
	{

		if (!(T = (BiTNode *)malloc(sizeof(BiTNode))))  exit(OVERFLOW);
		T->data = ch;              // 生成根结点
		CreateBiTree(T->lchild);      // 构造左子树
		CreateBiTree(T->rchild);      // 构造右子树
	}
	return OK;
} // CreateBiTree


  //打印元素
Status PrintElement(ElemType e)
{
	printf("%c ", e);
	return OK;
}
#pragma endregion

#pragma region 2 先序遍历二叉树(递归算法)
//2-先序遍历二叉树(递归算法)
/* 初始条件: 二叉树T存在 */
/* 操作结果: 前序递归遍历T */
void PreOrderTraverse(BiTree T)
{
	if (!T) return;
	printf("%c ", T->data);
	PreOrderTraverse(T->lchild);
	PreOrderTraverse(T->rchild);
}//PreOrderTraverse
#pragma endregion

#pragma region 3 中序遍历二叉树(递归算法)
 //3-中序遍历二叉树(递归算法)
 /* 初始条件: 二叉树T存在 */
 /* 操作结果: 中序递归遍历T */
void InOrderTraverse(BiTree T)
{
	if (!T) return;
	InOrderTraverse(T->lchild);
	printf("%c ", T->data);
	InOrderTraverse(T->rchild);
}//InOrderTraverse
#pragma endregion

#pragma region 4 后序遍历二叉树(递归算法)
 //4-后序遍历二叉树(递归算法)
 /* 初始条件: 二叉树T存在 */
 /* 操作结果: 后序递归遍历T */
void PostOrderTraverse(BiTree T)
{
	if (!T) return;
	PostOrderTraverse(T->lchild);
	PostOrderTraverse(T->rchild);
	printf("%c ", T->data);
}//PostOrderTraverse
#pragma endregion

#pragma region 5 中序遍历二叉树(非递归算法)
 //构造一个空栈
Status InitStack(SqStack &S)
{
	S.base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));
	if (!S.base) {
		printf("栈溢出!\n");
		exit(OVERFLOW);
	}
	S.top = S.base;
	S.stacksize = STACK_INIT_SIZE;
	return OK;
}

//进栈
Status Push(SqStack &S, SElemType e)
{
	if (S.top - S.base >= S.stacksize)
	{
		S.base = (SElemType *)realloc(S.base, (S.stacksize + STACKINCREMENT) * sizeof(SElemType));
		if (!S.base)
		{
			printf("栈溢出!\n");
			return OVERFLOW;
		}
		S.top = S.base + S.stacksize;
		S.stacksize += STACKINCREMENT;
	}//若栈满,追加存储空间
	*S.top++ = e;
	return OK;
}

//出栈
Status Pop(SqStack &S, SElemType &e)
{
	if (StackEmpty(S))
		return ERROR; //判空
	e = *(--S.top);
	return OK;
}

//判断栈是否为空
Status StackEmpty(SqStack S)
{
	if (S.top == S.base)
		return TRUE;
	else
		return FALSE;
}



//5-中序遍历二叉树(非递归算法)
//中序遍历二叉树T的非递归算法,对每个数据元素调用函数Visit,
//采用栈作为辅助结构,注意栈中存储的数据类型是指向树结点的指针
Status InOrderTraverse1(BiTree T, Status(*Visit)(ElemType))
{
	SqStack S;
	BiTree p;
	p = T;
	InitStack(S);
	while (p || !StackEmpty(S))
	{
		if (p) { Push(S, p);  p = p->lchild; }  // 非空指针进栈,继续左进
		else {       // 上层指针退栈,访问其所指结点,再向右进
			Pop(S, p);
			if (!Visit(p->data))
				return ERROR;
			p = p->rchild;
		}
	}
	return OK;
} // InOrderTraverse
#pragma endregion

#pragma region 6 层次遍历二叉树
  //6-层次遍历二叉树
  //层次遍历二叉树T的递归算法,对每个数据元素调用函数Visit,采用队列作为辅助结构
Status LevelOrderTraverse(BiTree T, Status(*Visit)(ElemType))
{
	BiTNode  *Queue[100], *p = T;
	int  front = 0, rear = 0;
	if (p != NULL)
	{
		Queue[++rear] = p;    /*   根结点入队  */
		while (front<rear)
		{
			p = Queue[++front];  Visit(p->data);
			if (p->lchild != NULL)
				Queue[++rear] = p->lchild;    /*   左结点入队  */
			if (p->rchild != NULL)
				Queue[++rear] = p->rchild;    /*   左结点入队  */
		}
		return OK;
	}
	return ERROR;
}
#pragma endregion

#pragma region 7 统计树的叶子结点个数
//7-统计树的叶子结点个数
/*若二叉树存在, 输出其结点个数 */
int CountLeafs(BiTree root)
{
	if (root == NULL)
	{
		return 0;
	}
	if (root->lchild == NULL&&root->rchild == NULL)
	{
		return 1;
	}
	return CountLeafs(root->lchild) + CountLeafs(root->rchild);
}
#pragma endregion

#pragma region 8 统计树的层次数
//8-统计树的层次数
/* 初始条件: 二叉树T存在。操作结果: 返回T的深度 */
int CountLevels(BiTree T)
{
	if (T == NULL)
		return 0;
	int l = 0, r = 0;
	if (T->lchild)
		l = CountLevels(T->lchild);
	if (T->rchild)
		r = CountLevels(T->rchild);

	return l > r ? l + 1 : r + 1;
}
#pragma endregion

void main()
{
	BiTree T;
	int n = 0;
	/*创建二叉树 start*/
	InitTree(&T);
	BiTree a = CreateNode('a');
	BiTree b = CreateNode('b');
	BiTree c = CreateNode('c');
	BiTree d = CreateNode('d');
	BiTree e = CreateNode('e');
	BiTree f = CreateNode('f');
	BiTree g = CreateNode('g');
	BiTree h = CreateNode('h');
	BiTree i = CreateNode('i');
	T = a;//根结点a
	a->lchild = b;//a结点左子树b
	a->rchild = c;//a结点右子树c
	b->lchild = d;//b结点左子树d
	b->rchild = e;//b结点右子树e
	c->lchild = f;//c结点左子树f
	c->rchild = g;//c结点右子树g
	d->lchild = h;//d结点左子树h
	e->lchild = i;//e结点左子树i
	/*创建二叉树 end*/
	
	n = CountLeafs(T);
	printf("树的叶子结点个数为:%d", n);
	printf("\n树的层次数为:%d\n", CountLevels(T));
	printf("先序遍历二叉树(递归算法):");
	PreOrderTraverse(T);
	printf("\n中序遍历二叉树(递归算法):");
	InOrderTraverse(T);
	printf("\n后序遍历二叉树(递归算法):");
	PostOrderTraverse(T);
	printf("\n中序遍历二叉树(非递归算法):");
	InOrderTraverse1(T, PrintElement);
	printf("\n层次遍历二叉树(递归算法):");
	LevelOrderTraverse(T, PrintElement);
	printf("\n");
}
  • 49
    点赞
  • 298
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 29
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 29
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

DXnima

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

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

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

打赏作者

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

抵扣说明:

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

余额充值