《算法笔记》读书记录DAY_31

CHAPTER_9  提高篇(3)——数据结构(2)

这节我们讲解二叉树的遍历。二叉树的遍历是指通过一定顺序访问二叉树的所有结点。遍历方法有四种:先序遍历、中序遍历、后序遍历、层序遍历。下面分别介绍这四种遍历。

9.2.1 先序遍历

先序遍历采用递归的方式进行,首先要将树分为三个部分:根节点、左子树、右子树。对于先序遍历来说,总是先访问根节点,然后访问左子树,最后访问右子树。访问左子树和右子树的过程是一个递归的过程,例如访问左子树时,同样要访问它的根节点,然后访问它的左子树,最后访问它的右子树。访问右子树的过程也同样。

对于上图这个例子,先序遍历的过程如下:1 2 4 6 7 3 5 。

为了实现递归的先序遍历,我们需要两样东西:递归式和递归边界。其中递归式已经由定义得到,即按照根节点、左子树、右子树的顺序访问。那么递归的边界是什么呢?从上个例子可以发现,递归边界是二叉树和为一个空树。即访问子树时,发现子树为空,那么可以停止子树的访问而继续后面的访问。

由此可以给出递归的先序遍历代码:

void preorder(node* root) {
	if(root==NULL)             //到达递归边界,回退 
		return;
	cout<<root->data<<endl;    //访问根节点 
	preorder(root->lchild);    //访问左子树 
	preorder(root->rchild);    //访问右子树 
}

9.2.2 中序遍历

中序遍历采用递归的方式进行,它总是先访问左子树,然后访问根节点,最后访问右子树。同样地,访问左子树和右子树的过程是递归进行的。例如访问左子树时,先访问它的左子树,再访问它的根节点,最后访问它的右子树。递归的过程中,若子树为空,则停止子树的访问进行后续的遍历。

对于上图例子,中序遍历的结果为:4 6 7 2 1 5 3 。

中序遍历的递归实现思路与先序遍历相同,只是左子树和根节点的访问顺序交换了,递归代码如下:

void preorder(node* root) {
	if(root==NULL)             //到达递归边界,回退 
		return;
	preorder(root->lchild);    //访问左子树 
	cout<<root->data<<endl;    //访问根节点 
	preorder(root->rchild);    //访问右子树 
}

9.2.3 后序遍历

后序遍历也采用递归的方式进行,它总是先访问左子树,然后访问右子树,最后访问根节点。同样地,访问左子树和右子树的过程是递归进行的。例如访问左子树时,先访问它的左子树,再访问它的右子树,最后访问它的根节点。递归的过程中,若子树为空,则停止子树的访问进行后续的遍历。

同样是上面那张图,后续遍历的结果为:7 6 4 2 5 3 1 。

后序遍历的递归实现和上面两种是大致相同的,唯一的区别只是访问顺序不同,代码如下:

void preorder(node* root) {
	if(root==NULL)             //到达递归边界,回退 
		return;
	preorder(root->lchild);    //访问左子树 
	preorder(root->rchild);    //访问右子树 
	cout<<root->data<<endl;    //访问根节点 
}

9.2.4 层序遍历

可以看到,二叉树的先序、中序、后续的实现思路是相同的。其实这种思想我们在DFS中已经学习,一层一层的递归实际上就是栈的实现。而层序遍历则和BFS有着相同的思想,应用的数据结构为队列。

层序遍历是指按层次的顺序从根节点向下逐层进行遍历,且对同一层进行从左到右的顺序。层序遍历从逻辑上非常直观,例如下面这个例子,层序遍历的结果为:1 2 3 4 5 6 。

这个过程和BFS很像,因为BFS进行搜索总是以广度为第一关键词,对应到二叉树中广度就体现在层次上。因此层次遍历就是二叉树从根节点开始的广度优先搜索,其思路就是BFS的思路:

(1)将根节点入队;

(2)访问队首结点,然后队首出队;

(3)如果该结点有左孩子,则左孩子入队;

(4)如果该节点有右孩子,则右孩子入队;

(5)返回第二步循环,直到队列为空时退出循环。

代码如下:

void Layerorder(node* root) {
	queue<node*> q;
	q.push(root);
	while(!q.empty()) {
		node *now=q.front();     //访问该节点 
		q.pop();
		if(now->lchild) {
			q.push(now->lchild)
		}
		if(now->rchild) {
			q.push(now->rchild)
		}
	}
}

猜你喜欢

转载自blog.csdn.net/jgsecurity/article/details/120820317