二叉树的概念及三种遍历方法(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 BNULL D FNULL NULL NULLC E NULL NULL NULL

中序遍历:B F D A E C

后序遍历:F D B E C A


三种遍历方法的代码实现

结构体的定义

typedefcharBTDataType;
typedefstructBinaryTreeNode{
structBinaryTreeNode*left;  //左孩子structBinaryTreeNode*right;  //右孩子BTDataTypedata;
}BTNode;

解释:

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

②下面是结构体的定义


前序遍历代码实现

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

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

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

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

中序遍历代码实现

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

后序遍历代码实现

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

所有函数和main函数

#include<stdio.h>#include<stdlib.h>typedefcharBTDataType;
typedefstructBinaryTreeNode{
structBinaryTreeNode*left;  //左孩子structBinaryTreeNode*right;  //右孩子BTDataTypedata;
}BTNode;
voidPrevOrder(BTNode*root)  //前序遍历{
if (root==NULL) //空树return;
printf("%c ", root->data);
PrevOrder(root->left);
PrevOrder(root->right);
}
voidInOrder(BTNode*root) //中序遍历{
if (root==NULL) //空树return;
InOrder(root->left);
printf("%c ", root->data);  
InOrder(root->right);
}
voidPostOrder(BTNode*root) //后序遍历{
if (root==NULL) //空树return;
PostOrder(root->left);
PostOrder(root->right);
printf("%c ", root->data);
}
intmain()
{
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("");
return0;
} 

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

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

目录
相关文章
|
25天前
|
传感器 人工智能 物联网
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发,以及面临的挑战和未来趋势,旨在帮助读者深入了解并掌握这些关键技术。
42 6
|
25天前
|
C语言 开发者
C语言中的模块化编程思想,介绍了模块化编程的概念、实现方式及其优势,强调了合理划分模块、明确接口、保持独立性和内聚性的实践技巧
本文深入探讨了C语言中的模块化编程思想,介绍了模块化编程的概念、实现方式及其优势,强调了合理划分模块、明确接口、保持独立性和内聚性的实践技巧,并通过案例分析展示了其应用,展望了未来的发展趋势,旨在帮助读者提升程序质量和开发效率。
48 5
|
25天前
|
存储 算法 C语言
C语言中常见的字符串处理技巧,包括字符串的定义、初始化、输入输出、长度计算、比较、查找与替换、拼接、截取、转换、遍历及注意事项
本文深入探讨了C语言中常见的字符串处理技巧,包括字符串的定义、初始化、输入输出、长度计算、比较、查找与替换、拼接、截取、转换、遍历及注意事项,并通过案例分析展示了实际应用,旨在帮助读者提高编程效率和代码质量。
70 4
|
1月前
|
C语言
【数据结构】二叉树(c语言)(附源码)
本文介绍了如何使用链式结构实现二叉树的基本功能,包括前序、中序、后序和层序遍历,统计节点个数和树的高度,查找节点,判断是否为完全二叉树,以及销毁二叉树。通过手动创建一棵二叉树,详细讲解了每个功能的实现方法和代码示例,帮助读者深入理解递归和数据结构的应用。
132 8
|
2月前
|
Java 编译器 C语言
【一步一步了解Java系列】:Java中的方法对标C语言中的函数
【一步一步了解Java系列】:Java中的方法对标C语言中的函数
31 3
|
3月前
|
存储 算法 C语言
数据结构基础详解(C语言): 二叉树的遍历_线索二叉树_树的存储结构_树与森林详解
本文从二叉树遍历入手,详细介绍了先序、中序和后序遍历方法,并探讨了如何构建二叉树及线索二叉树的概念。接着,文章讲解了树和森林的存储结构,特别是如何将树与森林转换为二叉树形式,以便利用二叉树的遍历方法。最后,讨论了树和森林的遍历算法,包括先根、后根和层次遍历。通过这些内容,读者可以全面了解二叉树及其相关概念。
|
3月前
|
存储 机器学习/深度学习 C语言
数据结构基础详解(C语言): 树与二叉树的基本类型与存储结构详解
本文介绍了树和二叉树的基本概念及性质。树是由节点组成的层次结构,其中节点的度为其分支数量,树的度为树中最大节点度数。二叉树是一种特殊的树,其节点最多有两个子节点,具有多种性质,如叶子节点数与度为2的节点数之间的关系。此外,还介绍了二叉树的不同形态,包括满二叉树、完全二叉树、二叉排序树和平衡二叉树,并探讨了二叉树的顺序存储和链式存储结构。
|
3月前
|
存储 算法 C语言
C语言手撕实战代码_二叉树_构造二叉树_层序遍历二叉树_二叉树深度的超详细代码实现
这段代码和文本介绍了一系列二叉树相关的问题及其解决方案。其中包括根据前序和中序序列构建二叉树、通过层次遍历序列和中序序列创建二叉树、计算二叉树节点数量、叶子节点数量、度为1的节点数量、二叉树高度、特定节点子树深度、判断两棵树是否相似、将叶子节点链接成双向链表、计算算术表达式的值、判断是否为完全二叉树以及求二叉树的最大宽度等。每道题目均提供了详细的算法思路及相应的C/C++代码实现,帮助读者理解和掌握二叉树的基本操作与应用。
|
3月前
|
存储 C语言
数据结构基础详解(C语言): 树与二叉树的应用_哈夫曼树与哈夫曼曼编码_并查集_二叉排序树_平衡二叉树
本文详细介绍了树与二叉树的应用,涵盖哈夫曼树与哈夫曼编码、并查集以及二叉排序树等内容。首先讲解了哈夫曼树的构造方法及其在数据压缩中的应用;接着介绍了并查集的基本概念、存储结构及优化方法;随后探讨了二叉排序树的定义、查找、插入和删除操作;最后阐述了平衡二叉树的概念及其在保证树平衡状态下的插入和删除操作。通过本文,读者可以全面了解树与二叉树在实际问题中的应用技巧和优化策略。
|
4月前
|
机器学习/深度学习 C语言
【C语言篇】递归详细介绍(基础概念习题及汉诺塔等进阶问题)
要保持最小的步数,每一次汉诺塔问题(无论是最初还是递归过程中的),如果此时初始柱盘子数为偶数,我们第一步是把最上面的盘子移动到中转柱,如果为奇数,我们第一步则是将其移动到目标柱。
104 0
【C语言篇】递归详细介绍(基础概念习题及汉诺塔等进阶问题)