一、树的定义
1.定义
树是n(n>=0)个节点的有限集,且这些节点满足如下关系:
(1)有且仅有一个节点没有父节点,该节点称为树的根;
(2)除根外,其余的每个节点都有且仅有一个父节点;
(3)树中的每一个节点都构成一个以它为根的树。
二叉树在满足树的条件时,满足如下条件:每个节点最多有两个孩子(子树),这两个子树有左右之分,次序不可颠倒。
2.树的遍历
二、先序遍历
1.先序遍历
递归
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
def preorderTraversal(self,root):
'''
递归,时间复杂度O(n),空间复杂度平均O(logn),最坏情况下O(n)
:param root:
:return:
'''
if root:
print(root.val)
else:
return
self.preorderTraversal(root.left)
self.preorderTraversal(root.right)
非递归:时间复杂度O(n),空间复杂度O(n)
思路:
1)申请一个新的栈,把头结点压入栈中
2)从栈中弹出栈顶节点,记为node,然后打印node节点的值,再将节点node的由孩子先压入stack中,最后将node的左孩子压入stack中
3)不断重复步骤2,直到栈为空,过程结束
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
def preorderTraversal1(self,root):
'''
:param root:
:return:
'''
if root == None:
return
res = []
stack = [root]
while stack:
node = stack.pop()
print(node.val)
res.append(node.val)
if node.right:
stack.append(node.right)
if node.left:
stack.append(node.left)
return res
2.左叶子之和
leetcode 404
3.判断一棵树是不是平衡树
4.复制二叉树
5.求二叉树的所有叶子节点,并且判断两棵二叉树的叶子节点是否相等
思路1:用先序遍历按左到右顺序遍历所有叶子节点,并返回,然后判断两棵树的叶子序列是否相等。
时间复杂度O(T1+T2) 空间复杂度O(T1+T2)
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def leafSimilar(self, root1: TreeNode, root2: TreeNode) -> bool:
values1,values2=[],[]
self.printleaf(root1,values1)
self.printleaf(root2,values2)
if values1 == values2:
return True
else:
return False
def printleaf(self,root,values):
if root == None:
return
if root.left == None and root.right == None:
values.append(root.val)
self.printleaf(root.left,values)
self.printleaf(root.right,values)
思路2:dfs
class Solution:
def leafSimilar(self, root1, root2):
def dfs(node):
if node:
if not node.left and not node.right:
yield node.val
yield from dfs(node.left)
yield from dfs(node.right)
return list(dfs(root1)) == list(dfs(root2))
三、中序遍历
1.中序遍历
递归:时间复杂度O(n),空间复杂度平均O(logn),最坏情况下O(n)
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
def inorderTraversal(self,root):
'''
:param root:
:return:
'''
if root == None:
return
self.inorderTraversal(root.left)
print(root.val)
self.inorderTraversal(root.right)
非递归:时间复杂度O(n),空间复杂度O(n)
思路:
1)申请一个新的栈,初始时,令变量node=head
2)先把node节点压入栈中,对以node节点为头的整棵子树来说,依次把左边界压入栈中,即不停的令node=node.left,然后重复步骤2
3)不断重复步骤2,直到发现node为空,此时,从栈中弹出一个节点,记为node,打印node的值,并且让node=node.right,然后继续重复步骤2
4)当stack为空且cur为空时,整个过程停止.
class Solution:
def inorderTraversal1(self,root):
'''
:param root:
:return:
'''
if root == None:
return
res = []
stack = []
node = root
while stack or node:
if node:
stack.append(node)
node = node.left
else:
node = stack.pop()
res.append(node.val)
node = node.right
return res
2.判断一棵树是不是二叉搜索树
3.在二叉排序树中找出第一个大于中间值的借贷
4.二叉树转换为双向链表
四、后序遍历
1.后序遍历
递归:时间复杂度O(n),空间复杂度平均O(logn),最坏情况下O(n)
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
def posorderTraversal(self,root):
'''
:param root:
:return:
'''
if root == None:
return
self.posorderTraversal(root.left)
self.posorderTraversal(root.right)
print(root.val)
非递归
a.两个栈:时间复杂度O(n),空间复杂度O(n)
思路:用两个栈实现后序遍历
1)申请一个栈,记为s1,然后将头结点head压入栈Ss1中;
2)从s1中弹出的节点记为cur,然后依次将cur的左孩子和右孩子压入s1中;
3)从整个过程中,每一个从s1中弹出的节点都放进s2中;
4)不断重复步骤2和步骤3,直到s1为空,过程停止;
5)从s2中依次弹出节点并打印,打印的顺序就是后序遍历的顺序.
class Solution:
def posorderTraversal1(self,root):
'''
:param root:
:return:
'''
if not root:
return []
s1,s2 = [root],[]
while s1:
cur = s1.pop()
s2.append(cur.val)
if cur.left:
s1.append(cur.left)
if cur.right:
s1.append(cur.right)
return s2[::-1]
b.一个栈
思路:用一个栈实现后序遍历
申请一个栈,将头结点压入栈中,同时设置变量h和c,h代表最近一次弹出并打印的节点,c代表stack的栈顶节点,初始时h为头结点,c为null
def posorderTraversal2(self,root):
'''
:param root:
:return:
'''
if not root:
return []
res = []
cur = [root]
while cur:
node = cur[-1]
if node.left and node.left != root and node.right != root:
cur.append(node.left)
elif node.right and node.right != root:
cur.append(node.right)
else:
res.append(cur.pop().val)
root = node
return res
2.二叉树的最小深度
leetcode 111
3.判断一个数组是否是二元查找树后序遍历的序列
4.对二叉树进行镜像反转
5.求二叉树的最大子树和
五、层次遍历
1.层次遍历
递归
思路:每次遍历到新层,层数+1,
class Solution:
def levelOrder(self,root,level,result):
'''
递归,按层输出
:param root:
:param level:
:param result:
:return:
'''
if root == None:
return
if level == len(result): # 如果遍历到了新层,就新建一个[]用来存放新层的值
result.append([])
result[level].append(root.val)
if root.left:
self.levelOrder(root.left,level+1,result)
if root.right:
self.levelOrder(root.right,level+1,result)
def levelOrder1(self, root):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
level,result = 0,[]
self.levelOrder(root,level,result)
return result
非递归
思路:用一个队列记录
def levelOrder2(self,root):
'''
思路:队列
用队列存储节点,每次左边出一个节点,如果该节点有左右节点,就将左右节点入队列,直到队列空为止
:param root:
:return:
'''
from collections import deque
if root == None:
return
queue = deque()
queue.append(root)
res = []
while queue:
node = queue.popleft()
res.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
2.二叉树的锯齿形层次遍历 leetcode103
3.二叉树自底向上层次遍历
4.判断一棵树是不是二叉完全树
5.找树左下角的值 leetcode153
思想:层次遍历找最后一层的第一个节点的值
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def findBottomLeftValue(self, root: TreeNode) -> int:
#层次遍历,找最后一层的第一个数
self.res = []
def levelOrder(root,level):
if not root:
return
if len(self.res) == level:#如果层数和res里面的长度相等,说明该层已经遍历完,或者是第一次遍历,就新建一个[],用来放下一层的数据
self.res.append([])
self.res[-1].append(root.val)
if root.left:
levelOrder(root.left,level+1)
if root.right:
levelOrder(root.right,level+1)
if not root:
return
if not root.left and not root.right:
return root.val
levelOrder(root,0)
return self.res[-1][0]
六、给定二叉树前、中序遍历,构造二叉树
分析:
前序遍历序列第一个是根节点x
从中序遍历序列中找到根节点x
中序遍历中x的左边序列对应等长的前序遍历序列【左子树】
中序遍历中的x的右边序列对应等长的前序遍历序列【右子树】
class TreeNode(object):
def __init__(self, x):
self.val = x
self.left = None
self.right = None
def buildTree(preorder,inorder):
if preorder == []:
return None
val = preorder[0]
idx = inorder.index(val)
l_inorder = inorder[0:idx]
r_inorder = inorder[idx+1:]
l_preorder = preorder[1:1+len(l_inorder)]
r_preorder = preorder[1+len(l_inorder):]
root = TreeNode(val)
root.left = buildTree(l_preorder,l_inorder)
root.right = buildTree(r_preorder,r_inorder)
return root
七、给定二叉树中、后序遍历,构造二叉树
class TreeNode(object):
def __init__(self, x):
self.val = x
self.left = None
self.right = None
def buildTree(inorder,postorder):
if postorder == []:
return None
val = postorder[-1]
idx = inorder.index(val)
l_inorder = inorder[0:idx]
r_inorder = inorder[idx+1:]
l_postorder = postorder[:len(l_inorder)]
r_postorder = postorder[len(l_inorder):-1]
root = TreeNode(val)
root.left = buildTree(l_inorder,l_postorder)
root.right = buildTree(r_inorder,r_postorder)
return root
来源:oschina
链接:https://my.oschina.net/u/4401649/blog/3401284