Merge branch 'master' into binary_search_tree

This commit is contained in:
Yudong Jin
2023-01-10 13:30:38 +08:00
committed by GitHub
215 changed files with 5618 additions and 1642 deletions

View File

@ -26,9 +26,9 @@ def remove(n0):
""" 访问链表中索引为 index 的结点 """
def access(head, index):
for _ in range(index):
head = head.next
if not head:
return None
head = head.next
return head
""" 在链表中查找值为 target 的首个结点 """

View File

@ -28,11 +28,11 @@ def merge(nums, left, mid, right):
if i > left_end:
nums[k] = tmp[j]
j += 1
# 否则,若“右子数组已全部合并完”或“左子数组元素 < 右子数组元素”,则选取左子数组元素,并且 i++
# 否则,若“右子数组已全部合并完”或“左子数组元素 <= 右子数组元素”,则选取左子数组元素,并且 i++
elif j > right_end or tmp[i] <= tmp[j]:
nums[k] = tmp[i]
i += 1
# 否则,若“左子数组元素 > 右子数组元素”,则选取右子数组元素,并且 j++
# 否则,若“左右子数组都未全部合并完”且“左子数组元素 > 右子数组元素”,则选取右子数组元素,并且 j++
else:
nums[k] = tmp[j]
j += 1

View File

@ -5,30 +5,28 @@ Author: a16su (lpluls001@gmail.com)
"""
import sys, os.path as osp
import typing
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from include import *
class AVLTree:
def __init__(self, root: typing.Optional[TreeNode] = None):
def __init__(self, root: Optional[TreeNode] = None):
self.root = root
""" 获取结点高度 """
def height(self, node: typing.Optional[TreeNode]) -> int:
def height(self, node: Optional[TreeNode]) -> int:
# 空结点高度为 -1 ,叶结点高度为 0
if node is not None:
return node.height
return -1
""" 更新结点高度 """
def __update_height(self, node: TreeNode):
def __update_height(self, node: Optional[TreeNode]):
# 结点高度等于最高子树高度 + 1
node.height = max([self.height(node.left), self.height(node.right)]) + 1
""" 获取平衡因子 """
def balance_factor(self, node: TreeNode) -> int:
def balance_factor(self, node: Optional[TreeNode]) -> int:
# 空结点平衡因子为 0
if node is None:
return 0
@ -36,7 +34,7 @@ class AVLTree:
return self.height(node.left) - self.height(node.right)
""" 右旋操作 """
def __right_rotate(self, node: TreeNode) -> TreeNode:
def __right_rotate(self, node: Optional[TreeNode]) -> TreeNode:
child = node.left
grand_child = child.right
# 以 child 为原点,将 node 向右旋转
@ -49,7 +47,7 @@ class AVLTree:
return child
""" 左旋操作 """
def __left_rotate(self, node: TreeNode) -> TreeNode:
def __left_rotate(self, node: Optional[TreeNode]) -> TreeNode:
child = node.right
grand_child = child.left
# 以 child 为原点,将 node 向左旋转
@ -62,7 +60,7 @@ class AVLTree:
return child
""" 执行旋转操作,使该子树重新恢复平衡 """
def __rotate(self, node: TreeNode) -> TreeNode:
def __rotate(self, node: Optional[TreeNode]) -> TreeNode:
# 获取结点 node 的平衡因子
balance_factor = self.balance_factor(node)
# 左偏树
@ -92,7 +90,7 @@ class AVLTree:
return self.root
""" 递归插入结点(辅助函数)"""
def __insert_helper(self, node: typing.Optional[TreeNode], val: int) -> TreeNode:
def __insert_helper(self, node: Optional[TreeNode], val: int) -> TreeNode:
if node is None:
return TreeNode(val)
# 1. 查找插入位置,并插入结点
@ -114,7 +112,7 @@ class AVLTree:
return root
""" 递归删除结点(辅助函数) """
def __remove_helper(self, node: typing.Optional[TreeNode], val: int) -> typing.Optional[TreeNode]:
def __remove_helper(self, node: Optional[TreeNode], val: int) -> Optional[TreeNode]:
if node is None:
return None
# 1. 查找结点,并删除之
@ -132,7 +130,7 @@ class AVLTree:
else:
node = child
else: # 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点
temp = self.__min_node(node.right)
temp = self.__get_inorder_next(node.right)
node.right = self.__remove_helper(node.right, temp.val)
node.val = temp.val
# 更新结点高度
@ -140,8 +138,8 @@ class AVLTree:
# 2. 执行旋转操作,使该子树重新恢复平衡
return self.__rotate(node)
""" 获取最小结点 """
def __min_node(self, node: typing.Optional[TreeNode]) -> typing.Optional[TreeNode]:
""" 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) """
def __get_inorder_next(self, node: Optional[TreeNode]) -> Optional[TreeNode]:
if node is None:
return None
# 循环访问左子结点,直到叶结点时为最小结点,跳出

View File

@ -5,20 +5,18 @@ Author: a16su (lpluls001@gmail.com)
"""
import sys, os.path as osp
import typing
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from include import *
""" 二叉搜索树 """
class BinarySearchTree:
def __init__(self, nums: typing.List[int]) -> None:
def __init__(self, nums: List[int]) -> None:
nums.sort()
self.__root = self.build_tree(nums, 0, len(nums) - 1)
""" 构建二叉搜索树 """
def build_tree(self, nums: typing.List[int], start_index: int, end_index: int) -> typing.Optional[TreeNode]:
def build_tree(self, nums: List[int], start_index: int, end_index: int) -> Optional[TreeNode]:
if start_index > end_index:
return None
@ -31,11 +29,11 @@ class BinarySearchTree:
return root
@property
def root(self) -> typing.Optional[TreeNode]:
def root(self) -> Optional[TreeNode]:
return self.__root
""" 查找结点 """
def search(self, num: int) -> typing.Optional[TreeNode]:
def search(self, num: int) -> Optional[TreeNode]:
cur = self.root
# 循环查找,越过叶结点后跳出
while cur is not None:
@ -51,7 +49,7 @@ class BinarySearchTree:
return cur
""" 插入结点 """
def insert(self, num: int) -> typing.Optional[TreeNode]:
def insert(self, num: int) -> Optional[TreeNode]:
root = self.root
# 若树为空,直接提前返回
if root is None:
@ -81,7 +79,7 @@ class BinarySearchTree:
return node
""" 删除结点 """
def remove(self, num: int) -> typing.Optional[TreeNode]:
def remove(self, num: int) -> Optional[TreeNode]:
root = self.root
# 若树为空,直接提前返回
if root is None:
@ -117,7 +115,7 @@ class BinarySearchTree:
# 子结点数量 = 2
else:
# 获取中序遍历中 cur 的下一个结点
nex = self.min(cur.right)
nex = self.get_inorder_next(cur.right)
tmp = nex.val
# 递归删除结点 nex
self.remove(nex.val)
@ -125,11 +123,10 @@ class BinarySearchTree:
cur.val = tmp
return cur
""" 获取最小结点 """
def min(self, root: typing.Optional[TreeNode]) -> typing.Optional[TreeNode]:
""" 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) """
def get_inorder_next(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
if root is None:
return root
# 循环访问左子结点,直到叶结点时为最小结点,跳出
while root.left is not None:
root = root.left
@ -139,7 +136,7 @@ class BinarySearchTree:
""" Driver Code """
if __name__ == "__main__":
# 初始化二叉搜索树
nums = list(range(1, 16))
nums = list(range(1, 16)) # [1, 2, ..., 15]
bst = BinarySearchTree(nums=nums)
print("\n初始化的二叉树为\n")
print_tree(bst.root)

View File

@ -36,5 +36,5 @@ if __name__ == "__main__":
print_tree(n1)
# 删除结点
n1.left = n2
print("\n删除结点 P 后\n");
print("\n删除结点 P 后\n")
print_tree(n1)

View File

@ -5,14 +5,12 @@ Author: a16su (lpluls001@gmail.com)
"""
import sys, os.path as osp
import typing
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from include import *
""" 层序遍历 """
def hier_order(root: TreeNode):
def hier_order(root: Optional[TreeNode]):
# 初始化队列,加入根结点
queue = collections.deque()
queue.append(root)
@ -32,7 +30,7 @@ def hier_order(root: TreeNode):
if __name__ == "__main__":
# 初始化二叉树
# 这里借助了一个从数组直接生成二叉树的函数
root = list_to_tree(arr=[1, 2, 3, 4, 5, 6, 7, None, None, None, None, None, None, None, None])
root = list_to_tree(arr=[1, 2, 3, 4, 5, 6, 7])
print("\n初始化二叉树\n")
print_tree(root)

View File

@ -5,8 +5,6 @@ Author: a16su (lpluls001@gmail.com)
"""
import sys, os.path as osp
import typing
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from include import *
@ -14,7 +12,7 @@ from include import *
res = []
""" 前序遍历 """
def pre_order(root: typing.Optional[TreeNode]):
def pre_order(root: Optional[TreeNode]):
if root is None:
return
# 访问优先级:根结点 -> 左子树 -> 右子树
@ -23,7 +21,7 @@ def pre_order(root: typing.Optional[TreeNode]):
pre_order(root=root.right)
""" 中序遍历 """
def in_order(root: typing.Optional[TreeNode]):
def in_order(root: Optional[TreeNode]):
if root is None:
return
# 访问优先级:左子树 -> 根结点 -> 右子树
@ -32,7 +30,7 @@ def in_order(root: typing.Optional[TreeNode]):
in_order(root=root.right)
""" 后序遍历 """
def post_order(root: typing.Optional[TreeNode]):
def post_order(root: Optional[TreeNode]):
if root is None:
return
# 访问优先级:左子树 -> 右子树 -> 根结点
@ -45,7 +43,7 @@ def post_order(root: typing.Optional[TreeNode]):
if __name__ == "__main__":
# 初始化二叉树
# 这里借助了一个从数组直接生成二叉树的函数
root = list_to_tree(arr=[1, 2, 3, 4, 5, 6, 7, None, None, None, None, None, None, None, None])
root = list_to_tree(arr=[1, 2, 3, 4, 5, 6, 7])
print("\n初始化二叉树\n")
print_tree(root)

View File

@ -4,7 +4,7 @@ import queue
import random
import functools
import collections
from typing import List
from typing import Optional, List, Dict, DefaultDict, OrderedDict, Set, Deque
from .linked_list import ListNode, list_to_linked_list, linked_list_to_list, get_list_node
from .binary_tree import TreeNode, list_to_tree, tree_to_list, get_tree_node
from .print_util import print_matrix, print_linked_list, print_tree, print_dict

View File

@ -26,39 +26,30 @@ class TreeNode:
def list_to_tree(arr):
"""Generate a binary tree with a list
Args:
arr ([type]): [description]
Returns:
[type]: [description]
"""
if not arr:
return None
i = 1
root = TreeNode(int(arr[0]))
queue = collections.deque()
queue.append(root)
i = 0
root = TreeNode(arr[0])
queue = collections.deque([root])
while queue:
node = queue.popleft()
i += 1
if i >= len(arr): break
if arr[i] != None:
node.left = TreeNode(int(arr[i]))
node.left = TreeNode(arr[i])
queue.append(node.left)
i += 1
if i >= len(arr): break
if arr[i] != None:
node.right = TreeNode(int(arr[i]))
node.right = TreeNode(arr[i])
queue.append(node.right)
i += 1
return root
def tree_to_list(root):
"""Serialize a tree into an array
Args:
root ([type]): [description]
Returns:
[type]: [description]
"""
if not root: return []
queue = collections.deque()
@ -75,13 +66,6 @@ def tree_to_list(root):
def get_tree_node(root, val):
"""Get a tree node with specific value in a binary tree
Args:
root ([type]): [description]
val ([type]): [description]
Returns:
[type]: [description]
"""
if not root:
return