二叉树理论
典型二叉树
- 满二叉树:顾名思义
- 完全二叉树:特点是除了底层没填满,其他各层均是满节点的树,且底层节点都聚集在左边位置
- 二叉搜索树:若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;它的左、右子树也分别为二叉排序树
- 平衡二叉搜索树:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是平衡二叉 树
二叉树的遍历方式
- 深度优先遍历(DFS):
- 前序遍历
- 中序遍历
- 后序遍历
- 广度优先遍历(BFS):
- 层序遍历
二叉树的定义
class TreeNode(self,val,left=None,right=None):
self.val=val
self.left=left
self.right=right
二叉树的递归遍历
在写递归的时候,要严格按照三要素来写,确保自己每次写都有一定的逻辑。
- 确定递归函数的参数和返回值
- 确定终止条件
- 确定单层递归的逻辑
前序遍历
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def __init__(self):
self.res=[]
def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
self.traverse(root)
return self.res
def traverse(self,root):
if root==None:
return
self.res.append(root.val)
left=self.traverse(root.left)
right=self.traverse(root.right)
中序遍历
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def __init__(self):
self.res=[]
def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
self.traverse(root)
return self.res
def traverse(self,root):#遍历的函数
if root==None:
return 0
left=self.traverse(root.left)
self.res.append(root.val)
right=self.traverse(root.right)
后序遍历
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def __init__(self):
self.res=[]
def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
self.traverse(root)
return self.res
def traverse(self,root):
if root is None:
return 0
# 后序遍历:左右中
left=self.traverse(root.left)
right=self.traverse(root.right)
self.res.append(root.val)
二叉树的迭代遍历
递归的实现就是:每一次递归调用都会把函数的局部变量、参数值和返回地址等压入调用栈中,然后递归返回的时候,从栈顶弹出上一次递归的各项参数,所以这就是递归为什么可以返回上一层位置的原因。
前序
这里注意要先加入右节点,再加入左节点;因为根据栈的特性,这样先弹出来的是左节点
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
if not root:
return []
stack=[root]
result=[]
while stack:
node=stack.pop()
result.append(node.val)
if node.right:
stack.append(node.right)
if node.left:
stack.append(node.left)
return result
后序
先说一下后序,因为前序和后序的迭代逻辑是一样的,只需要略微修改一下入栈顺序即可.
后序的顺序是左右中,我们只需要将入栈顺序写成中右左,然后反转result即可
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
if not root:
return []
stack=[root]
result=[]
while stack:
node=stack.pop()
result.append(node.val)
if node.left:
stack.append(node.left)
if node.right:
stack.append(node.right)
return list(reversed(result))
中序
中序遍历是左中右,先访问的是二叉树顶部的节点,然后一层一层向下访问,直到到达树左面的最底部,再开始处理节点(也就是在把节点的数值放进result数组中),这就造成了处理顺序和访问顺序是不一致的。
(后面还得回顾)
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
if not root:
return []
stack=[]
result=[]
cur=root
while cur or stack:
if cur:
stack.append(cur)
cur=cur.left
else:
cur=stack.pop()
result.append(cur.val)
cur=cur.right
return result
二叉树层序遍历
199.二叉树的右视图
和基本的层序遍历基本一模一样,主要就是判断每一层最后一个元素
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
from collections import deque
class Solution:
def rightSideView(self, root: Optional[TreeNode]) -> List[int]:
if root is None:
return []
q=deque()
q.append(root)
res=[]
while q:
sz=len(q)
for i in range(sz):
node=q.popleft()
if i==sz-1:
res.append(node.val)
if node.left:
q.append(node.left)
if node.right:
q.append(node.right)
return res
637.二叉树的层平均值
一遍过,爽~
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
from collections import deque
class Solution:
def averageOfLevels(self, root: Optional[TreeNode]) -> List[float]:
if not root:
return []
q=deque()
q.append(root)
res=[]
while q:
sz=len(q)
level=[]
avg=0
cnt=0
for i in range(sz):
cnt+=1
cur=q.popleft()
level.append(cur.val)
if cur.left:
q.append(cur.left)
if cur.right:
q.append(cur.right)
avg=sum(level)/cnt
res.append(avg)
return res
429.N叉树的层序遍历
"""
# Definition for a Node.
class Node:
def __init__(self, val: Optional[int] = None, children: Optional[List['Node']] = None):
self.val = val
self.children = children
"""
from collections import deque
class Solution:
def levelOrder(self, root: 'Node') -> List[List[int]]:
if not root:
return []
q=deque()
q.append(root)
res=[]
while q:
level=[]
sz=len(q)
for i in range(sz):
cur=q.popleft()
level.append(cur.val)
for child in cur.children:
q.append(child)
res.append(level)
return res
116.填充每个节点的下一个右侧节点指针
"""
# Definition for a Node.
class Node:
def __init__(self, val: int = 0, left: 'Node' = None, right: 'Node' = None, next: 'Node' = None):
self.val = val
self.left = left
self.right = right
self.next = next
"""
from collections import deque
class Solution:
def connect(self, root: 'Node') -> 'Node':
if not root:
return root
q=deque()
q.append(root)
while q:
sz=len(q)
prev=None
for i in range(sz):
cur=q.popleft()
if prev:
prev.next=cur
prev=cur
if cur.left:
q.append(cur.left)
if cur.right:
q.append(cur.right)
return root
111.二叉树的最小深度
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
from collections import deque
class Solution:
def minDepth(self, root: Optional[TreeNode]) -> int:
if not root:
return 0
q=deque()
q.append(root)
depth=0
while q:
sz=len(q)
depth+=1
for i in range(sz):
cur=q.popleft()
if not cur.left and not cur.right:
return depth
if cur.left:
q.append(cur.left)
if cur.right:
q.append(cur.right)
return depth