二叉树的遍历

二叉树的遍历

前言:二叉树的遍历是进行各种各样的操作的框架, 对其框架进行应用可以完成很多任务。树的遍历类型按DFS(深度优先搜索)分为:先序,中序,后序遍历。树的BFS(广度优先搜索)又可称为层次遍历

BFS:先序,中序,后序。

树的遍历类型依据是遍历根结点的顺序,先序遍历先访问根结点,再访问子树;中序遍历先访问左(右)子树再访问右(左)子树;后序遍历先访问子树再访问根结点。
在这里插入图片描述

需要注意的是,先序,中序,后序的区别非常小,只是操作的位置不一样,详情可以看一下下面的代码

先序遍历

void traverse(BiTree T){
  if(T == NULL) return; //终止条件
  //operations...
  traverse(T->left);
  traverse(T->right);
}

中序遍历

void traverse(BiTree T){
  if(T == NULL) return; //终止条件
  traverse(T->left);
    //operations...
  traverse(T->right);
}

后序遍历

void traverse(BiTree T){
  if(T == NULL) return; //终止条件
  traverse(T->left);
  traverse(T->right);
     //operations...
}

这三个框架可以完成一些基本的操作如:增删改查。他们的递归效率近似于迭代,写起来也很快,因此很多与二叉树相关的问题可以用递归来解决。

//将每个结点的值+1,中序遍历
void traverse(BiTree T){
  if(T == NULL) return;
  traverse(T->left);
  ++ T->val;
  traverse(T->right);
}

//求深度,无非是多利用了返回值
int Depth(BiTree T){
  if(T == NULL) return 0;
  int left = traverse(T->left);
  int right = traverse(T->right);
  return 1 +((left > right)? left: right); 
}

//求叶子结点数
void Leaves(BiTree T, int & cnt){
  if(T == NULL) return;
  if(NULL == T->left && NULL == T->right) ++cnt;
  Leaves(T->left);
  Leaves(T->right);
}

...

在这里插入图片描述

关于三种遍历的实际情况

我们以这棵二叉树为例

先序遍历:

5→1→0→4→8→7→9

中序遍历:

0→1→4→5 →7 →8 →9

后序遍历:

0 →4 → 1 → 7 →9 →8 →5

对于中序遍历,不知道大家有没有注意到,这段序列是升序的,而且这棵二叉树刚好是一棵二叉排序树,也就是说,我们可以通过中序遍历来验证二叉树是否是二叉排序树。当然这是题外话了。

在很多情况下,三种遍历的查找并没有过多的区别。

BFS层次遍历

层次遍历的想法比较朴素,而且一般通过迭代来完成,因此理解起来思路比较简单,相较于递归写法的DFS,BFS好理解一些(不需要人脑压栈模拟DFS的各个函数之间相互调用的情况),但是DFS在很多场合下是比较固定的思路,写多了容易上手,一般情况下DFS能胜任大部分的遍历工作,也有少部分比较难实现,比如说完全二叉树的判定等等。这个时候BFS就能派上用场了。

BFS层次遍历是指一层一层的遍历,以上面的二叉树为例,就是 5→1→8→0→4→7→9
在这里插入图片描述
这种遍历一般用到队列这种数据结构。
其实栈和队列的使用区别不大,主要是要遍历的方向。
我们的思路是通过队列来保存每一层的各个结点,每次访问一层的时候要把上一层的结点弹出,然后把新一层的结点加入其中,这样子就能达到通过循环层次遍历的效果。

talk is cheap, show me your code.

//这里用cpp STL的queue
void LevelOrderTraverse(BiTree T){
	if(!T) return;
	queue <BiTree *> q;
	q.push(T);
	for(; !q.empty(); ){
		int len = q.size();
		for(int i = 0; i < len; ++i)
		{
			BiTree * t = q.front();
			q.pop();
			if(t->left) {q.push(t->left);  
			//operations
			}
			if(t->right) {q.push(t->right);
			//opeartions
			}
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值