二叉树的理论基础
参考https://programmercarl.com/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html
二叉树的定义
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class TreeNode:
def __init__(self, value):
self.value = value
self.left = None
self.right = None
二叉树的递归遍历
递归要素:
-
确定递归函数的参数和返回值
-
确定终止条件
-
确定单层递归的逻辑
144. 二叉树的前序遍历
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def preorderTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
result = []
def travelsal(root):
# 当前遍历的结点为空 结束本层递归
if root == None:
return
# 前序 中左右
result.append(root.val)
travelsal(root.left)
travelsal(root.right)
travelsal(root)
return result
145.二叉树的后序遍历
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def postorderTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
result = []
def traversal(root):
if root == None:
return
# 后序 左右中
traversal(root.left)
traversal(root.right)
result.append(root.val)
traversal(root)
return result
94.二叉树的中序遍历
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def inorderTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
result = []
def traversal(root):
if root == None:
return
# 中序 左中右
traversal(root.left)
result.append(root.val)
traversal(root.right)
traversal(root)
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.right:
stack.append(node.right)
if node.left:
stack.append(node.left)
return 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 []
res = []
stack = []
cur = root
while cur or stack :
# 先遍历左子树
if cur:
stack.append(cur)
res.append(cur.val)
cur = cur.left
#cur为空 赋新值
else:
cur = stack.pop()
cur = cur.right
return res
后序遍历
# 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 postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
# 后序是【左右中】, 前序【中左右】
# 先调整左右代码变【中右左】,再反转result数组变左【左右中】
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 result[::-1]
# 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 postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
if not root:
return []
res = []
stack = []
cur = root
while cur or stack :
# 后序是左右中,所以先中右左(可以参考前序),再倒过来
# 先遍历右子树
if cur:
stack.append(cur)
res.append(cur.val)
cur = cur.right
#cur为空 赋新值
else:
cur = stack.pop()
cur = cur.left
return res[::-1]
# 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 postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
if not root:
return []
stack = []
res = []
cur = root
visited = None
while stack or cur:
print("cur",cur)
# 后序 左右中,先遍历到最后一个左结点
if cur:
stack.append(cur)
cur = cur.left
# cur为空,赋值新结点
else:
# 取栈顶元素 如果有右孩子且当前右孩子没有被访问过 就先遍历到右孩子 如果无 就pop自己且打印自己,且标记为访问过
cur = stack[-1]
#设置visited 是因为当前结点不止一次经过,如果当前结点有右孩子,且没被访问过,不然会死循环,一直加入同一个节点的右孩子
if cur.right and cur.right != visited:
cur = cur.right
#右孩子为空
else:
stack.pop()
res.append(cur.val)
visited = cur
cur = None #重置cur 因为pop了 需要重置cur
return res
中序遍历
因为中序遍历是左中右,先访问的是二叉树顶部的节点,然后一层一层向下访问,直到到达树左面的最底部,再开始处理节点(也就是在把节点的数值放进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 = [] # 不能提前将root加入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