二叉树或是树的遍历在各种面试和考试中都十分常见,本文主要是关于树的各种遍历算法.点赞过50更新算法动画,如果还有需要的遍算法可以留言哦
(1)二叉树的前中后遍历
以中序遍历为例,中序遍历的遍历顺序为:左、根、右,即以当前节点为例,先遍历左子节点,再是当前节点,再是右子节点。对于下图来说,**中序遍历的结果为:4,2,5,1,3.**伪代码如下:
def midorder(root):#中序遍历
if root.left:#有左子节点
midorder(root.left)
op(root)#对当前节点操作
if root.right:#有右子节点
midorder(root.right)
当代码执行到1节点,也就是根节点时,先遍历以1节点的左子节点,即2节点。以递归的方式来说,那就会递归到2节点,即先执行midorder(root.left)
,第二个递归函数进入调用栈,对以2节点为根节点的子树,先递归到4节点,即先执行midorder(root.left)
,第三个递归函数进入调用栈,而4节点没有子节点,因此对当前节点也就是4节点进行op,打印4节点的信息,第三个递归函数执行完成,退栈。返回第二个递归函数,执行过midorder(root.left)
后,继续执行op,打印2节点的信息,然后再判断是否有右子节点,并再次递归调用,将函数压入栈。故中序遍历代码:
def inorderTraversal(self, root):
result = []
def fun(node):
if node.left:
fun(node.left)
result.append(node.val)
if node.right:
fun(node.right)
if root:
fun(root)
return result
而先序遍历,后序遍历的写法就是把对当前节点的访问顺序放到最前面和最后面。
对于三种遍历,也可以用迭代的方式写代码。因为递归的本质就是函数调用入栈的过程,如果我们自己建立栈来模拟系统栈,就可以不使用递归来实现。
(2)二叉树的深度(深度优先遍历):
其实前中后序三种遍历也是深度优先遍历。如果要求树的深度,也可以用深度优先遍历的思路。因此下面的深度优先遍历代码可以说是更普遍的、通用的DFS遍历。所谓DFS,就是一条路走到黑,不碰南墙不回头。例如一直遍历左子节点,直到没有左子节点为止。
对上面的例题,代码如下:left和right的值是向左和向右遍历得到的深度值。如果遇到节点不存在的情况,返回值为0,代表深度为0,否则就返回的是左子树和右子树中深度的最大值。
class Solution(object):
def calculateDepth(self, root):
if not root:
return 0
left = self.calculateDepth(root.left)
right = self.calculateDepth(root.right)
return max(left,right) + 1
或者写成这样:
class Solution(object):
def maxDepth(self, root):
def dfs(node):
if not node:
return 0
L = dfs(node.left)
R = dfs(node.right)
return max(L,R)+1
return dfs(root)
(3)二叉树的层序遍历
层序遍历是利用队列,对于python可以使用deque数据结构,也可以不使用。但本质上都是模拟队列的操作。先将根节点入队,再对队列进行循环操作:如果队列未空,则将队头元素弹出,对队头元素操作,并将其子节点放入对内。层序遍历代码如下:
#注意!下面代码是二叉树!
def solution(root):
if not root:
return [] # 如果树为空,返回空数组
res = [] # 初始化结果数组
queue = deque([root]) # 初始化队列,首先包含根节点
while queue:
current = queue.popleft() # 从队列中取出第一个节点
res.append(current.value) # 将当前节点的值追加到结果数组
# 将当前节点的左子节点添加到队列中
if node.left:
queue.append(node.left)
# 如果当前节点有右子节点,将其加入队列
if node.right:
queue.append(node.right)
return res # 返回结果数组
对于上图进行层序遍历,先将1节点入队,入队列后进入循环迭代操作:当队列未空就一直循环。1节点出队,为current,并将其增添进res,1节点有左右节点,则2、3节点进入队列等待下一次循环。对2节点进行操作,2节点出队,添加进入res,并将其子节点即4、5节点入队列,等待之后的操作。2节点处理结束后,当前队列剩余节点为3、4、5节点,3节点出队但没有子节点,故只用添加进res即可。4、5处理方式同3,循环结束,得到res为1、2、3、4、5.
#注意!下面代码不是二叉树,而是树!
def solution(root):
if not root:
return [] # 如果树为空,返回空数组
res = [] # 初始化结果数组
queue = deque([root]) # 初始化队列,首先包含根节点
while queue:
current = queue.popleft() # 从队列中取出第一个节点
res.append(current.value) # 将当前节点的值追加到结果数组
# 将当前节点的所有子节点添加到队列中
for child in current.childNodes:
queue.append(child)
return res # 返回结果数组
上述代码是对于树进行的层序遍历,因此一个节点的子节点个数可以大于2。