二叉树前序、中序以及后序遍历、层序遍厉(了解)

425 阅读4分钟

「这是我参与11月更文挑战的第19天,活动详情查看:2021最后一次更文挑战

💦 二叉树的遍历

学习二叉树结构,最简单的方式就是遍历。所谓二叉树遍历 (Traversal) 是按照某种特定的规则,依次对二叉树中的节点进行相应的操作,并且每个节点只操作一次。
访问结点所做的操作依赖于具体的应用问题。 遍历是二叉树上最重要的运算之一,也是二叉树上进行其它运算的基础。

其实这种就是递归的思想,且在现实生活中也经常使用到 —— 比如 1 位校长要统计学校的人数,他不可能亲自去挨个数,一般是通过院长、系主任、辅导员、班长、舍长的层层反馈才得到结果的 在这里插入图片描述

1️⃣ 前序遍厉: 根   左子树  右子树 在这里插入图片描述

2️⃣ 中序遍厉: 左子树   根  右子树 在这里插入图片描述

3️⃣ 后序遍厉: 左子树  右子树  根 在这里插入图片描述

4️⃣ 层序遍厉: 一层一层的遍 在这里插入图片描述

在之前就提到过深度和广度,其实指的就是这个:

1️⃣ 深度优先遍厉:前序遍厉、中序遍厉、后序遍厉,注意有些说法只认同前序遍厉

2️⃣ 广度优先遍厉:层序遍厉

1、前序、中序以及后序遍历

1️⃣ 前序遍历(Preorder Traversal 亦称先序遍历) —— 访问根结点的操作发生在遍历其左右子树之前。

2️⃣ 中序遍历(Inorder Traversal) —— 访问根结点的操作发生在遍历其左右子树之中(间)。

3️⃣ 后序遍历(Postorder Traversal) —— 访问根结点的操作发生在遍历其左右子树之后。

由于被访问的结点必是某子树的根,所以N(Node)、L(Left subtree)和R(Right subtree)又可解释为根、根的左子树和根的右子树。NLR、LNR和LRN分别又称为先根遍历、中根遍历和后根遍历。
// 二叉树前序遍历
void PreOrder(BTNode* root);
// 二叉树中序遍历
void InOrder(BTNode* root);
// 二叉树后序遍历
void PostOrder(BTNode* root);

❗ 实现 ❕

#include<stdio.h>
#include<stdlib.h>

typedef int BTDataType;
typedef struct BinaryTreeNode
{
	BTDataType _data;
	struct BinaryTreeNode* _left;
	struct BinaryTreeNode* _right; 
}BTNode; 

BTNode* BuyNode(BTDataType x)
{
	BTNode* node = malloc(sizeof(BTNode));
	node->_data = x;
	node->_left = NULL;
	node->_right = NULL;
	
	return node;
}

BTNode* CreatBinaryTree()
{
	BTNode* node1 = BuyNode('A');
	BTNode* node2 = BuyNode('B');
	BTNode* node3 = BuyNode('C');
	BTNode* node4 = BuyNode('D');
	BTNode* node5 = BuyNode('E');
	BTNode* node6 = BuyNode('F');

	node1->_left = node2;
	node1->_right = node3;
	node2->_left = node4;
	node3->_left = node5;
	node3->_right = node6;
	
	return node1; 
 }
//二叉树前序遍历
void PreOrder(BTNode* root)
{
	if(root == NULL)
	{
		printf("NULL ");
		return;
	}
	printf("%c ", root->_data);
	PreOrder(root->_left);
	PreOrder(root->_right);
}
//二叉树中序遍历
void InOrder(BTNode* root)
{
	if(root == NULL)
	{
		printf("NULL ");
		return;
	}
	InOrder(root->_left);
	printf("%c ", root->_data);
	InOrder(root->_right);
}
//二叉树后序遍历
void PostOrder(BTNode* root)
{
	if(root == NULL)
	{
		printf("NULL ");
		return;
	}
	PostOrder(root->_left);
	PostOrder(root->_right);
	printf("%c ", root->_data);
}
//构建二叉树
void TestTree()
{
	BTNode* root = CreatBinaryTree();
	PreOrder(root);
}

int main()
{
	TestTree();
	return 0;
}

📝 分析:

以上真正的核心代码是 PreOrder、InOrder、PostOrder 函数的递归调用短短几行代码却执行了如此复杂的计算,这里豌豆太懒了就只画一个展开图:

❗ PreOrder ❕

在这里插入图片描述

2、层序遍历
除了先序遍历、中序遍历、后序遍历外,还可以对二叉树进行层序遍历。
设二叉树的根节点所在层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层上的节点,接着是第三层的节点,
以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。
// 层序遍历 - 在下文实现
void LevelOrder(BTNode* root);
3、概念选择题 (如何利用已知限有条件构建二叉树)

1.某完全二叉树按层次输出(同一层从左到右)的序列为 ABCDEFGH 。该完全二叉树的前序序列为( )

A. ABDHECFG

B. ABCDEFGH

C. HDBEAFCG

D. HDEBFGCA

📝 分析

在这里插入图片描述

所以选择 A 选项


2.二叉树的先序遍历和中序遍历如下:先序遍历:EFHIGJK; 中序遍历:HFIEJKG; 则二叉树根结点为( )

A. E

B. F

C. G

D. H

📝 分析

根据这棵树的先序遍厉、中序遍厉并不能重建 (其实可以重建的,详情看下题) 这棵树。但是这里并不需要重建,因为先序遍厉是从根开始的。

所以选择 A 选项

--

3.设—课二叉树的中序遍历序列: badce,后序遍历序列: bdeca, 则二叉树前序遍历序列为( )

A. adbce

B. decab

C. debac

D. abcde

📝 分析

这里在没有 # 的情况下,满足以下条件即可构建出二叉树 在这里插入图片描述

在这里插入图片描述

所以选择 D 选项


4.某二叉树的后序遍历序列与中序遍历序列相同,均为 ABCDEF,则按层次输出 (同一层从左到右) 的序列为( )

A. FEDCBA

B. CBAFED

C. DEFCBA

D. ABCDEF

📝 分析

显然这道题作为选择题来说一眼就能知道答案:根据它的后序遍厉知道根是 F

在这里插入图片描述

所以选择 A 选项


❓ 如果知道了前中后序遍历序列,不包括 #(空) ,能否构建一棵二叉树 ❔

     不能构建,但满足以下的条件即可构建: 在这里插入图片描述