二叉树的遍历是指按照某种顺序依次访问树中的所有节点一次。
四种遍历方式分别是:先序遍历、中序遍历、后序遍历、层序遍历。其中前三种属于深度优先遍历(DFS),后一种属于广度优先遍历(BFS)。
首先声明节点类:
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self,right = None
二叉树的先序遍历:
若二叉树为空树,则空操作;否则,(1)访问根结点;(2)先序遍历左子树;(3)先序遍历右子树。
递归实现:
def preOrder(self, root):
if not root:
return
# 先访问根节点
print(root.val)
# 递归访问左子树
preorder(root.left)
# 访问右子树
preorder(root.right)
迭代实现:
def pre(self, root):
# 将 root放入栈顶
stack = [root]
while stack:
# 取栈顶元素
s = stack.pop()
if s:
print(s.val)
# 由于栈的先进后出特性 先放入右孩子 再放入左孩子
stack.append(s.right)
stack.append(s.left)
二叉树的中序遍历:
若二叉树为空树,则空操作;否则,(1)中序遍历左子树;(2)访问根结点;(3)中序遍历右子树。
递归实现:
def midOrder(self, root):
if not root:
return
# 先访问左节点 再访问根节点 最后访问右节点
midOrder(root.left)
print(roo.val)
midOrder(root.right)
迭代实现:
# 对于树的遍历 ,基本会用到栈这个数据结构
def inOrder(self,root):
stack = []
while stack or root:
# 当root节点存在,一直往下遍历 直到遍历到叶节点
while root:
stack.append(root)
root = root.left
# 当前节点为None时 出栈一个节点打印出节点的value值
root = satck.pop()
print(root.val)
# 也系欸但的孩子肯定为空 所以就会弹出栈中叶节点的父节点,当左子树完全遍历完就会遍历右子树
root = root.right
二叉树的后序遍历:
若二叉树为空树,则空操作;否则,(1)后序遍历左子树;(2)后序遍历右子树;(3)访问根结点。
递归实现:
def postOrder(self, root):
if not root:
return
postOrder(root.left)
postOrder(root.right)
print(root.val)
迭代实现:
法一:
def post(self, root):
stack = []
while root or stack:
# 下行遍历 一直遍历到叶节点
while root:
# 将根节点放入放入栈中
stack.append(root)
# 能左就左 能右就右
if root.left:
root = root.left
if root.right:
root = root.right
s = stack.pop()
print(s.val)
# 如果当前节点是上一节点的左子节点,则遍历右子节点
if stack and s == stack[-1].left:
root = stack[-1].right
else:
root = None
法二:在先序遍历的基础上稍加改动
# 先序遍历 顺序是 根左右 ,后续遍历是 左右根
# 所以可以将res数组的值反过来输出
def post_2(self, root):
stack = [root]
res = []
while stack:
s = stack.pop()
res.append(s.val)
stack.append(s.left)
satck.append(s.right)
return res[::-1]
二叉树的层次遍历:
从上往下、从左至右依次打印树的节点
写法一:利用队列
def levelOrder(self, root):
# 如果根节点不存在,返回空列表
if not root:
return []
# 结果列表
res = []
# 将根节点放入队列
queue = [root]
while queue:
# 获取当前队列的长度 也就是这一层的节点数
size = len(queue)
tmp = []
# 将队列中的元素拿出来 放到临时list中
# 如果左右子树不为空,放入队列中
for _ in range(size):
# 弹出队列中的节点
r = queue.pop(0)
# 将r的值 存进临时列表中
tmp.append(r.val)
if r.left:
queue.append(r.left)
if r.right:
queue.append(r.right)
res.append(tmp)
return res
写法二:利用collections.deque 双向队列
def levelOrder(self, root):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
# 创建队列
queue = collections.deque()
queue.append(root)
# 结果集
res = []
while queue:
size = len(queue)
level = []
for _ in range(size):
# 弹出左边第一个元素
cur = queue.popleft()
if not cur:
continue
level.append(cur.val)
queue.append(cur.left)
queue.append(cur.right)
if level:
res.append(level)
return res
二叉树的一些基本操作总结:
1.二叉树的最大深度
def maxDepth(self, root):
if not root:
return 0
return max(maxDepth(root.left), maxDepth(root.right)) + 1
2.二叉树的最小深度
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。可以通过递归求左右节点的最小深度的较小值,也可以层序遍历找到第一个叶子节点所在的层数。
递归实现:
def minDepth(self, root):
if not root:
return 0
if not root.left and not root.right:
return 1
if not root.right:
return 1+self.minDepth(root.left)
if not root.left:
return 1+self.minDepth(root.right)
return 1+min(self.minDepth(root.left),self.minDepth(root.right))
迭代实现:
def min_Depth(self, root):
if not root:
return 0
ans , count = [root], 1
# 遍历完所有节点
while ans:
n = len(ans)
# 遍历完某一层的节点
for _ in range(n):
r = ans.pop(0)
if r:
# 算法遍历每一层 发现某一层的某个节点没有子树 返回count
if not r.left and not r.right:
return count
# 如果左孩子存在 加入栈
ans.append(r.left if r.left else [])
ans.append(r.right if r.right else [])
count+=1
return count
未完待续 ,后续还会补充更多知识点。
参考链接: