引言
本篇博客是初阶数据结构树的收尾,将会讲掉基本二叉树链式结构的具体内容和实现,包括二叉树的构建,前序遍历,中序遍历,后序遍历和层序遍历,计算二叉树结点个数,第k层结点个数,二叉树叶子结点个数,以及判断一个二叉树是否为完全二叉树。话不多说,开始我们今天的内容。
二叉树链式结构
在之前的博客中,已经讲到了关于链式二叉树相关定义的内容。
这里我们可以来看一看关于二叉树结点的定义:
typedef char BTDataType;//定义存储数据类型
typedef struct BinaryTreeNode
{
BTDataType _data; //存储数据
struct BinaryTreeNode* _left; //指向左孩子(左子树)
struct BinaryTreeNode* _right; //指向右孩子(右子树)
}BTNode;
二叉树:
1. 空树
2. 非空树:由根结点,根节点的左子树,根节点的右子树组成。
从概念上可以看出,二叉树是递归定义的,后面对二叉树的构建和遍历操作都是围绕递归的思路展开。
二叉树的遍历方式及实现
学习二叉树,首先就需要学会其遍历方式,所谓二叉树遍历(Traversal)是按照某种特定的规则,依次对二叉树中的节点进行相应的操作,并且每个节点只操作一次。访问结点所做的操作依赖于具体的应用问题。 遍历是二叉树上最重要的运算之一,也是二叉树上进行其它运算的基础。
按照不同的遍历规则,二叉树的遍历方式有四种:前序遍历,中序遍历,后序遍历和层序遍历
- 前序遍历(Preorder Traversal 亦称先序遍历)访问根结点的操作发生在遍历其左右子树之前。
- 中序遍历(Inorder Traversal)访问根结点的操作发生在遍历其左右子树之中(间)。
- 后序遍历(Postorder Traversal)访问根结点的操作发生在遍历其左右子树之后。
这三种遍历方式大同小异,层序遍历放到后面单独再讲。
下面仔细讲下前序遍历,弄懂前序遍历,中序和后序也就没什么难度了。
1.前序遍历
前序遍历:访问根结点的操作发生在遍历其左右子树之前。
前序遍历图解:
对于上面这棵二叉树:
前序遍历结果:1 2 3 N N N 4 5 N N 6 N N
中序遍历结果:N 3 N 2 N 1 N 5 N 4 N 6 N
后序遍历结果:N N 3 N 2 N N 5 N N 6 4 1
层序遍历结果:1 2 4 3 N 5 6 N N N N N N
代码实现:
打印结点操作在遍历左右子树之前。
// 二叉树前序遍历
void BinaryTreePrevOrder(BTNode* root)
{
if (root == NULL)return; //遇到NULL结点返回
printf("%c ", root->_data);
BinaryTreePrevOrder(root->_left); //递归到左子树
BinaryTreePrevOrder(root->_right); //递归到右子树
}