任务5: 9~10天
1.学习目标
1.1 二叉树
实现一个二叉查找树,并且支持插入、删除、查找操作
实现查找二叉查找树中某个节点的后继、前驱节点
实现二叉树前、中、后序以及按层遍历
1.2 堆
实现一个小顶堆、大顶堆、优先级队列
实现堆排序
利用优先级队列合并 K 个有序数组
求一组动态数据集合的最大 Top K
1.3 对应的 LeetCode 练习题
Invert Binary Tree(翻转二叉树)
英文版:Loading…
中文版:力扣
Maximum Depth of Binary Tree(二叉树的最大深度)
英文版:Loading…
中文版:力扣
Validate Binary Search Tree(验证二叉查找树)
英文版:Loading…
中文版:力扣
Path Sum(路径总和)
英文版:Loading…
中文版:力扣
2. 学习内容
2.1 二叉树
定义:
左子树不为空的时候,左子树的节点值小于根结点
右子树不为空的时候,右子树的节点值大于根结点
左右子数据分别为二叉查找树
二叉查找树最左边的节点即为最小值,要查找最小值,仅需遍历左子树的节点值到空为止
二叉查找树的插入/查找/删除操作都是通过递归方式实现的。删除一个节点:
先找到这个节点S,假设节点左右孩子都不为空
在其右子树找到后继(最小)节点,将后继节点的值给S
删除该后继节点
实现一个二叉查找树,并且支持插入、删除、查找操作
实现查找二叉查找树中某个节点的后继、前驱节点
实现二叉树前、中、后序以及按层遍历
class Node:
def __init__(self, data):
self.data = data
self.lchild = None
self.rchild = None
class BST:
def __init__(self, node_list):
self.root = Node(node_list[0])
for data in node_list[1:]:
self.insert(data)
def search(self, node, parent, data): # 搜索
if node is None:
return False, node, parent
if node.data == data:
return True, node, parent
if node.data > data:
return self.search(node.lchild, node, data)
else:
return self.search(node.rchild, node, data)
def insert(self, data): # 插入
flag, n, p = self.search(self.root, self.root, data)
if not flag:
new_node = Node(data)
if data > p.data:
p.rchild = new_node
else:
p.lchild = new_node
def delete(self, root, data): # 删除
flag, n, p = self.search(root, root, data) # n待删除节点,p节点n的父节点
if flag is False:
print("无该关键字,删除失败")
else:
if n.lchild is None: # n的左子树为空(仅存在右子树)
if n == p.lchild: # n为p的左孩子
p.lchild = n.rchild
else: # n为p的右孩子
p.rchild = n.rchild
del n
elif n.rchild is None: # 右子树为空
if n == p.lchild:
p.lchild = n.lchild
else:
p.rchild = n.lchild
del n
else: # n的左右子树均不为空,将右子树的最小数据代替此节点的数据
pre = n.rchild
if pre.lchild is None: # 左子树,则该节点为最小节点
n.data = pre.data
n.rchild = pre.rchild
del pre
else:
next = pre.lchild
while next.lchild is not None:
pre = next
next = next.lchild
n.data = next.data
pre.lchild = next.rchild
del next
def preOrderTraverse(self, node): # 先序遍历
if node is not None:
print(node.data)
self.preOrderTraverse(node.lchild)
self.preOrderTraverse(node.rchild)
def inOrderTraverse(self, node): # 中序遍历
if node is not None:
self.inOrderTraverse(node.lchild)
print(node.data)
self.inOrderTraverse(node.rchild)
def postOrderTraverse(self, node): # 后序遍历
if node is not None:
self.postOrderTraverse(node.lchild)
self.postOrderTraverse(node.rchild)
print(node.data)
层次遍历
将二叉树的节点加入队列,出队的同时,将其非空左右孩子依次入队
出队至队列为空则完成遍历
def PrintFromTopToBottom(self, root):
outList=[]
queue=[root]
while queue!=[] and root:
outList.append(queue[0].val)
if queue[0].left!=None:
queue.append(queue[0].left)
if queue[0].right!=None:
queue.append(queue[0].right)
queue.pop(0)
return outList
def printFromTopToBottom(self, root):
if not root:
return[]
currentStack = [root]
outList = []
while currentStack:
nextStack = []
for point in currentStack:
if point.lchild:
nextStack.append(point.lchild)
if point.rchild:
nextStack.append(point.rchild)
outList.append(point.data)
currentStack = nextStack
return outList
2.2 堆
堆树的定义
完全二叉树
堆树中某个节点的值总是不大于或者不小于其孩子节点的值
堆树中的每个节点的子树都是堆树
实现一个小顶堆、大顶堆、优先级队列
实现堆排序
def heap_sort(lists):
# 堆排序(交换堆顶元素和末尾元素,逐步得到最终结果)
size = len(lists)
build_heap(lists, size)
for i in range(0, size)[::-1]:
lists[0], lists[i] = lists[i], lists[0]
adjust_heap(lists, 0, i)
return lists
def adjust_heap(lists, i, size):
# 调整堆(根结点 < 孩子结点,和最大的孩子结点交换位置)
lchild = 2 * i + 1
rchild = 2 * i + 2
maxi = i
if lchild < size and lists[maxi] < lists[lchild]:
maxi = lchild
if rchild < size and lists[maxi] < lists[rchild]:
maxi = rchild
if maxi != i:
# 如果做了堆调整则maxi的值等于左节点或者右节点的,这个时候做对调值操作
lists[maxi], lists[i] = lists[i], lists[maxi]
adjust_heap(lists, maxi, size)
def build_heap(lists, size):
# 堆的构建
for i in range(int(size / 2), 0, -1):
adjust_heap(lists, i, size)
利用优先级队列合并 K 个有序数组
求一组动态数据集合的最大 Top K
2.3 对应的 LeetCode 练习题
翻转二叉树
class Solution:
def invertTree(self, root):
if not root:
return root
self.invertTree(root.left)
self.invertTree(root.right)
root.left, root.right = root.right, root.left
return root
二叉树的最大深度
class Solution(object):
def maxDepth(self, root):
depth = 0
level = [root] if root else []
while level:
depth += 1
queue = []
for el in level:
if el.left:
queue.append(el.left)
if el.right:
queue.append(el.right)
level = queue
return depth
验证二叉查找树
class Solution:
def isValidBST(self, root, left=None, right=None):
if not root:
return True
if left and left.val >= root.val:
return False
if right and right.val <= root.val:
return False
return self._isValidBST(root.left, left, root) and self._isValidBST(root.right, root, right)
路径总和
class Solution:
def hasPathSum(self, root, sum):
"""
:type root: TreeNode
:type sum: int
:rtype: bool
"""
if root is None:
return False
if sum == root.val and root.left is None and root.right is None:
return True
return self.hasPathSum(root.left, sum-root.val) or self.hasPathSum(root.right, sum-root.val)