二叉树是数据结构中不仅可以用来存储数据的,同时也可以有很多其他的功能,比如说二叉搜索树,如果中序遍历的话就是排序加去重等,而且查找效率很高,如果是AVL树或者红黑树(二叉树的一种)查找效率为log n,效率特别高,所以二叉树很重要,但是普通的二叉树没有什么用,所以这里不会教你如何push或者pop等,这里只能教你如何编辑等,但是这里很重要的是一种思想(递归),下面会讲清楚的
那么下面先看一下二叉树的节点
OK就是这样,其实这个结构和链表没什么区别,由于是二叉树所以需要两个指针,一个左 一个右
下面我们就先看一下二叉树如何遍历
其中二叉树的遍历方法有很多种,有前中后序遍历,其中这三个都是用递归(用循环也可以,不过这里用递归更简单一点,以后会说到循环的),还有一个是层序遍历,其中这个直接用循环,一会会说到思路的
今天就只看一下遍历等简单的
所以我们先看一下前序遍历
假设我们要遍历这棵树,那么前序遍历怎么遍历呢?
这里首先应该说一下什么是前序遍历,首先遍历就是对这棵树挨个走一遍,不一定要打印,如果这里我们遍历就是打印出来,那么前序遍历就是,我们先打印根节点,在打印左孩子节点,在打印右孩子节点,所以我们来看一下这棵树
这里我们只画了一小部分,和我一起看一下,首先我们的第一个节点是4,那么4是我们的根节点,所以我们直接打印,然后根节点访问完之后我们就要去他的左孩子节点2,然后打印,那么此时2就是我们的根节点,根节点访问完之后我们还是得去他的左孩子节点1然后我们打印1,这时候我们同样把1看作我们的根节点,此时我们需要访问1的左孩子节点,但是1的左孩子节点为空,所以我们直接返回即可,然后此时1这个根节点访问玩了,1的左孩子节点也访问完了,那么就要去1的右孩子节点,同样为空直接返回,然后我们就把1这一整棵树都访问完了,所以我们就已经访问完了2的左子树,2的左子树访问完之后,我们就需要去访问2的右子树,和刚才同样的步骤,此时我们2这棵树也访问完了,所以我们4这棵树的根节点访问完了,同时4的左子树也访问完了,所以我们就需要访问4的右子树,和上面步骤相同,都是(根 左 右)先访问根,在访问左子树,在访问右子树就是这样,那么这棵树前序遍历是怎么样子的,我们先看一下他遍历出来是什么样子
这就是前序遍历出来后的效果,下面我们就来看一下代码怎么实现
我们说了,前中后序遍历是用递归,而这里递归,我们可以看一下,首先我们 可以看一下,我们先把根节点传给该函数,然后他直接去打印根节点,然后再递归调用自己,把左孩子和右孩子分别传给该函数
这里还是可以画一下递归展开图
我们可以看到,我们先把4传进去,然后他不是空所以会调用他自己,然后把他的左孩子传进去
就是这样,虽然这里画的不是很好,但是可以将就看懂,这里就是先把4传进去,然后打印,4又不为空,所以把他的左孩子穿进去,2又不为空,然后打印,又访问2的左孩子,为1然后打印,把传进去,由于1的左为空所以直接返回,此时传入1左孩子的这一个函数已经调用结束了,所以需要把1的右孩子传进去,然后也为空返回,此时前序遍历1这棵树已经访问结束,又返回到上一层,就是这样下去
前序遍历就是这样,下面看一下中序遍历和后序遍历,其实和前序遍历一样,只是访问根节点的时机不同,下面就不详细讲解了
首先这里是中序遍历,中序遍历就是左 根 右,那么先是4这个节点, 首先能不能访问4这个节点?不能因为访问根之前先要访问根的左
所以应该先访问4的左,那么就是2,此时可不可以访问2,还是不可以,因为先要访问2的左就是1,和上面一样能不能访问1,不可以因为先要访问1的左,由于1的左是空,所以我们直接返回就可以,这时候1的左已经访问结束,这时候才可以访问1这个节点
此时已经把1访问了,那么就要访问1的右,由于1的右也为空,所以直接返回,此时1这棵树就访问结束了,所以要访问2了
就是这样,和之前的步骤相同,所以这棵树中序遍历结束后就是这样
下面我们就看代码,这次不画递归展开图了,可以自己去画,按照上面的逻辑
直接看代码
下面就看后序遍历,同时也是访问实际不同,就是先访问左,在访问右,最后访问根,这里也就直接看代码,和前面都是一样的,也可以自己画一下递归展开图,这样思路会更清晰一点
本来准备讲层序遍历和其他几个的,但是现在时间有点不够,所以只能在这里了,剩下的下一节讲 。