写点什么

二叉树的概念及三种遍历方法(C 语言)

作者:孤衫
  • 2022 年 9 月 17 日
    安徽
  • 本文字数:2306 字

    阅读完需:约 8 分钟

二叉树的概念及三种遍历方法(C语言)

二叉树的概念及结构

每个结点最多有两颗子树,即二叉树不存在度大于 2 的结点。

任何一颗二叉树可以看成三个部分:①根节点②左子树③右子树


遍历的三种方法

以下面的二叉树为例介绍遍历的方法。


图片.png



先序遍历(前序)

先序遍历的方法是:“根左右”依次遍历,即先访问根结点,再访问左子树,再访问右子树。

以上面的二叉树为例,肯定要先访问根结点 A,然后访问左子树,但 A 的左子树是以 B 为根结点的一颗子树,如下图。


图片.png

那么在这颗子树里我们又要根据“根左右”进行遍历,先访问根结点 B,然后左子树 D,但在这我想让你思考 D 还有没有子树?看样子是没有,不过严格意义我们可以写上 NULL(空),然后就是 B 的右子树,结点 E。

到此为止 A 的左子树已经访问完了,可以写 A B D NULL NULL E NULL NULL,有时候题目不要求我们写空的话,可以直接写 ABDE(接下来为了方便大家看我就不写 NULL 了)。

然后再访问 A 的右子树 C。


先序遍历完成,顺序为:ABDEC


中序遍历

中序遍历的方法是:“左根右”依次遍历,即先访问左子树,再访问根结点,再访问右子树。


以上面二叉树为例,先看 A 有无左子树,有!是根结点为 B 的子树! 再看 B 有无左子树,有!是结点 D。


D 还有左子树吗?没有,是 NULL(空,我们这里暂且不算)那就先访问 D,然后 D 作为 B 的左子树,接下来就该访问根结点 B。


接着访问 B 的右子树 E,E 有左子树吗?没有。现在我们看到 A 的所有左子树已经遍历完了,接着就是访问根结点 A。


到此为止的顺序为:DBEA


然后再访问 A 的右结点 C。


所以中序遍历的顺序为:DBEAC


可以自己试着把空(NULL)也给算上写出中序遍历:

NULL D NULL B NULL E NULL A NULL C NULL


后序遍历

后序遍历的方法是:“左右根”依次遍历,即先访问左子树,再访问右子树,再访问根结点。


以上面二叉树为例,先看 A 有无左子树,有!是根结点为 B 的子树! 再看 B 有无左子树,有!是结点 D。D 无子树了,再看 B 是否有右子树,有!是结点 E。


好的那就先访问 D 和 E,然后再访问 B,接着就是 A 的右子树。然后 A 的右子树只有一个 C,最后再访问 A,访问完毕。


后序遍历的顺序为:DEBCA


遍历例题

写出下面二叉树的三种遍历结果


图片.png

严格上可以写 NULL,读者可以自己加以理解,大多数情况会忽略 NULL。

前序遍历:A B NULL D F NULL NULL NULL C E NULL NULL NULL

中序遍历:B F D A E C

后序遍历:F D B E C A


三种遍历方法的代码实现

结构体的定义

typedef char BTDataType;typedef struct BinaryTreeNode{    struct BinaryTreeNode* left;  //左孩子    struct BinaryTreeNode* right;  //右孩子    BTDataType data;}BTNode;
复制代码

解释:


①typedef char BTDataType;  是将 char 字符类型重新命名为 BTDataType,目的是为了方便代码的可维护性,比如我后面发现 char 不是我想要的类型了,但我已经打了好几个 char 了,就不方便更改了。而用此方法,只需要把 typedef char BTDataType 里的 char 改成 int 就行。


②下面是结构体的定义



前序遍历代码实现

void PrevOrder(BTNode* root)  //前序遍历{	if (root == NULL) //空树		return; 	printf("%c ", root->data);	PrevOrder(root->left);	PrevOrder(root->right);}
复制代码

这里就是先打印根结点,毕竟这是前序遍历,然后就访问左子树,即 root->left。

如果遍历的时候想严格打印 NULL 那么就这样写.

void PrevOrder(BTNode* root)  //前序遍历{	if (root == NULL) //空树	{		printf("NULL ");		return;	} 	printf("%c ", root->data);	PrevOrder(root->left);	PrevOrder(root->right);}
复制代码



中序遍历代码实现

void InOrder(BTNode* root) //中序遍历{	if (root == NULL) //空树		return; 	InOrder(root->left);	printf("%c ", root->data);		InOrder(root->right);}
复制代码



后序遍历代码实现

void PostOrder(BTNode* root) //后序遍历{	if (root == NULL) //空树		return; 	PostOrder(root->left);	PostOrder(root->right);	printf("%c ", root->data);}
复制代码



所有函数和 main 函数

#include<stdio.h>#include<stdlib.h>typedef char BTDataType;typedef struct BinaryTreeNode{	struct BinaryTreeNode* left;  //左孩子	struct BinaryTreeNode* right;  //右孩子	BTDataType data;}BTNode; void PrevOrder(BTNode* root)  //前序遍历{	if (root == NULL) //空树		return; 	printf("%c ", root->data);	PrevOrder(root->left);	PrevOrder(root->right);} void InOrder(BTNode* root) //中序遍历{	if (root == NULL) //空树		return; 	InOrder(root->left);	printf("%c ", root->data);		InOrder(root->right);} void PostOrder(BTNode* root) //后序遍历{	if (root == NULL) //空树		return; 	PostOrder(root->left);	PostOrder(root->right);	printf("%c ", root->data);}  int main(){	BTNode* A = (BTNode*)malloc(sizeof(BTNode));	A->data = 'A';	A->left = NULL;	A->right = NULL; 	BTNode* B = (BTNode*)malloc(sizeof(BTNode));	B->data = 'B';	B->left = NULL;	B->right = NULL; 	BTNode* C = (BTNode*)malloc(sizeof(BTNode));	C->data = 'C';	C->left = NULL;	C->right = NULL; 	BTNode* D = (BTNode*)malloc(sizeof(BTNode));	D->data = 'D';	D->left = NULL;	D->right = NULL; 	BTNode* E = (BTNode*)malloc(sizeof(BTNode));	E->data = 'E';	E->left = NULL;	E->right = NULL; 	A->left = B;	A->right = C;	B->left = D;	B->right = E; 	PrevOrder(A);	printf("\n"); 	InOrder(A);	printf("\n"); 	PostOrder(A);	printf("\n"); 	printf("");	return 0;} 
复制代码

这里还是以最上面的二叉树为例。

主函数里我使用了动态内存开辟,使用一次就开一次,不要浪费内存。

发布于: 刚刚阅读数: 5
用户头像

孤衫

关注

还未添加个人签名 2022.08.02 加入

还未添加个人简介

评论

发布
暂无评论
二叉树的概念及三种遍历方法(C语言)_后端_孤衫_InfoQ写作社区