Add typing annotations to Python codes. (#411)

This commit is contained in:
Yudong Jin 2023-03-12 18:49:52 +08:00 committed by GitHub
parent 2029d2b939
commit 9151eaf533
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
50 changed files with 577 additions and 817 deletions

View file

@ -8,7 +8,7 @@ import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import *
def random_access(nums):
def random_access(nums: List[int]) -> int:
""" 随机访问元素 """
# 在区间 [0, len(nums)-1] 中随机抽取一个数字
random_index = random.randint(0, len(nums) - 1)
@ -18,7 +18,7 @@ def random_access(nums):
# 请注意Python 的 list 是动态数组,可以直接扩展
# 为了方便学习,本函数将 list 看作是长度不可变的数组
def extend(nums, enlarge):
def extend(nums: List[int], enlarge: int) -> List[int]:
""" 扩展数组长度 """
# 初始化一个扩展长度后的数组
res = [0] * (len(nums) + enlarge)
@ -28,7 +28,7 @@ def extend(nums, enlarge):
# 返回扩展后的新数组
return res
def insert(nums, num, index):
def insert(nums: List[int], num: int, index: int) -> None:
""" 在数组的索引 index 处插入元素 num """
# 把索引 index 以及之后的所有元素向后移动一位
for i in range(len(nums) - 1, index, -1):
@ -36,13 +36,13 @@ def insert(nums, num, index):
# 将 num 赋给 index 处元素
nums[index] = num
def remove(nums, index):
def remove(nums: List[int], index: int) -> None:
""" 删除索引 index 处元素 """
# 把索引 index 之后的所有元素向前移动一位
for i in range(index, len(nums) - 1):
nums[i] = nums[i + 1]
def traverse(nums):
def traverse(nums: List[int]) -> None:
""" 遍历数组 """
count = 0
# 通过索引遍历数组
@ -52,28 +52,27 @@ def traverse(nums):
for num in nums:
count += 1
def find(nums, target):
def find(nums: List[int], target: int) -> int:
""" 在数组中查找指定元素 """
for i in range(len(nums)):
if nums[i] == target:
return i
return -1
""" Driver Code """
if __name__ == "__main__":
""" 初始化数组 """
arr = [0] * 5
arr: List[int] = [0] * 5
print("数组 arr =", arr)
nums = [1, 3, 2, 5, 4]
nums: List[int] = [1, 3, 2, 5, 4]
print("数组 nums =", nums)
""" 随机访问 """
random_num = random_access(nums)
random_num: int = random_access(nums)
print("在 nums 中获取随机元素", random_num)
""" 长度扩展 """
nums = extend(nums, 3)
nums: List[int] = extend(nums, 3)
print("将数组长度扩展至 8 ,得到 nums =", nums)
""" 插入元素 """
@ -88,5 +87,5 @@ if __name__ == "__main__":
traverse(nums)
""" 查找元素 """
index = find(nums, 3)
index: int = find(nums, 3)
print("在 nums 中查找元素 3 ,得到索引 =", index)

View file

@ -8,13 +8,13 @@ import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import *
def insert(n0, P):
def insert(n0: ListNode, P: ListNode) -> None:
""" 在链表的结点 n0 之后插入结点 P """
n1 = n0.next
P.next = n1
n0.next = P
def remove(n0):
def remove(n0: ListNode) -> None:
""" 删除链表的结点 n0 之后的首个结点 """
if not n0.next:
return
@ -23,7 +23,7 @@ def remove(n0):
n1 = P.next
n0.next = n1
def access(head, index):
def access(head: ListNode, index: int) -> Optional[ListNode]:
""" 访问链表中索引为 index 的结点 """
for _ in range(index):
if not head:
@ -31,7 +31,7 @@ def access(head, index):
head = head.next
return head
def find(head, target):
def find(head: ListNode, target: int) -> int:
""" 在链表中查找值为 target 的首个结点 """
index = 0
while head:
@ -70,9 +70,9 @@ if __name__ == "__main__":
print_linked_list(n0)
""" 访问结点 """
node = access(n0, 3)
node: ListNode = access(n0, 3)
print("链表中索引 3 处的结点的值 = {}".format(node.val))
""" 查找结点 """
index = find(n0, 2)
index: int = find(n0, 2)
print("链表中值为 2 的结点的索引 = {}".format(index))

View file

@ -12,11 +12,11 @@ from modules import *
""" Driver Code """
if __name__ == "__main__":
""" 初始化列表 """
list = [1, 3, 2, 5, 4]
list: List[int] = [1, 3, 2, 5, 4]
print("列表 list =", list)
""" 访问元素 """
num = list[1]
num: int = list[1]
print("访问索引 1 处的元素,得到 num =", num)
""" 更新元素 """
@ -44,17 +44,17 @@ if __name__ == "__main__":
print("删除索引 3 处的元素,得到 list =", list)
""" 通过索引遍历列表 """
count = 0
count: int = 0
for i in range(len(list)):
count += 1
""" 直接遍历列表元素 """
count = 0
count: int = 0
for n in list:
count += 1
""" 拼接两个列表 """
list1 = [6, 8, 7, 10, 9]
list1: List[int] = [6, 8, 7, 10, 9]
list += list1
print("将列表 list1 拼接到 list 之后,得到 list =", list)

View file

@ -12,31 +12,31 @@ class MyList:
""" 列表类简易实现 """
def __init__(self):
""" 构造方法 """
self.__capacity = 10 # 列表容量
self.__nums = [0] * self.__capacity # 数组(存储列表元素)
self.__size = 0 # 列表长度(即当前元素数量)
self.__extend_ratio = 2 # 每次列表扩容的倍数
self.__capacity: int = 10 # 列表容量
self.__nums: List[int] = [0] * self.__capacity # 数组(存储列表元素)
self.__size: int = 0 # 列表长度(即当前元素数量)
self.__extend_ratio: int = 2 # 每次列表扩容的倍数
def size(self):
def size(self) -> int:
""" 获取列表长度(即当前元素数量) """
return self.__size
def capacity(self):
def capacity(self) -> int:
""" 获取列表容量 """
return self.__capacity
def get(self, index):
def get(self, index: int) -> int:
""" 访问元素 """
# 索引如果越界则抛出异常,下同
assert index >= 0 and index < self.__size, "索引越界"
return self.__nums[index]
def set(self, num, index):
def set(self, num: int, index: int) -> None:
""" 更新元素 """
assert index >= 0 and index < self.__size, "索引越界"
self.__nums[index] = num
def add(self, num):
def add(self, num: int) -> None:
""" 尾部添加元素 """
# 元素数量超出容量时,触发扩容机制
if self.size() == self.capacity():
@ -44,7 +44,7 @@ class MyList:
self.__nums[self.__size] = num
self.__size += 1
def insert(self, num, index):
def insert(self, num: int, index: int) -> None:
""" 中间插入元素 """
assert index >= 0 and index < self.__size, "索引越界"
# 元素数量超出容量时,触发扩容机制
@ -57,7 +57,7 @@ class MyList:
# 更新元素数量
self.__size += 1
def remove(self, index):
def remove(self, index: int) -> int:
""" 删除元素 """
assert index >= 0 and index < self.__size, "索引越界"
num = self.__nums[index]
@ -69,14 +69,14 @@ class MyList:
# 返回被删除元素
return num
def extend_capacity(self):
def extend_capacity(self) -> None:
""" 列表扩容 """
# 新建一个长度为 self.__size 的数组,并将原数组拷贝到新数组
self.__nums = self.__nums + [0] * self.capacity() * (self.__extend_ratio - 1)
# 更新列表容量
self.__capacity = len(self.__nums)
def to_array(self):
def to_array(self) -> List[int]:
""" 返回有效长度的列表 """
return self.__nums[:self.__size]

View file

@ -14,7 +14,7 @@ def two_sum_brute_force(nums: List[int], target: int) -> List[int]:
for i in range(len(nums) - 1):
for j in range(i + 1, len(nums)):
if nums[i] + nums[j] == target:
return i, j
return [i, j]
return []
def two_sum_hash_table(nums: List[int], target: int) -> List[int]:
@ -24,7 +24,7 @@ def two_sum_hash_table(nums: List[int], target: int) -> List[int]:
# 单层循环,时间复杂度 O(n)
for i in range(len(nums)):
if target - nums[i] in dic:
return dic[target - nums[i]], i
return [dic[target - nums[i]], i]
dic[nums[i]] = i
return []
@ -37,8 +37,8 @@ if __name__ == '__main__':
# ====== Driver Code ======
# 方法一
res = two_sum_brute_force(nums, target)
res: List[int] = two_sum_brute_force(nums, target)
print("方法一 res =", res)
# 方法二
res = two_sum_hash_table(nums, target)
res: List[int] = two_sum_hash_table(nums, target)
print("方法二 res =", res)

View file

@ -8,52 +8,52 @@ import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import *
def function():
def function() -> int:
""" 函数 """
# do something
return 0
def constant(n):
def constant(n: int) -> None:
""" 常数阶 """
# 常量、变量、对象占用 O(1) 空间
a = 0
nums = [0] * 10000
a: int = 0
nums: List[int] = [0] * 10000
node = ListNode(0)
# 循环中的变量占用 O(1) 空间
for _ in range(n):
c = 0
c: int = 0
# 循环中的函数占用 O(1) 空间
for _ in range(n):
function()
def linear(n):
def linear(n: int) -> None:
""" 线性阶 """
# 长度为 n 的列表占用 O(n) 空间
nums = [0] * n
nums: List[int] = [0] * n
# 长度为 n 的哈希表占用 O(n) 空间
mapp = {}
mapp: Dict = {}
for i in range(n):
mapp[i] = str(i)
def linear_recur(n):
def linear_recur(n: int) -> None:
""" 线性阶(递归实现) """
print("递归 n =", n)
if n == 1: return
linear_recur(n - 1)
def quadratic(n):
def quadratic(n: int) -> None:
""" 平方阶 """
# 二维列表占用 O(n^2) 空间
num_matrix = [[0] * n for _ in range(n)]
num_matrix: List[List[int]] = [[0] * n for _ in range(n)]
def quadratic_recur(n):
def quadratic_recur(n: int) -> int:
""" 平方阶(递归实现) """
if n <= 0: return 0
# 数组 nums 长度为 n, n-1, ..., 2, 1
nums = [0] * n
nums: List[int] = [0] * n
return quadratic_recur(n - 1)
def build_tree(n):
def build_tree(n: int) -> Optional[TreeNode]:
""" 指数阶(建立满二叉树) """
if n == 0: return None
root = TreeNode(0)
@ -74,5 +74,5 @@ if __name__ == "__main__":
quadratic(n)
quadratic_recur(n)
# 指数阶
root = build_tree(n)
root: Optional[TreeNode] = build_tree(n)
print_tree(root)

View file

@ -8,56 +8,57 @@ import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import *
def constant(n):
def constant(n: int) -> int:
""" 常数阶 """
count = 0
size = 100000
count: int = 0
size: int = 100000
for _ in range(size):
count += 1
return count
def linear(n):
def linear(n: int) -> int:
""" 线性阶 """
count = 0
count: int = 0
for _ in range(n):
count += 1
return count
def array_traversal(nums):
def array_traversal(nums: List[int]) -> int:
""" 线性阶(遍历数组)"""
count = 0
count: int = 0
# 循环次数与数组长度成正比
for num in nums:
count += 1
return count
def quadratic(n):
def quadratic(n: int) -> int:
""" 平方阶 """
count = 0
count: int = 0
# 循环次数与数组长度成平方关系
for i in range(n):
for j in range(n):
count += 1
return count
def bubble_sort(nums):
def bubble_sort(nums: List[int]) -> int:
""" 平方阶(冒泡排序)"""
count = 0 # 计数器
count: int = 0 # 计数器
# 外循环:待排序元素数量为 n-1, n-2, ..., 1
for i in range(len(nums) - 1, 0, -1):
# 内循环:冒泡操作
for j in range(i):
if nums[j] > nums[j + 1]:
# 交换 nums[j] 与 nums[j + 1]
tmp = nums[j]
tmp: int = nums[j]
nums[j] = nums[j + 1]
nums[j + 1] = tmp
count += 3 # 元素交换包含 3 个单元操作
return count
def exponential(n):
def exponential(n: int) -> int:
""" 指数阶(循环实现)"""
count, base = 0, 1
count: int = 0
base: int = 1
# cell 每轮一分为二,形成数列 1, 2, 4, 8, ..., 2^(n-1)
for _ in range(n):
for _ in range(base):
@ -66,37 +67,37 @@ def exponential(n):
# count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1
return count
def exp_recur(n):
def exp_recur(n: int) -> int:
""" 指数阶(递归实现)"""
if n == 1: return 1
return exp_recur(n - 1) + exp_recur(n - 1) + 1
def logarithmic(n):
def logarithmic(n: float) -> int:
""" 对数阶(循环实现)"""
count = 0
count: int = 0
while n > 1:
n = n / 2
count += 1
return count
def log_recur(n):
def log_recur(n: float) -> int:
""" 对数阶(递归实现)"""
if n <= 1: return 0
return log_recur(n / 2) + 1
def linear_log_recur(n):
def linear_log_recur(n: float) -> int:
""" 线性对数阶 """
if n <= 1: return 1
count = linear_log_recur(n // 2) + \
linear_log_recur(n // 2)
count: int = linear_log_recur(n // 2) + \
linear_log_recur(n // 2)
for _ in range(n):
count += 1
return count
def factorial_recur(n):
def factorial_recur(n: int) -> int:
""" 阶乘阶(递归实现)"""
if n == 0: return 1
count = 0
count: int = 0
# 从 1 个分裂出 n 个
for _ in range(n):
count += factorial_recur(n - 1)
@ -109,32 +110,32 @@ if __name__ == "__main__":
n = 8
print("输入数据大小 n =", n)
count = constant(n)
count: int = constant(n)
print("常数阶的计算操作数量 =", count)
count = linear(n)
count: int = linear(n)
print("线性阶的计算操作数量 =", count)
count = array_traversal([0] * n)
count: int = array_traversal([0] * n)
print("线性阶(遍历数组)的计算操作数量 =", count)
count = quadratic(n)
count: int = quadratic(n)
print("平方阶的计算操作数量 =", count)
nums = [i for i in range(n, 0, -1)] # [n,n-1,...,2,1]
count = bubble_sort(nums)
nums: List[int] = [i for i in range(n, 0, -1)] # [n,n-1,...,2,1]
count: int = bubble_sort(nums)
print("平方阶(冒泡排序)的计算操作数量 =", count)
count = exponential(n)
count: int = exponential(n)
print("指数阶(循环实现)的计算操作数量 =", count)
count = exp_recur(n)
count: int = exp_recur(n)
print("指数阶(递归实现)的计算操作数量 =", count)
count = logarithmic(n)
count: int = logarithmic(n)
print("对数阶(循环实现)的计算操作数量 =", count)
count = log_recur(n)
count: int = log_recur(n)
print("对数阶(递归实现)的计算操作数量 =", count)
count = linear_log_recur(n)
count: int = linear_log_recur(n)
print("线性对数阶(递归实现)的计算操作数量 =", count)
count = factorial_recur(n)
count: int = factorial_recur(n)
print("阶乘阶(递归实现)的计算操作数量 =", count)

View file

@ -8,15 +8,15 @@ import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import *
def random_numbers(n):
def random_numbers(n: int) -> List[int]:
""" 生成一个数组,元素为: 1, 2, ..., n ,顺序被打乱 """
# 生成数组 nums =: 1, 2, 3, ..., n
nums = [i for i in range(1, n + 1)]
nums: List[int] = [i for i in range(1, n + 1)]
# 随机打乱数组元素
random.shuffle(nums)
return nums
def find_one(nums):
def find_one(nums: List[int]) -> int:
""" 查找数组 nums 中数字 1 所在索引 """
for i in range(len(nums)):
# 当元素 1 在数组头部时,达到最佳时间复杂度 O(1)
@ -29,8 +29,8 @@ def find_one(nums):
""" Driver Code """
if __name__ == "__main__":
for i in range(10):
n = 100
nums = random_numbers(n)
index = find_one(nums)
n: int = 100
nums: List[int] = random_numbers(n)
index: int = find_one(nums)
print("\n数组 [ 1, 2, ..., n ] 被打乱后 =", nums)
print("数字 1 的索引为", index)

View file

@ -10,12 +10,10 @@ from modules import *
class GraphAdjList:
""" 基于邻接表实现的无向图类 """
# 邻接表key: 顶点value该顶点的所有邻接顶点
adj_list = {}
def __init__(self, edges: List[List[Vertex]]) -> None:
""" 构造方法 """
self.adj_list = {}
# 邻接表key: 顶点value该顶点的所有邻接顶点
self.adj_list: Dict = {}
# 添加所有顶点和边
for edge in edges:
self.add_vertex(edge[0])

View file

@ -11,14 +11,14 @@ from modules import *
class GraphAdjMat:
""" 基于邻接矩阵实现的无向图类 """
# 顶点列表,元素代表“顶点值”,索引代表“顶点索引”
vertices = []
vertices: List[int] = []
# 邻接矩阵,行列索引对应“顶点索引”
adj_mat = []
adj_mat: List[List[int]] = []
def __init__(self, vertices, edges):
def __init__(self, vertices: List[int], edges: List[List[int]]) -> None:
""" 构造方法 """
self.vertices = []
self.adj_mat = []
self.vertices: List[int] = []
self.adj_mat: List[List[int]] = []
# 添加顶点
for val in vertices:
self.add_vertex(val)
@ -27,23 +27,23 @@ class GraphAdjMat:
for e in edges:
self.add_edge(e[0], e[1])
def size(self):
def size(self) -> int:
""" 获取顶点数量 """
return len(self.vertices)
def add_vertex(self, val):
def add_vertex(self, val: int) -> None:
""" 添加顶点 """
n = self.size()
# 向顶点列表中添加新顶点的值
self.vertices.append(val)
# 在邻接矩阵中添加一行
new_row = [0]*n
new_row = [0] * n
self.adj_mat.append(new_row)
# 在邻接矩阵中添加一列
for row in self.adj_mat:
row.append(0)
def remove_vertex(self, index):
def remove_vertex(self, index: int) -> None:
""" 删除顶点 """
if index >= self.size():
raise IndexError()
@ -55,7 +55,7 @@ class GraphAdjMat:
for row in self.adj_mat:
row.pop(index)
def add_edge(self, i, j):
def add_edge(self, i: int, j: int) -> None:
""" 添加边 """
# 参数 i, j 对应 vertices 元素索引
# 索引越界与相等处理
@ -65,7 +65,7 @@ class GraphAdjMat:
self.adj_mat[i][j] = 1
self.adj_mat[j][i] = 1
def remove_edge(self, i, j):
def remove_edge(self, i: int, j: int) -> None:
""" 删除边 """
# 参数 i, j 对应 vertices 元素索引
# 索引越界与相等处理
@ -74,7 +74,7 @@ class GraphAdjMat:
self.adj_mat[i][j] = 0
self.adj_mat[j][i] = 0
def print(self):
def print(self) -> None:
""" 打印邻接矩阵 """
print("顶点列表 =", self.vertices)
print("邻接矩阵 =")
@ -85,8 +85,8 @@ class GraphAdjMat:
if __name__ == "__main__":
""" 初始化无向图 """
# 请注意edges 元素代表顶点索引,即对应 vertices 元素索引
vertices = [1, 3, 2, 5, 4]
edges = [[0, 1], [0, 3], [1, 2], [2, 3], [2, 4], [3, 4]]
vertices: List[int] = [1, 3, 2, 5, 4]
edges: List[List[int]] = [[0, 1], [0, 3], [1, 2], [2, 3], [2, 4], [3, 4]]
graph = GraphAdjMat(vertices, edges)
print("\n初始化后,图为")
graph.print()

View file

@ -4,9 +4,13 @@ Created Time: 2022-12-14
Author: msk397 (machangxinq@gmail.com)
"""
import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import *
class Entry:
""" 键值对 int->String """
def __init__(self, key, val):
def __init__(self, key: int, val: str):
self.key = key
self.val = val
@ -15,58 +19,58 @@ class ArrayHashMap:
def __init__(self):
""" 构造方法 """
# 初始化一个长度为 100 的桶(数组)
self.bucket = [None] * 100
self.bucket: List[Optional[Entry]] = [None] * 100
def hash_func(self, key):
def hash_func(self, key: int) -> int:
""" 哈希函数 """
index = key % 100
index: int = key % 100
return index
def get(self, key):
def get(self, key: int) -> str:
""" 查询操作 """
index = self.hash_func(key)
pair = self.bucket[index]
index: int = self.hash_func(key)
pair: Entry = self.bucket[index]
if pair is None:
return None
return pair.val
def put(self, key, val):
def put(self, key: int, val: str) -> None:
""" 添加操作 """
pair = Entry(key, val)
index = self.hash_func(key)
index: int = self.hash_func(key)
self.bucket[index] = pair
def remove(self, key):
def remove(self, key: int) -> None:
""" 删除操作 """
index = self.hash_func(key)
index: int = self.hash_func(key)
# 置为 None ,代表删除
self.bucket[index] = None
def entry_set(self):
def entry_set(self) -> List[Entry]:
""" 获取所有键值对 """
result = []
result: List[Entry] = []
for pair in self.bucket:
if pair is not None:
result.append(pair)
return result
def key_set(self):
def key_set(self) -> List[int]:
""" 获取所有键 """
result = []
result: List[int] = []
for pair in self.bucket:
if pair is not None:
result.append(pair.key)
return result
def value_set(self):
def value_set(self) -> List[str]:
""" 获取所有值 """
result = []
result: List[str] = []
for pair in self.bucket:
if pair is not None:
result.append(pair.val)
return result
def print(self):
def print(self) -> None:
""" 打印哈希表 """
for pair in self.bucket:
if pair is not None:

View file

@ -12,7 +12,7 @@ from modules import *
""" Driver Code """
if __name__ == "__main__":
""" 初始化哈希表 """
mapp = {}
mapp: Dict = {}
""" 添加操作 """
# 在哈希表中添加键值对 (key, value)
@ -26,7 +26,7 @@ if __name__ == "__main__":
""" 查询操作 """
# 向哈希表输入键 key ,得到值 value
name = mapp[15937]
name: str = mapp[15937]
print("\n输入学号 15937 ,查询到姓名 " + name)
""" 删除操作 """

View file

@ -4,16 +4,18 @@ Created Time: 2023-02-23
Author: Krahets (krahets@163.com)
"""
import sys, os.path as osp
import sys
import os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import *
def test_push(heap, val, flag=1):
def test_push(heap: List, val: int, flag: int = 1) -> None:
heapq.heappush(heap, flag * val) # 元素入堆
print(f"\n元素 {val} 入堆后")
print_heap([flag * val for val in heap])
def test_pop(heap, flag=1):
def test_pop(heap: List, flag: int = 1) -> None:
val = flag * heapq.heappop(heap) # 堆顶元素出堆
print(f"\n堆顶元素 {val} 出堆后")
print_heap([flag * val for val in heap])
@ -37,7 +39,7 @@ if __name__ == "__main__":
test_push(max_heap, 4, flag)
""" 获取堆顶元素 """
peek = flag * max_heap[0]
peek: int = flag * max_heap[0]
print(f"\n堆顶元素为 {peek}")
""" 堆顶元素出堆 """
@ -48,16 +50,16 @@ if __name__ == "__main__":
test_pop(max_heap, flag)
""" 获取堆大小 """
size = len(max_heap)
size: int = len(max_heap)
print(f"\n堆元素数量为 {size}")
""" 判断堆是否为空 """
is_empty = not max_heap
is_empty: bool = not max_heap
print(f"\n堆是否为空 {is_empty}")
""" 输入列表并建堆 """
# 时间复杂度为 O(n) ,而非 O(nlogn)
min_heap = [1, 3, 2, 5, 4]
min_heap: List[int] = [1, 3, 2, 5, 4]
heapq.heapify(min_heap)
print("\n输入列表并建立小顶堆后")
print_heap(min_heap)

View file

@ -8,7 +8,7 @@ import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import *
def binary_search(nums, target):
def binary_search(nums: List[int], target: int) -> int:
""" 二分查找(双闭区间) """
# 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
i, j = 0, len(nums) - 1
@ -23,7 +23,7 @@ def binary_search(nums, target):
return -1 # 未找到目标元素,返回 -1
def binary_search1(nums, target):
def binary_search1(nums: List[int], target: int) -> int:
""" 二分查找(左闭右开) """
# 初始化左闭右开 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
i, j = 0, len(nums)
@ -41,13 +41,13 @@ def binary_search1(nums, target):
""" Driver Code """
if __name__ == '__main__':
target = 6
nums = [1, 3, 6, 8, 12, 15, 23, 67, 70, 92]
target: int = 6
nums: List[int] = [1, 3, 6, 8, 12, 15, 23, 67, 70, 92]
# 二分查找(双闭区间)
index = binary_search(nums, target)
index: int = binary_search(nums, target)
print("目标元素 6 的索引 = ", index)
# 二分查找(左闭右开)
index = binary_search1(nums, target)
index: int = binary_search1(nums, target)
print("目标元素 6 的索引 = ", index)

View file

@ -8,38 +8,38 @@ import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import *
def hashing_search_array(mapp, target):
def hashing_search_array(mapp: Dict[int, int], target: int) -> int:
""" 哈希查找(数组) """
# 哈希表的 key: 目标元素value: 索引
# 若哈希表中无此 key ,返回 -1
return mapp.get(target, -1)
def hashing_search_linkedlist(mapp, target):
def hashing_search_linkedlist(mapp: Dict[int, ListNode], target: int) -> Optional[ListNode]:
""" 哈希查找(链表) """
# 哈希表的 key: 目标元素value: 结点对象
# 若哈希表中无此 key ,返回 -1
return mapp.get(target, -1)
# 若哈希表中无此 key ,返回 None
return mapp.get(target, None)
""" Driver Code """
if __name__ == '__main__':
target = 3
target: int = 3
# 哈希查找(数组)
nums = [1, 5, 3, 2, 4, 7, 5, 9, 10, 8]
nums: List[int] = [1, 5, 3, 2, 4, 7, 5, 9, 10, 8]
# 初始化哈希表
mapp = {}
mapp: Dict[int, int] = {}
for i in range(len(nums)):
mapp[nums[i]] = i # key: 元素value: 索引
index = hashing_search_array(mapp, target)
index: int = hashing_search_array(mapp, target)
print("目标元素 3 的索引 =", index)
# 哈希查找(链表)
head = list_to_linked_list(nums)
head: ListNode = list_to_linked_list(nums)
# 初始化哈希表
map1 = {}
map1: Dict[int, ListNode] = {}
while head:
map1[head.val] = head # key: 结点值value: 结点
head = head.next
node = hashing_search_linkedlist(map1, target)
node: ListNode = hashing_search_linkedlist(map1, target)
print("目标结点值 3 的对应结点对象为", node)

View file

@ -8,7 +8,7 @@ import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import *
def linear_search_array(nums, target):
def linear_search_array(nums: List[int], target: int) -> int:
""" 线性查找(数组) """
# 遍历数组
for i in range(len(nums)):
@ -16,7 +16,7 @@ def linear_search_array(nums, target):
return i
return -1 # 未找到目标元素,返回 -1
def linear_search_linkedlist(head, target):
def linear_search_linkedlist(head: ListNode, target: int) -> Optional[ListNode]:
""" 线性查找(链表) """
# 遍历链表
while head:
@ -28,14 +28,14 @@ def linear_search_linkedlist(head, target):
""" Driver Code """
if __name__ == '__main__':
target = 3
target: int = 3
# 在数组中执行线性查找
nums = [1, 5, 3, 2, 4, 7, 5, 9, 10, 8]
index = linear_search_array(nums, target)
nums: List[int] = [1, 5, 3, 2, 4, 7, 5, 9, 10, 8]
index: int = linear_search_array(nums, target)
print("目标元素 3 的索引 =", index)
# 在链表中执行线性查找
head = list_to_linked_list(nums)
node = linear_search_linkedlist(head, target)
head: ListNode = list_to_linked_list(nums)
node: Optional[ListNode] = linear_search_linkedlist(head, target)
print("目标结点值 3 的对应结点对象为", node)

View file

@ -8,9 +8,9 @@ import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import *
def bubble_sort(nums):
def bubble_sort(nums: List[int]) -> None:
""" 冒泡排序 """
n = len(nums)
n: int = len(nums)
# 外循环:待排序元素数量为 n-1, n-2, ..., 1
for i in range(n - 1, 0, -1):
# 内循环:冒泡操作
@ -19,12 +19,12 @@ def bubble_sort(nums):
# 交换 nums[j] 与 nums[j + 1]
nums[j], nums[j + 1] = nums[j + 1], nums[j]
def bubble_sort_with_flag(nums):
def bubble_sort_with_flag(nums: List[int]) -> None:
""" 冒泡排序(标志优化) """
n = len(nums)
n: int = len(nums)
# 外循环:待排序元素数量为 n-1, n-2, ..., 1
for i in range(n - 1, 0, -1):
flag = False # 初始化标志位
flag: bool = False # 初始化标志位
# 内循环:冒泡操作
for j in range(i):
if nums[j] > nums[j + 1]:
@ -37,10 +37,10 @@ def bubble_sort_with_flag(nums):
""" Driver Code """
if __name__ == '__main__':
nums = [4, 1, 3, 1, 5, 2]
nums: List[int] = [4, 1, 3, 1, 5, 2]
bubble_sort(nums)
print("排序后数组 nums =", nums)
nums1 = [4, 1, 3, 1, 5, 2]
nums1: List[int] = [4, 1, 3, 1, 5, 2]
bubble_sort_with_flag(nums1)
print("排序后数组 nums =", nums1)

View file

@ -8,12 +8,12 @@ import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import *
def insertion_sort(nums):
def insertion_sort(nums: List[int]) -> None:
""" 插入排序 """
# 外循环base = nums[1], nums[2], ..., nums[n-1]
for i in range(1, len(nums)):
base = nums[i]
j = i - 1
base: int = nums[i]
j: int = i - 1
# 内循环:将 base 插入到左边的正确位置
while j >= 0 and nums[j] > base:
nums[j + 1] = nums[j] # 1. 将 nums[j] 向右移动一位
@ -23,6 +23,6 @@ def insertion_sort(nums):
""" Driver Code """
if __name__ == '__main__':
nums = [4, 1, 3, 1, 5, 2]
nums: List[int] = [4, 1, 3, 1, 5, 2]
insertion_sort(nums)
print("排序后数组 nums =", nums)

View file

@ -8,18 +8,21 @@ import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import *
def merge(nums, left, mid, right):
def merge(nums: List[int], left: int, mid: int, right: int) -> None:
""" 合并左子数组和右子数组 """
# 左子数组区间 [left, mid]
# 右子数组区间 [mid + 1, right]
# 初始化辅助数组 借助 copy模块
tmp = nums[left:right + 1]
tmp: List[int] = nums[left:right + 1].copy()
# 左子数组的起始索引和结束索引
left_start, left_end = left - left, mid - left
left_start: int = 0
left_end: int = mid - left
# 右子数组的起始索引和结束索引
right_start, right_end = mid + 1 - left, right - left
right_start: int = mid + 1 - left
right_end: int = right - left
# i, j 分别指向左子数组、右子数组的首元素
i, j = left_start, right_start
i: int = left_start
j: int = right_start
# 通过覆盖原数组 nums 来合并左子数组和右子数组
for k in range(left, right + 1):
# 若“左子数组已全部合并完”,则选取右子数组元素,并且 j++
@ -35,13 +38,13 @@ def merge(nums, left, mid, right):
nums[k] = tmp[j]
j += 1
def merge_sort(nums, left, right):
def merge_sort(nums: List[int], left: int, right: int) -> None:
""" 归并排序 """
# 终止条件
if left >= right:
return # 当子数组长度为 1 时终止递归
# 划分阶段
mid = (left + right) // 2 # 计算中点
mid: int = (left + right) // 2 # 计算中点
merge_sort(nums, left, mid) # 递归左子数组
merge_sort(nums, mid + 1, right) # 递归右子数组
# 合并阶段
@ -50,6 +53,6 @@ def merge_sort(nums, left, right):
""" Driver Code """
if __name__ == '__main__':
nums = [ 7, 3, 2, 6, 0, 1, 5, 4 ]
nums: List[int] = [ 7, 3, 2, 6, 0, 1, 5, 4 ]
merge_sort(nums, 0, len(nums) - 1)
print("归并排序完成后 nums =", nums)

View file

@ -10,7 +10,7 @@ from modules import *
class QuickSort:
""" 快速排序类 """
def partition(self, nums, left, right):
def partition(self, nums: List[int], left: int, right: int) -> int:
""" 哨兵划分 """
# 以 nums[left] 作为基准数
i, j = left, right
@ -25,20 +25,20 @@ class QuickSort:
nums[i], nums[left] = nums[left], nums[i]
return i # 返回基准数的索引
def quick_sort(self, nums, left, right):
def quick_sort(self, nums: List[int], left: int, right: int) -> None:
""" 快速排序 """
# 子数组长度为 1 时终止递归
if left >= right:
return
# 哨兵划分
pivot = self.partition(nums, left, right)
pivot: int = self.partition(nums, left, right)
# 递归左子数组、右子数组
self.quick_sort(nums, left, pivot - 1)
self.quick_sort(nums, pivot + 1, right)
class QuickSortMedian:
""" 快速排序类(中位基准数优化)"""
def median_three(self, nums, left, mid, right):
def median_three(self, nums: List[int], left: int, mid: int, right: int) -> int:
""" 选取三个元素的中位数 """
# 此处使用异或运算来简化代码
# 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1
@ -48,10 +48,10 @@ class QuickSortMedian:
return mid
return right
def partition(self, nums, left, right):
def partition(self, nums: List[int], left: int, right: int) -> int:
""" 哨兵划分(三数取中值) """
# 以 nums[left] 作为基准数
med = self.median_three(nums, left, (left + right) // 2, right)
med: int = self.median_three(nums, left, (left + right) // 2, right)
# 将中位数交换至数组最左端
nums[left], nums[med] = nums[med], nums[left]
# 以 nums[left] 作为基准数
@ -67,19 +67,20 @@ class QuickSortMedian:
nums[i], nums[left] = nums[left], nums[i]
return i # 返回基准数的索引
def quick_sort(self, nums, left, right):
def quick_sort(self, nums: List[int], left: int, right: int) -> None:
""" 快速排序 """
# 子数组长度为 1 时终止递归
if left >= right: return
if left >= right:
return
# 哨兵划分
pivot = self.partition(nums, left, right)
pivot: int = self.partition(nums, left, right)
# 递归左子数组、右子数组
self.quick_sort(nums, left, pivot - 1)
self.quick_sort(nums, pivot + 1, right)
class QuickSortTailCall:
""" 快速排序类(尾递归优化) """
def partition(self, nums, left, right):
def partition(self, nums: List[int], left: int, right: int) -> int:
""" 哨兵划分 """
# 以 nums[left] 作为基准数
i, j = left, right
@ -94,12 +95,12 @@ class QuickSortTailCall:
nums[i], nums[left] = nums[left], nums[i]
return i # 返回基准数的索引
def quick_sort(self, nums, left, right):
def quick_sort(self, nums: List[int], left: int, right: int) -> None:
""" 快速排序(尾递归优化) """
# 子数组长度为 1 时终止
while left < right:
# 哨兵划分操作
pivot = self.partition(nums, left, right)
pivot: int = self.partition(nums, left, right)
# 对两个子数组中较短的那个执行快排
if pivot - left < right - pivot:
self.quick_sort(nums, left, pivot - 1) # 递归排序左子数组
@ -112,16 +113,16 @@ class QuickSortTailCall:
""" Driver Code """
if __name__ == '__main__':
# 快速排序
nums = [2, 4, 1, 0, 3, 5]
nums: List[int] = [2, 4, 1, 0, 3, 5]
QuickSort().quick_sort(nums, 0, len(nums) - 1)
print("快速排序完成后 nums =", nums)
# 快速排序(中位基准数优化)
nums1 = [2, 4, 1, 0, 3, 5]
nums1: List[int] = [2, 4, 1, 0, 3, 5]
QuickSortMedian().quick_sort(nums1, 0, len(nums1) - 1)
print("快速排序(中位基准数优化)完成后 nums =", nums1)
# 快速排序(尾递归优化)
nums2 = [2, 4, 1, 0, 3, 5]
nums2: List[int] = [2, 4, 1, 0, 3, 5]
QuickSortTailCall().quick_sort(nums2, 0, len(nums2) - 1)
print("快速排序(尾递归优化)完成后 nums =", nums2)

View file

@ -4,94 +4,94 @@ Created Time: 2023-03-01
Author: Krahets (krahets@163.com)
"""
import os.path as osp
import sys
import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import *
class ArrayDeque:
""" 基于环形数组实现的双向队列 """
def __init__(self, capacity):
""" 构造方法 """
self.nums = [0] * capacity
self.front = 0
self.que_size = 0
def capacity(self):
def __init__(self, capacity: int) -> None:
""" 构造方法 """
self.__nums: List[int] = [0] * capacity
self.__front: int = 0
self.__size: int = 0
def capacity(self) -> int:
""" 获取双向队列的容量 """
return len(self.nums)
return len(self.__nums)
def size(self):
def size(self) -> int:
""" 获取双向队列的长度 """
return self.que_size
return self.__size
def is_empty(self):
def is_empty(self) -> bool:
""" 判断双向队列是否为空 """
return self.que_size == 0
return self.__size == 0
def index(self, i):
def index(self, i: int) -> int:
""" 计算环形数组索引 """
# 通过取余操作实现数组首尾相连
# 当 i 越过数组尾部后,回到头部
# 当 i 越过数组头部后,回到尾部
return (i + self.capacity()) % self.capacity()
def push_first(self, num):
def push_first(self, num: int) -> None:
""" 队首入队 """
if self.que_size == self.capacity():
if self.__size == self.capacity():
print("双向队列已满")
return
# 队首指针向左移动一位
# 通过取余操作,实现 front 越过数组头部后回到尾部
self.front = self.index(self.front-1)
self.__front = self.index(self.__front - 1)
# 将 num 添加至队首
self.nums[self.front] = num
self.que_size += 1
self.__nums[self.__front] = num
self.__size += 1
def push_last(self, num):
def push_last(self, num: int) -> None:
""" 队尾入队 """
if self.que_size == self.capacity():
if self.__size == self.capacity():
print("双向队列已满")
return
# 计算尾指针,指向队尾索引 + 1
rear = self.index(self.front + self.que_size)
rear = self.index(self.__front + self.__size)
# 将 num 添加至队尾
self.nums[rear] = num
self.que_size += 1
self.__nums[rear] = num
self.__size += 1
def poll_first(self):
def poll_first(self) -> int:
""" 队首出队 """
num = self.peek_first()
# 队首指针向后移动一位
self.front = self.index(self.front+1)
self.que_size -= 1
self.__front = self.index(self.__front + 1)
self.__size -= 1
return num
def poll_last(self):
def poll_last(self) -> int:
""" 队尾出队 """
num = self.peek_last()
self.que_size -= 1
self.__size -= 1
return num
def peek_first(self):
def peek_first(self) -> int:
""" 访问队首元素 """
assert not self.is_empty(), "双向队列为空"
return self.nums[self.front]
return self.__nums[self.__front]
def peek_last(self):
def peek_last(self) -> int:
""" 访问队尾元素 """
assert not self.is_empty(), "双向队列为空"
# 计算尾元素索引
last = self.index(self.front + self.que_size - 1)
return self.nums[last]
last = self.index(self.__front + self.__size - 1)
return self.__nums[last]
def to_array(self):
def to_array(self) -> List[int]:
""" 返回数组用于打印 """
# 仅转换有效长度范围内的列表元素
res = []
for i in range(self.que_size):
res.append(self.nums[self.index(self.front+i)])
for i in range(self.__size):
res.append(self.__nums[self.index(self.__front + i)])
return res
@ -105,9 +105,9 @@ if __name__ == "__main__":
print("双向队列 deque =", deque.to_array())
""" 访问元素 """
peek_first = deque.peek_first()
peek_first: int = deque.peek_first()
print("队首元素 peek_first =", peek_first)
peek_last = deque.peek_last()
peek_last: int = deque.peek_last()
print("队尾元素 peek_last =", peek_last)
""" 元素入队 """
@ -117,15 +117,15 @@ if __name__ == "__main__":
print("元素 1 队首入队后 deque =", deque.to_array())
""" 元素出队 """
poll_last = deque.poll_last()
poll_last: int = deque.poll_last()
print("队尾出队元素 =", poll_last, ",队尾出队后 deque =", deque.to_array())
poll_first = deque.poll_first()
poll_first: int = deque.poll_first()
print("队首出队元素 =", poll_first, ",队首出队后 deque =", deque.to_array())
""" 获取双向队列的长度 """
size = deque.size()
size: int = deque.size()
print("双向队列长度 size =", size)
""" 判断双向队列是否为空 """
is_empty = deque.is_empty()
is_empty: bool = deque.is_empty()
print("双向队列是否为空 =", is_empty)

View file

@ -4,59 +4,57 @@ Created Time: 2022-12-01
Author: Peng Chen (pengchzn@gmail.com)
"""
import os.path as osp
import sys
import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import *
class ArrayQueue:
""" 基于环形数组实现的队列 """
def __init__(self, size):
def __init__(self, size: int) -> None:
""" 构造方法 """
self.__nums = [0] * size # 用于存储队列元素的数组
self.__front = 0 # 队首指针,指向队首元素
self.__size = 0 # 队列长度
self.__nums: List[int] = [0] * size # 用于存储队列元素的数组
self.__front: int = 0 # 队首指针,指向队首元素
self.__size: int = 0 # 队列长度
def capacity(self):
def capacity(self) -> int:
""" 获取队列的容量 """
return len(self.__nums)
def size(self):
def size(self) -> int:
""" 获取队列的长度 """
return self.__size
def is_empty(self):
def is_empty(self) -> bool:
""" 判断队列是否为空 """
return self.__size == 0
def push(self, num):
def push(self, num: int) -> None:
""" 入队 """
assert self.__size < self.capacity(), "队列已满"
# 计算尾指针,指向队尾索引 + 1
# 通过取余操作,实现 rear 越过数组尾部后回到头部
rear = (self.__front + self.__size) % self.capacity()
rear: int = (self.__front + self.__size) % self.capacity()
# 将 num 添加至队尾
self.__nums[rear] = num
self.__size += 1
def poll(self):
def poll(self) -> int:
""" 出队 """
num = self.peek()
num: int = self.peek()
# 队首指针向后移动一位,若越过尾部则返回到数组头部
self.__front = (self.__front + 1) % self.capacity()
self.__size -= 1
return num
def peek(self):
def peek(self) -> int:
""" 访问队首元素 """
assert not self.is_empty(), "队列为空"
return self.__nums[self.__front]
def to_list(self):
def to_list(self) -> List[int]:
""" 返回列表用于打印 """
res = [0] * self.size()
j = self.__front
res: List[int] = [0] * self.size()
j: int = self.__front
for i in range(self.size()):
res[i] = self.__nums[(j % self.capacity())]
j += 1
@ -77,24 +75,24 @@ if __name__ == "__main__":
print("队列 queue =", queue.to_list())
""" 访问队首元素 """
peek = queue.peek()
peek: int = queue.peek()
print("队首元素 peek =", peek)
""" 元素出队 """
poll = queue.poll()
poll: int = queue.poll()
print("出队元素 poll =", poll)
print("出队后 queue =", queue.to_list())
""" 获取队列的长度 """
size = queue.size()
size: int = queue.size()
print("队列长度 size =", size)
""" 判断队列是否为空 """
is_empty = queue.is_empty()
is_empty: bool = queue.is_empty()
print("队列是否为空 =", is_empty)
""" 测试环形数组 """
for i in range(10):
queue.push(i);
queue.poll();
print("", i, "轮入队 + 出队后 queue = ", queue.to_list());
queue.push(i)
queue.poll()
print("", i, "轮入队 + 出队后 queue = ", queue.to_list())

View file

@ -10,33 +10,33 @@ from modules import *
class ArrayStack:
""" 基于数组实现的栈 """
def __init__(self):
def __init__(self) -> None:
""" 构造方法 """
self.__stack = []
self.__stack: List[int] = []
def size(self):
def size(self) -> int:
""" 获取栈的长度 """
return len(self.__stack)
def is_empty(self):
def is_empty(self) -> bool:
""" 判断栈是否为空 """
return self.__stack == []
def push(self, item):
def push(self, item: int) -> None:
""" 入栈 """
self.__stack.append(item)
def pop(self):
def pop(self) -> int:
""" 出栈 """
assert not self.is_empty(), "栈为空"
return self.__stack.pop()
def peek(self):
def peek(self) -> int:
""" 访问栈顶元素 """
assert not self.is_empty(), "栈为空"
return self.__stack[-1]
def to_list(self):
def to_list(self) -> List[int]:
""" 返回列表用于打印 """
return self.__stack
@ -55,18 +55,18 @@ if __name__ == "__main__":
print("栈 stack =", stack.to_list())
""" 访问栈顶元素 """
peek = stack.peek()
peek: int = stack.peek()
print("栈顶元素 peek =", peek)
""" 元素出栈 """
pop = stack.pop()
pop: int = stack.pop()
print("出栈元素 pop =", pop)
print("出栈后 stack =", stack.to_list())
""" 获取栈的长度 """
size = stack.size()
size: int = stack.size()
print("栈的长度 size =", size)
""" 判断是否为空 """
is_empty = stack.is_empty()
is_empty: bool = stack.is_empty()
print("栈是否为空 =", is_empty)

View file

@ -4,19 +4,15 @@ Created Time: 2022-11-29
Author: Peng Chen (pengchzn@gmail.com)
"""
import os.path as osp
import sys
import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import *
from collections import deque
""" Driver Code """
if __name__ == "__main__":
""" 初始化双向队列 """
deque = deque()
deque: Deque[int] = collections.deque()
""" 元素入队 """
deque.append(2) # 添加至队尾
@ -27,23 +23,23 @@ if __name__ == "__main__":
print("双向队列 deque =", deque)
""" 访问元素 """
front = deque[0] # 队首元素
front: int = deque[0] # 队首元素
print("队首元素 front =", front)
rear = deque[-1] # 队尾元素
rear: int = deque[-1] # 队尾元素
print("队尾元素 rear =", rear)
""" 元素出队 """
pop_front = deque.popleft() # 队首元素出队
pop_front: int = deque.popleft() # 队首元素出队
print("队首出队元素 pop_front =", pop_front)
print("队首出队后 deque =", deque)
pop_rear = deque.pop() # 队尾元素出队
pop_rear: int = deque.pop() # 队尾元素出队
print("队尾出队元素 pop_rear =", pop_rear)
print("队尾出队后 deque =", deque)
""" 获取双向队列的长度 """
size = len(deque)
size: int = len(deque)
print("双向队列长度 size =", size)
""" 判断双向队列是否为空 """
is_empty = len(deque) == 0
is_empty: bool = len(deque) == 0
print("双向队列是否为空 =", is_empty)

View file

@ -4,36 +4,35 @@ Created Time: 2023-03-01
Author: Krahets (krahets@163.com)
"""
import os.path as osp
import sys
import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import *
class ListNode:
""" 双向链表结点 """
def __init__(self, val):
def __init__(self, val: int) -> None:
""" 构造方法 """
self.val = val
self.next = None # 后继结点引用(指针)
self.prev = None # 前驱结点引用(指针)
self.val: int = val
self.next: Optional[ListNode] = None # 后继结点引用(指针)
self.prev: Optional[ListNode] = None # 前驱结点引用(指针)
class LinkedListDeque:
""" 基于双向链表实现的双向队列 """
def __init__(self):
def __init__(self) -> None:
""" 构造方法 """
self.front, self.rear = None, None # 头结点 front ,尾结点 rear
self.__size = 0 # 双向队列的长度
self.front: Optional[ListNode] = None # 头结点 front
self.rear: Optional[ListNode] = None # 尾结点 rear
self.__size: int = 0 # 双向队列的长度
def size(self):
def size(self) -> int:
""" 获取双向队列的长度 """
return self.__size
def is_empty(self):
def is_empty(self) -> bool:
""" 判断双向队列是否为空 """
return self.size() == 0
def push(self, num, is_front):
def push(self, num: int, is_front: bool) -> None:
""" 入队操作 """
node = ListNode(num)
# 若链表为空,则令 front, rear 都指向 node
@ -53,33 +52,33 @@ class LinkedListDeque:
self.rear = node # 更新尾结点
self.__size += 1 # 更新队列长度
def push_first(self, num):
def push_first(self, num: int) -> None:
""" 队首入队 """
self.push(num, True)
def push_last(self, num):
def push_last(self, num: int) -> None:
""" 队尾入队 """
self.push(num, False)
def poll(self, is_front):
def poll(self, is_front: bool) -> int:
""" 出队操作 """
# 若队列为空,直接返回 None
if self.is_empty():
return None
# 队首出队操作
if is_front:
val = self.front.val # 暂存头结点值
val: int = self.front.val # 暂存头结点值
# 删除头结点
fnext = self.front.next
fnext: Optional[ListNode] = self.front.next
if fnext != None:
fnext.prev = None
self.front.next = None
self.front = fnext # 更新头结点
# 队尾出队操作
else:
val = self.rear.val # 暂存尾结点值
val: int = self.rear.val # 暂存尾结点值
# 删除尾结点
rprev = self.rear.prev
rprev: Optional[ListNode] = self.rear.prev
if rprev != None:
rprev.next = None
self.rear.prev = None
@ -87,26 +86,26 @@ class LinkedListDeque:
self.__size -= 1 # 更新队列长度
return val
def poll_first(self):
def poll_first(self) -> int:
""" 队首出队 """
return self.poll(True)
def poll_last(self):
def poll_last(self) -> int:
""" 队尾出队 """
return self.poll(False)
def peek_first(self):
def peek_first(self) -> int:
""" 访问队首元素 """
return None if self.is_empty() else self.front.val
def peek_last(self):
def peek_last(self) -> int:
""" 访问队尾元素 """
return None if self.is_empty() else self.rear.val
def to_array(self):
def to_array(self) -> List[int]:
""" 返回数组用于打印 """
node = self.front
res = [0] * self.size()
node: Optional[ListNode] = self.front
res: List[int] = [0] * self.size()
for i in range(self.size()):
res[i] = node.val
node = node.next
@ -123,9 +122,9 @@ if __name__ == "__main__":
print("双向队列 deque =", deque.to_array())
""" 访问元素 """
peek_first = deque.peek_first()
peek_first: int = deque.peek_first()
print("队首元素 peek_first =", peek_first)
peek_last = deque.peek_last()
peek_last: int = deque.peek_last()
print("队尾元素 peek_last =", peek_last)
""" 元素入队 """
@ -135,15 +134,15 @@ if __name__ == "__main__":
print("元素 1 队首入队后 deque =", deque.to_array())
""" 元素出队 """
poll_last = deque.poll_last()
poll_last: int = deque.poll_last()
print("队尾出队元素 =", poll_last, ",队尾出队后 deque =", deque.to_array())
poll_first = deque.poll_first()
poll_first: int = deque.poll_first()
print("队首出队元素 =", poll_first, ",队首出队后 deque =", deque.to_array())
""" 获取双向队列的长度 """
size = deque.size()
size: int = deque.size()
print("双向队列长度 size =", size)
""" 判断双向队列是否为空 """
is_empty = deque.is_empty()
is_empty: bool = deque.is_empty()
print("双向队列是否为空 =", is_empty)

View file

@ -4,9 +4,7 @@ Created Time: 2022-12-01
Author: Peng Chen (pengchzn@gmail.com)
"""
import os.path as osp
import sys
import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import *
@ -14,19 +12,19 @@ class LinkedListQueue:
""" 基于链表实现的队列 """
def __init__(self):
""" 构造方法 """
self.__front = None # 头结点 front
self.__rear = None # 尾结点 rear
self.__size = 0
self.__front: Optional[ListNode] = None # 头结点 front
self.__rear: Optional[ListNode] = None # 尾结点 rear
self.__size: int = 0
def size(self):
def size(self) -> int:
""" 获取队列的长度 """
return self.__size
def is_empty(self):
def is_empty(self) -> bool:
""" 判断队列是否为空 """
return not self.__front
def push(self, num):
def push(self, num: int) -> None:
""" 入队 """
# 尾结点后添加 num
node = ListNode(num)
@ -40,7 +38,7 @@ class LinkedListQueue:
self.__rear = node
self.__size += 1
def poll(self):
def poll(self) -> int:
""" 出队 """
num = self.peek()
# 删除头结点
@ -48,14 +46,14 @@ class LinkedListQueue:
self.__size -= 1
return num
def peek(self):
def peek(self) -> int:
""" 访问队首元素 """
if self.size() == 0:
print("队列为空")
return False
return self.__front.val
def to_list(self):
def to_list(self) -> List[int]:
""" 转化为列表用于打印 """
queue = []
temp = self.__front
@ -79,18 +77,18 @@ if __name__ == "__main__":
print("队列 queue =", queue.to_list())
""" 访问队首元素 """
peek = queue.peek()
peek: int = queue.peek()
print("队首元素 front =", peek)
""" 元素出队 """
pop_front = queue.poll()
pop_front: int = queue.poll()
print("出队元素 poll =", pop_front)
print("出队后 queue =", queue.to_list())
""" 获取队列的长度 """
size = queue.size()
size: int = queue.size()
print("队列长度 size =", size)
""" 判断队列是否为空 """
is_empty = queue.is_empty()
is_empty: bool = queue.is_empty()
print("队列是否为空 =", is_empty)

View file

@ -12,40 +12,40 @@ class LinkedListStack:
""" 基于链表实现的栈 """
def __init__(self):
""" 构造方法 """
self.__peek = None
self.__size = 0
self.__peek: Optional[ListNode] = None
self.__size: int = 0
def size(self):
def size(self) -> int:
""" 获取栈的长度 """
return self.__size
def is_empty(self):
def is_empty(self) -> bool:
""" 判断栈是否为空 """
return not self.__peek
def push(self, val):
def push(self, val: int) -> None:
""" 入栈 """
node = ListNode(val)
node.next = self.__peek
self.__peek = node
self.__size += 1
def pop(self):
def pop(self) -> int:
""" 出栈 """
num = self.peek()
num: int = self.peek()
self.__peek = self.__peek.next
self.__size -= 1
return num
def peek(self):
def peek(self) -> int:
""" 访问栈顶元素 """
# 判空处理
if not self.__peek: return None
return self.__peek.val
def to_list(self):
def to_list(self) -> List[int]:
""" 转化为列表用于打印 """
arr = []
arr: List[int] = []
node = self.__peek
while node:
arr.append(node.val)
@ -68,18 +68,18 @@ if __name__ == "__main__":
print("栈 stack =", stack.to_list())
""" 访问栈顶元素 """
peek = stack.peek()
peek: int = stack.peek()
print("栈顶元素 peek =", peek)
""" 元素出栈 """
pop = stack.pop()
pop: int = stack.pop()
print("出栈元素 pop =", pop)
print("出栈后 stack =", stack.to_list())
""" 获取栈的长度 """
size = stack.size()
size: int = stack.size()
print("栈的长度 size =", size)
""" 判断是否为空 """
is_empty = stack.is_empty()
is_empty: bool = stack.is_empty()
print("栈是否为空 =", is_empty)

View file

@ -4,9 +4,7 @@ Created Time: 2022-11-29
Author: Peng Chen (pengchzn@gmail.com)
"""
import os.path as osp
import sys
import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import *
@ -14,9 +12,9 @@ from modules import *
""" Driver Code """
if __name__ == "__main__":
""" 初始化队列 """
# 在 Python 中,我们一般将双向队列类 deque 看队列使用
# 虽然 queue.Queue() 是纯正的队列类,但不太好用,因此不建议
que = collections.deque()
# 在 Python 中,我们一般将双向队列类 deque 看队列使用
# 虽然 queue.Queue() 是纯正的队列类,但不太好用
que: Deque[int] = collections.deque()
""" 元素入队 """
que.append(1)
@ -27,18 +25,18 @@ if __name__ == "__main__":
print("队列 que =", que)
""" 访问队首元素 """
front = que[0];
print("队首元素 front =", front);
front: int = que[0]
print("队首元素 front =", front)
""" 元素出队 """
pop = que.popleft()
pop: int = que.popleft()
print("出队元素 pop =", pop)
print("出队后 que =", que)
""" 获取队列的长度 """
size = len(que)
size: int = len(que)
print("队列长度 size =", size)
""" 判断队列是否为空 """
is_empty = len(que) == 0
is_empty: bool = len(que) == 0
print("队列是否为空 =", is_empty)

View file

@ -13,7 +13,7 @@ from modules import *
if __name__ == "__main__":
""" 初始化栈 """
# Python 没有内置的栈类,可以把 list 当作栈来使用
stack = []
stack: List[int] = []
""" 元素入栈 """
stack.append(1)
@ -24,18 +24,18 @@ if __name__ == "__main__":
print("栈 stack =", stack)
""" 访问栈顶元素 """
peek = stack[-1]
peek: int = stack[-1]
print("栈顶元素 peek =", peek)
""" 元素出栈 """
pop = stack.pop()
pop: int = stack.pop()
print("出栈元素 pop =", pop)
print("出栈后 stack =", stack)
""" 获取栈的长度 """
size = len(stack)
size: int = len(stack)
print("栈的长度 size =", size)
""" 判断是否为空 """
is_empty = len(stack) == 0
is_empty: bool = len(stack) == 0
print("栈是否为空 =", is_empty)

View file

@ -12,7 +12,11 @@ class AVLTree:
""" AVL 树 """
def __init__(self, root: Optional[TreeNode] = None):
""" 构造方法 """
self.root = root
self.__root = root
@property
def root(self) -> Optional[TreeNode]:
return self.__root
def height(self, node: Optional[TreeNode]) -> int:
""" 获取结点高度 """
@ -34,7 +38,7 @@ class AVLTree:
# 结点平衡因子 = 左子树高度 - 右子树高度
return self.height(node.left) - self.height(node.right)
def __right_rotate(self, node: Optional[TreeNode]) -> TreeNode:
def __right_rotate(self, node: Optional[TreeNode]) -> Optional[TreeNode]:
""" 右旋操作 """
child = node.left
grand_child = child.right
@ -47,7 +51,7 @@ class AVLTree:
# 返回旋转后子树的根结点
return child
def __left_rotate(self, node: Optional[TreeNode]) -> TreeNode:
def __left_rotate(self, node: Optional[TreeNode]) -> Optional[TreeNode]:
""" 左旋操作 """
child = node.right
grand_child = child.left
@ -60,7 +64,7 @@ class AVLTree:
# 返回旋转后子树的根结点
return child
def __rotate(self, node: Optional[TreeNode]) -> TreeNode:
def __rotate(self, node: Optional[TreeNode]) -> Optional[TreeNode]:
""" 执行旋转操作,使该子树重新恢复平衡 """
# 获取结点 node 的平衡因子
balance_factor = self.balance_factor(node)
@ -87,8 +91,8 @@ class AVLTree:
def insert(self, val) -> TreeNode:
""" 插入结点 """
self.root = self.__insert_helper(self.root, val)
return self.root
self.__root = self.__insert_helper(self.__root, val)
return self.__root
def __insert_helper(self, node: Optional[TreeNode], val: int) -> TreeNode:
""" 递归插入结点(辅助方法)"""
@ -107,10 +111,10 @@ class AVLTree:
# 2. 执行旋转操作,使该子树重新恢复平衡
return self.__rotate(node)
def remove(self, val: int):
def remove(self, val: int) -> Optional[TreeNode]:
""" 删除结点 """
root = self.__remove_helper(self.root, val)
return root
self.__root = self.__remove_helper(self.__root, val)
return self.__root
def __remove_helper(self, node: Optional[TreeNode], val: int) -> Optional[TreeNode]:
""" 递归删除结点(辅助方法) """
@ -148,9 +152,9 @@ class AVLTree:
node = node.left
return node
def search(self, val: int):
def search(self, val: int) -> Optional[TreeNode]:
""" 查找结点 """
cur = self.root
cur = self.__root
# 循环查找,越过叶结点后跳出
while cur is not None:
# 目标结点在 cur 的右子树中

View file

@ -22,7 +22,7 @@ class BinarySearchTree:
return None
# 将数组中间结点作为根结点
mid = (start_index + end_index) // 2
mid: int = (start_index + end_index) // 2
root = TreeNode(nums[mid])
# 递归建立左子树和右子树
root.left = self.build_tree(nums=nums, start_index=start_index, end_index=mid - 1)
@ -35,7 +35,7 @@ class BinarySearchTree:
def search(self, num: int) -> Optional[TreeNode]:
""" 查找结点 """
cur = self.root
cur: Optional[TreeNode] = self.__root
# 循环查找,越过叶结点后跳出
while cur is not None:
# 目标结点在 cur 的右子树中
@ -51,13 +51,12 @@ class BinarySearchTree:
def insert(self, num: int) -> Optional[TreeNode]:
""" 插入结点 """
root = self.root
# 若树为空,直接提前返回
if root is None:
if self.__root is None:
return None
# 循环查找,越过叶结点后跳出
cur, pre = root, None
cur, pre = self.__root, None
while cur is not None:
# 找到重复结点,直接返回
if cur.val == num:
@ -80,13 +79,12 @@ class BinarySearchTree:
def remove(self, num: int) -> Optional[TreeNode]:
""" 删除结点 """
root = self.root
# 若树为空,直接提前返回
if root is None:
if self.__root is None:
return None
# 循环查找,越过叶结点后跳出
cur, pre = root, None
cur, pre = self.__root, None
while cur is not None:
# 找到待删除结点,跳出循环
if cur.val == num:
@ -112,8 +110,8 @@ class BinarySearchTree:
# 子结点数量 = 2
else:
# 获取中序遍历中 cur 的下一个结点
nex = self.get_inorder_next(cur.right)
tmp = nex.val
nex: TreeNode = self.get_inorder_next(cur.right)
tmp: int = nex.val
# 递归删除结点 nex
self.remove(nex.val)
# 将 nex 的值复制给 cur
@ -143,7 +141,7 @@ if __name__ == "__main__":
print("\n查找到的结点对象为: {},结点值 = {}".format(node, node.val))
# 插入结点
ndoe = bst.insert(16)
node = bst.insert(16)
print("\n插入结点 16 后,二叉树为\n")
print_tree(bst.root)

View file

@ -9,20 +9,20 @@ sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import *
def level_order(root: Optional[TreeNode]):
def level_order(root: Optional[TreeNode]) -> List[int]:
""" 层序遍历 """
# 初始化队列,加入根结点
queue = collections.deque()
queue: Deque[TreeNode] = collections.deque()
queue.append(root)
# 初始化一个列表,用于保存遍历序列
res = []
res: List[int] = []
while queue:
node = queue.popleft() # 队列出队
res.append(node.val) # 保存结点值
node: TreeNode = queue.popleft() # 队列出队
res.append(node.val) # 保存结点值
if node.left is not None:
queue.append(node.left) # 左子结点入队
queue.append(node.left) # 左子结点入队
if node.right is not None:
queue.append(node.right) # 右子结点入队
queue.append(node.right) # 右子结点入队
return res
@ -30,11 +30,11 @@ def level_order(root: Optional[TreeNode]):
if __name__ == "__main__":
# 初始化二叉树
# 这里借助了一个从数组直接生成二叉树的函数
root = list_to_tree(arr=[1, 2, 3, 4, 5, 6, 7])
root: TreeNode = list_to_tree(arr=[1, 2, 3, 4, 5, 6, 7])
print("\n初始化二叉树\n")
print_tree(root)
# 层序遍历
res = level_order(root)
res: List[int] = level_order(root)
print("\n层序遍历的结点打印序列 = ", res)
assert res == [1, 2, 3, 4, 5, 6, 7]

View file

@ -9,7 +9,7 @@ sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import *
def pre_order(root: Optional[TreeNode]):
def pre_order(root: Optional[TreeNode]) -> None:
""" 前序遍历 """
if root is None:
return
@ -18,7 +18,7 @@ def pre_order(root: Optional[TreeNode]):
pre_order(root=root.left)
pre_order(root=root.right)
def in_order(root: Optional[TreeNode]):
def in_order(root: Optional[TreeNode]) -> None:
""" 中序遍历 """
if root is None:
return
@ -27,7 +27,7 @@ def in_order(root: Optional[TreeNode]):
res.append(root.val)
in_order(root=root.right)
def post_order(root: Optional[TreeNode]):
def post_order(root: Optional[TreeNode]) -> None:
""" 后序遍历 """
if root is None:
return
@ -36,7 +36,6 @@ def post_order(root: Optional[TreeNode]):
post_order(root=root.right)
res.append(root.val)
res = []
""" Driver Code """
if __name__ == "__main__":
@ -47,7 +46,7 @@ if __name__ == "__main__":
print_tree(root)
# 前序遍历
res.clear()
res = []
pre_order(root)
print("\n前序遍历的结点打印序列 = ", res)
assert res == [1, 2, 4, 5, 3, 6, 7]

View file

@ -5,7 +5,7 @@ import queue
import random
import functools
import collections
from typing import Optional, List, Dict, DefaultDict, OrderedDict, Set, Deque
from typing import Optional, Tuple, 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 .vertex import Vertex, vals_to_vets, vets_to_vals

View file

@ -5,36 +5,26 @@ Author: Krahets (krahets@163.com)
"""
import collections
from typing import List, Deque, Optional
class TreeNode:
"""Definition for a binary tree node
"""
def __init__(self, val=0, left=None, right=None):
self.val = val # 结点值
self.height = 0 # 结点高度
self.left = left # 左子结点引用
self.right = right # 右子结点引用
""" Definition for a binary tree node """
def __init__(self, val: int = 0, left: Optional['TreeNode'] = None, right: Optional['TreeNode'] = None):
self.val: int = val # 结点值
self.height: int = 0 # 结点高度
self.left: Optional[TreeNode] = left # 左子结点引用
self.right: Optional[TreeNode] = right # 右子结点引用
def __str__(self):
val = self.val
left_node_val = self.left.val if self.left else None
right_node_val = self.right.val if self.right else None
return "<TreeNode: {}, leftTreeNode: {}, rightTreeNode: {}>".format(val, left_node_val, right_node_val)
__repr__ = __str__
def list_to_tree(arr):
"""Generate a binary tree with a list
"""
def list_to_tree(arr: List[int]) -> Optional[TreeNode]:
""" Generate a binary tree with a list """
if not arr:
return None
i = 0
i: int = 0
root = TreeNode(arr[0])
queue = collections.deque([root])
queue: Deque[TreeNode] = collections.deque([root])
while queue:
node = queue.popleft()
node: TreeNode = queue.popleft()
i += 1
if i >= len(arr): break
if arr[i] != None:
@ -48,15 +38,14 @@ def list_to_tree(arr):
return root
def tree_to_list(root):
"""Serialize a tree into an array
"""
def tree_to_list(root: Optional[TreeNode]) -> List[int]:
""" Serialize a tree into an array """
if not root: return []
queue = collections.deque()
queue: Deque[TreeNode] = collections.deque()
queue.append(root)
res = []
res: List[int] = []
while queue:
node = queue.popleft()
node: Optional[TreeNode] = queue.popleft()
if node:
res.append(node.val)
queue.append(node.left)
@ -64,13 +53,12 @@ def tree_to_list(root):
else: res.append(None)
return res
def get_tree_node(root, val):
"""Get a tree node with specific value in a binary tree
"""
def get_tree_node(root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
""" Get a tree node with specific value in a binary tree """
if not root:
return
if root.val == val:
return root
left = get_tree_node(root.left, val)
right = get_tree_node(root.right, val)
left: Optional[TreeNode] = get_tree_node(root.left, val)
right: Optional[TreeNode] = get_tree_node(root.right, val)
return left if left else right

View file

@ -4,22 +4,16 @@ Created Time: 2021-12-11
Author: Krahets (krahets@163.com)
"""
from typing import List, Optional
class ListNode:
"""Definition for a singly-linked list node
"""
def __init__(self, val=0, next=None):
self.val = val
self.next = next
""" Definition for a singly-linked list node """
def __init__(self, val: int):
self.val: int = val # 结点值
self.next: Optional[ListNode] = None # 后继结点引用
def list_to_linked_list(arr):
"""Generate a linked list with a list
Args:
arr ([type]): [description]
Returns:
[type]: [description]
"""
def list_to_linked_list(arr: List[int]) -> Optional[ListNode]:
""" Generate a linked list with a list """
dum = head = ListNode(0)
for a in arr:
node = ListNode(a)
@ -27,31 +21,16 @@ def list_to_linked_list(arr):
head = head.next
return dum.next
def linked_list_to_list(head):
"""Serialize a linked list into an array
Args:
head ([type]): [description]
Returns:
[type]: [description]
"""
arr = []
def linked_list_to_list(head: Optional[ListNode]) -> List[int]:
""" Serialize a linked list into an array """
arr: List[int] = []
while head:
arr.append(head.val)
head = head.next
return arr
def get_list_node(head, val):
"""Get a list node with specific value from a linked list
Args:
head ([type]): [description]
val ([type]): [description]
Returns:
[type]: [description]
"""
def get_list_node(head: Optional[ListNode], val: int) -> Optional[ListNode]:
""" Get a list node with specific value from a linked list """
while head and head.val != val:
head = head.next
return head

View file

@ -4,57 +4,48 @@ Created Time: 2021-12-11
Author: Krahets (krahets@163.com), msk397 (machangxinq@gmail.com)
"""
from .binary_tree import TreeNode, tree_to_list, list_to_tree
from .binary_tree import TreeNode, list_to_tree
from .linked_list import ListNode, linked_list_to_list
def print_matrix(mat):
"""Print a matrix
from typing import List, Optional, Dict
Args:
mat ([type]): [description]
"""
pstr = []
def print_matrix(mat: List[List[int]]) -> None:
""" Print a matrix """
s: List[str] = []
for arr in mat:
pstr.append(' ' + str(arr))
s.append(' ' + str(arr))
print('[\n' + ',\n'.join(pstr) + '\n]')
print('[\n' + ',\n'.join(s) + '\n]')
def print_linked_list(head):
"""Print a linked list
Args:
head ([type]): [description]
"""
arr = linked_list_to_list(head)
def print_linked_list(head: Optional[ListNode]) -> None:
""" Print a linked list """
arr: List[int] = linked_list_to_list(head)
print(' -> '.join([str(a) for a in arr]))
class Trunk:
def __init__(self, prev=None, str=None):
self.prev = prev
self.str = str
def show_trunks(p):
def __init__(self, prev: Optional['Trunk'] = None, string: Optional[str] = None) -> None:
self.prev: Optional[Trunk] = prev
self.str: Optional[str] = string
def show_trunks(p: Optional[Trunk]) -> None:
if p is None:
return
show_trunks(p.prev)
print(p.str, end='')
def print_tree(root, prev=None, is_left=False):
"""Print a binary tree
This tree printer is borrowed from TECHIE DELIGHT
https://www.techiedelight.com/c-program-print-binary-tree/
Args:
root ([type]): [description]
prev ([type], optional): [description]. Defaults to None.
is_left (bool, optional): [description]. Defaults to False.
def print_tree(root: Optional[TreeNode], prev: Optional[Trunk] = None, is_left: bool = False) -> None:
"""
Print a binary tree
This tree printer is borrowed from TECHIE DELIGHT
https://www.techiedelight.com/c-program-print-binary-tree/
"""
if root is None:
return
prev_str = ' '
prev_str: str = ' '
trunk = Trunk(prev, prev_str)
print_tree(root.right, trunk, True)
if prev is None:
trunk.str = '———'
elif is_left:
@ -63,7 +54,7 @@ def print_tree(root, prev=None, is_left=False):
else:
trunk.str = '\———'
prev.str = prev_str
show_trunks(trunk)
print(' ' + str(root.val))
if prev:
@ -71,17 +62,14 @@ def print_tree(root, prev=None, is_left=False):
trunk.str = ' |'
print_tree(root.left, trunk, False)
def print_dict(d):
"""Print a dict
Args:
d ([type]): [description]
"""
for key, value in d.items():
def print_dict(mapp: Dict) -> None:
""" Print a dict """
for key, value in mapp.items():
print(key, '->', value)
def print_heap(heap):
print("堆的数组表示:", heap);
print("堆的树状表示:");
root = list_to_tree(heap)
print_tree(root);
def print_heap(heap: List[int]) -> None:
""" Print a heap both in array and tree representations """
print("堆的数组表示:", heap)
print("堆的树状表示:")
root: Optional[TreeNode] = list_to_tree(heap)
print_tree(root)

View file

@ -34,8 +34,8 @@
```python title="array.py"
""" 初始化数组 """
arr = [0] * 5 # [ 0, 0, 0, 0, 0 ]
nums = [1, 3, 2, 5, 4]
arr: List[int] = [0] * 5 # [ 0, 0, 0, 0, 0 ]
nums: List[int] = [1, 3, 2, 5, 4]
```
=== "Go"

View file

@ -37,9 +37,9 @@
```python title=""
""" 链表结点类 """
class ListNode:
def __init__(self, x):
self.val = x # 结点值
self.next = None # 指向下一结点的指针(引用)
def __init__(self, val: int):
self.val: int = val # 结点值
self.next: Optional[ListNode] = None # 指向下一结点的指针(引用)
```
=== "Go"
@ -609,10 +609,10 @@
```python title=""
""" 双向链表结点类 """
class ListNode:
def __init__(self, x):
self.val = x # 结点值
self.next = None # 指向后继结点的指针(引用)
self.prev = None # 指向前驱结点的指针(引用)
def __init__(self, val: int):
self.val: int = val # 结点值
self.next: Optional[ListNode] = None # 指向后继结点的指针(引用)
self.prev: Optional[ListNode] = None # 指向前驱结点的指针(引用)
```
=== "Go"

View file

@ -35,9 +35,9 @@
```python title="list.py"
""" 初始化列表 """
# 无初始值
list1 = []
list1: List[int] = []
# 有初始值
list = [1, 3, 2, 5, 4]
list: List[int] = [1, 3, 2, 5, 4]
```
=== "Go"
@ -132,7 +132,7 @@
```python title="list.py"
""" 访问元素 """
num = list[1] # 访问索引 1 处的元素
num: int = list[1] # 访问索引 1 处的元素
""" 更新元素 """
list[1] = 0 # 将索引 1 处的元素更新为 0
@ -430,12 +430,12 @@
```python title="list.py"
""" 通过索引遍历列表 """
count = 0
count: int = 0
for i in range(len(list)):
count += 1
""" 直接遍历列表元素 """
count = 0
count: int = 0
for n in list:
count += 1
```
@ -568,7 +568,7 @@
```python title="list.py"
""" 拼接两个列表 """
list1 = [6, 8, 7, 10, 9]
list1: List[int] = [6, 8, 7, 10, 9]
list += list1 # 将列表 list1 拼接到 list 之后
```

View file

@ -66,8 +66,8 @@
int algorithm(int n) { // 输入数据
const int a = 0; // 暂存数据(常量)
int b = 0; // 暂存数据(变量)
Node* node = new Node(0); // 暂存数据(对象)
int c = func(); // 栈帧空间(调用函数)
Node* node = new Node(0); // 暂存数据(对象)
int c = func(); // 栈帧空间(调用函数)
return a + b + c; // 输出数据
}
```
@ -77,20 +77,20 @@
```python title=""
""" 类 """
class Node:
def __init__(self, x):
self.val = x # 结点值
self.next = None # 指向下一结点的指针(引用)
def __init__(self, x: int):
self.val: int = x # 结点值
self.next: Optional[Node] = None # 指向下一结点的指针(引用)
""" 函数 """
def function():
def function() -> int:
# do something...
return 0
def algorithm(n): # 输入数据
b = 0 # 暂存数据(变量)
node = Node(0) # 暂存数据(对象)
c = function() # 栈帧空间(调用函数)
return a + b + c # 输出数据
def algorithm(n) -> int: # 输入数据
b: int = 0 # 暂存数据(变量)
node = Node(0) # 暂存数据(对象)
c: int = function() # 栈帧空间(调用函数)
return a + b + c # 输出数据
```
=== "Go"
@ -280,11 +280,11 @@
=== "Python"
```python title=""
def algorithm(n):
a = 0 # O(1)
b = [0] * 10000 # O(1)
def algorithm(n: int) -> None:
a: int = 0 # O(1)
b: List[int] = [0] * 10000 # O(1)
if n > 10:
nums = [0] * n # O(n)
nums: List[int] = [0] * n # O(n)
```
=== "Go"
@ -408,17 +408,17 @@
=== "Python"
```python title=""
def function():
def function() -> int:
# do something
return 0
""" 循环 O(1) """
def loop(n):
def loop(n: int) -> None:
for _ in range(n):
function()
""" 递归 O(n) """
def recur(n):
def recur(n: int) -> int:
if n == 1: return
return recur(n - 1)
```

View file

@ -48,7 +48,7 @@ $$
```python title=""
# 在某运行平台下
def algorithm(n):
def algorithm(n: int) -> None:
a = 2 # 1 ns
a = a + 1 # 1 ns
a = a * 2 # 10 ns
@ -213,14 +213,14 @@ $$
```python title=""
# 算法 A 时间复杂度:常数阶
def algorithm_A(n):
def algorithm_A(n: int) -> None:
print(0)
# 算法 B 时间复杂度:线性阶
def algorithm_B(n):
def algorithm_B(n: int) -> None:
for _ in range(n):
print(0)
# 算法 C 时间复杂度:常数阶
def algorithm_C(n):
def algorithm_C(n: int) -> None:
for _ in range(1000000):
print(0)
```
@ -414,8 +414,8 @@ $$
=== "Python"
```python title=""
def algorithm(n):
a = 1 # +1
def algorithm(n: int) -> None:
a: int = 1 # +1
a = a + 1 # +1
a = a * 2 # +1
# 循环 n 次
@ -605,9 +605,9 @@ $$
=== "Python"
```python title=""
def algorithm(n):
a = 1 # +0技巧 1
a = a + n # +0技巧 1
def algorithm(n: int) -> None:
a: int = 1 # +0技巧 1
a = a + n # +0技巧 1
# +n技巧 2
for i in range(5 * n + 1):
print(0)

View file

@ -81,7 +81,7 @@
```python title="hash_map.py"
""" 初始化哈希表 """
mapp = {}
mapp: Dict = {}
""" 添加操作 """
# 在哈希表中添加键值对 (key, value)
@ -93,7 +93,7 @@
""" 查询操作 """
# 向哈希表输入键 key ,得到值 value
name = mapp[15937]
name: str = mapp[15937]
""" 删除操作 """
# 在哈希表中删除键值对 (key, value)

View file

@ -133,7 +133,7 @@
heapq.heappush(max_heap, flag * 4)
""" 获取堆顶元素 """
peek = flag * max_heap[0] # 5
peek: int = flag * max_heap[0] # 5
""" 堆顶元素出堆 """
# 出堆元素会形成一个从大到小的序列
@ -144,13 +144,13 @@
val = flag * heapq.heappop(max_heap) # 1
""" 获取堆大小 """
size = len(max_heap)
size: int = len(max_heap)
""" 判断堆是否为空 """
is_empty = not max_heap
is_empty: bool = not max_heap
""" 输入列表并建堆 """
min_heap = [1, 3, 2, 5, 4]
min_heap: List[int] = [1, 3, 2, 5, 4]
heapq.heapify(min_heap)
```

View file

@ -64,43 +64,9 @@
=== "C++"
```cpp title="merge_sort.cpp"
/* 合并左子数组和右子数组 */
// 左子数组区间 [left, mid]
// 右子数组区间 [mid + 1, right]
void merge(vector<int>& nums, int left, int mid, int right) {
// 初始化辅助数组
vector<int> tmp(nums.begin() + left, nums.begin() + right + 1);
// 左子数组的起始索引和结束索引
int leftStart = left - left, leftEnd = mid - left;
// 右子数组的起始索引和结束索引
int rightStart = mid + 1 - left, rightEnd = right - left;
// i, j 分别指向左子数组、右子数组的首元素
int i = leftStart, j = rightStart;
// 通过覆盖原数组 nums 来合并左子数组和右子数组
for (int k = left; k <= right; k++) {
// 若“左子数组已全部合并完”,则选取右子数组元素,并且 j++
if (i > leftEnd)
nums[k] = tmp[j++];
// 否则,若“右子数组已全部合并完”或“左子数组元素 <= 右子数组元素”,则选取左子数组元素,并且 i++
else if (j > rightEnd || tmp[i] <= tmp[j])
nums[k] = tmp[i++];
// 否则,若“左右子数组都未全部合并完”且“左子数组元素 > 右子数组元素”,则选取右子数组元素,并且 j++
else
nums[k] = tmp[j++];
}
}
[class]{}-[func]{merge}
/* 归并排序 */
void mergeSort(vector<int>& nums, int left, int right) {
// 终止条件
if (left >= right) return; // 当子数组长度为 1 时终止递归
// 划分阶段
int mid = (left + right) / 2; // 计算中点
mergeSort(nums, left, mid); // 递归左子数组
mergeSort(nums, mid + 1, right); // 递归右子数组
// 合并阶段
merge(nums, left, mid, right);
}
[class]{}-[func]{mergeSort}
```
=== "Python"
@ -114,139 +80,25 @@
=== "Go"
```go title="merge_sort.go"
/*
合并左子数组和右子数组
左子数组区间 [left, mid]
右子数组区间 [mid + 1, right]
*/
func merge(nums []int, left, mid, right int) {
// 初始化辅助数组 借助 copy 模块
tmp := make([]int, right-left+1)
for i := left; i <= right; i++ {
tmp[i-left] = nums[i]
}
// 左子数组的起始索引和结束索引
leftStart, leftEnd := left-left, mid-left
// 右子数组的起始索引和结束索引
rightStart, rightEnd := mid+1-left, right-left
// i, j 分别指向左子数组、右子数组的首元素
i, j := leftStart, rightStart
// 通过覆盖原数组 nums 来合并左子数组和右子数组
for k := left; k <= right; k++ {
// 若“左子数组已全部合并完”,则选取右子数组元素,并且 j++
if i > leftEnd {
nums[k] = tmp[j]
j++
// 否则,若“右子数组已全部合并完”或“左子数组元素 <= 右子数组元素”,则选取左子数组元素,并且 i++
} else if j > rightEnd || tmp[i] <= tmp[j] {
nums[k] = tmp[i]
i++
// 否则,若“左右子数组都未全部合并完”且“左子数组元素 > 右子数组元素”,则选取右子数组元素,并且 j++
} else {
nums[k] = tmp[j]
j++
}
}
}
[class]{}-[func]{merge}
func mergeSort(nums []int, left, right int) {
// 终止条件
if left >= right {
return
}
// 划分阶段
mid := (left + right) / 2
mergeSort(nums, left, mid)
mergeSort(nums, mid+1, right)
// 合并阶段
merge(nums, left, mid, right)
}
[class]{}-[func]{mergeSort}
```
=== "JavaScript"
```javascript title="merge_sort.js"
/* 合并左子数组和右子数组 */
// 左子数组区间 [left, mid]
// 右子数组区间 [mid + 1, right]
function merge(nums, left, mid, right) {
// 初始化辅助数组
let tmp = nums.slice(left, right + 1);
// 左子数组的起始索引和结束索引
let leftStart = left - left, leftEnd = mid - left;
// 右子数组的起始索引和结束索引
let rightStart = mid + 1 - left, rightEnd = right - left;
// i, j 分别指向左子数组、右子数组的首元素
let i = leftStart, j = rightStart;
// 通过覆盖原数组 nums 来合并左子数组和右子数组
for (let k = left; k <= right; k++) {
// 若“左子数组已全部合并完”,则选取右子数组元素,并且 j++
if (i > leftEnd) {
nums[k] = tmp[j++];
// 否则,若“右子数组已全部合并完”或“左子数组元素 <= 右子数组元素”,则选取左子数组元素,并且 i++
} else if (j > rightEnd || tmp[i] <= tmp[j]) {
nums[k] = tmp[i++];
// 否则,若“左右子数组都未全部合并完”且“左子数组元素 > 右子数组元素”,则选取右子数组元素,并且 j++
} else {
nums[k] = tmp[j++];
}
}
}
/* 归并排序 */
function mergeSort(nums, left, right) {
// 终止条件
if (left >= right) return; // 当子数组长度为 1 时终止递归
// 划分阶段
let mid = Math.floor((left + right) / 2); // 计算中点
mergeSort(nums, left, mid); // 递归左子数组
mergeSort(nums, mid + 1, right); // 递归右子数组
// 合并阶段
merge(nums, left, mid, right);
}
[class]{}-[func]{merge}
[class]{}-[func]{mergeSort}
```
=== "TypeScript"
```typescript title="merge_sort.ts"
/* 合并左子数组和右子数组 */
// 左子数组区间 [left, mid]
// 右子数组区间 [mid + 1, right]
function merge(nums: number[], left: number, mid: number, right: number): void {
// 初始化辅助数组
let tmp = nums.slice(left, right + 1);
// 左子数组的起始索引和结束索引
let leftStart = left - left, leftEnd = mid - left;
// 右子数组的起始索引和结束索引
let rightStart = mid + 1 - left, rightEnd = right - left;
// i, j 分别指向左子数组、右子数组的首元素
let i = leftStart, j = rightStart;
// 通过覆盖原数组 nums 来合并左子数组和右子数组
for (let k = left; k <= right; k++) {
// 若“左子数组已全部合并完”,则选取右子数组元素,并且 j++
if (i > leftEnd) {
nums[k] = tmp[j++];
// 否则,若“右子数组已全部合并完”或“左子数组元素 <= 右子数组元素”,则选取左子数组元素,并且 i++
} else if (j > rightEnd || tmp[i] <= tmp[j]) {
nums[k] = tmp[i++];
// 否则,若“左右子数组都未全部合并完”且“左子数组元素 > 右子数组元素”,则选取右子数组元素,并且 j++
} else {
nums[k] = tmp[j++];
}
}
}
[class]{}-[func]{merge}
/* 归并排序 */
function mergeSort(nums: number[], left: number, right: number): void {
// 终止条件
if (left >= right) return; // 当子数组长度为 1 时终止递归
// 划分阶段
let mid = Math.floor((left + right) / 2); // 计算中点
mergeSort(nums, left, mid); // 递归左子数组
mergeSort(nums, mid + 1, right); // 递归右子数组
// 合并阶段
merge(nums, left, mid, right);
}
[class]{}-[func]{mergeSort}
```
=== "C"
@ -266,62 +118,17 @@
=== "Swift"
```swift title="merge_sort.swift"
/**
* 合并左子数组和右子数组
* 左子数组区间 [left, mid]
* 右子数组区间 [mid + 1, right]
*/
func merge(nums: inout [Int], left: Int, mid: Int, right: Int) {
// 初始化辅助数组
let tmp = Array(nums[left ..< (right + 1)])
// 左子数组的起始索引和结束索引
let leftStart = left - left
let leftEnd = mid - left
// 右子数组的起始索引和结束索引
let rightStart = mid + 1 - left
let rightEnd = right - left
// i, j 分别指向左子数组、右子数组的首元素
var i = leftStart
var j = rightStart
// 通过覆盖原数组 nums 来合并左子数组和右子数组
for k in left ... right {
// 若“左子数组已全部合并完”,则选取右子数组元素,并且 j++
if i > leftEnd {
nums[k] = tmp[j]
j += 1
}
// 否则,若“右子数组已全部合并完”或“左子数组元素 <= 右子数组元素”,则选取左子数组元素,并且 i++
else if j > rightEnd || tmp[i] <= tmp[j] {
nums[k] = tmp[i]
i += 1
}
// 否则,若“左右子数组都未全部合并完”且“左子数组元素 > 右子数组元素”,则选取右子数组元素,并且 j++
else {
nums[k] = tmp[j]
j += 1
}
}
}
[class]{}-[func]{merge}
/* 归并排序 */
func mergeSort(nums: inout [Int], left: Int, right: Int) {
// 终止条件
if left >= right { // 当子数组长度为 1 时终止递归
return
}
// 划分阶段
let mid = (left + right) / 2 // 计算中点
mergeSort(nums: &nums, left: left, right: mid) // 递归左子数组
mergeSort(nums: &nums, left: mid + 1, right: right) // 递归右子数组
// 合并阶段
merge(nums: &nums, left: left, mid: mid, right: right)
}
[class]{}-[func]{mergeSort}
```
=== "Zig"
```zig title="merge_sort.zig"
[class]{}-[func]{merge}
[class]{}-[func]{mergeSort}
```
下面重点解释一下合并方法 `merge()` 的流程:

View file

@ -83,7 +83,7 @@
```python title="deque.py"
""" 初始化双向队列 """
deque = deque()
deque: Deque[int] = collections.deque()
""" 元素入队 """
deque.append(2) # 添加至队尾
@ -93,18 +93,18 @@
deque.appendleft(1)
""" 访问元素 """
front = deque[0] # 队首元素
rear = deque[-1] # 队尾元素
front: int = deque[0] # 队首元素
rear: int = deque[-1] # 队尾元素
""" 元素出队 """
pop_front = deque.popleft() # 队首元素出队
pop_rear = deque.pop() # 队尾元素出队
pop_front: int = deque.popleft() # 队首元素出队
pop_rear: int = deque.pop() # 队尾元素出队
""" 获取双向队列的长度 """
size = len(deque)
size: int = len(deque)
""" 判断双向队列是否为空 """
is_empty = len(deque) == 0
is_empty: bool = len(deque) == 0
```
=== "Go"

View file

@ -80,7 +80,7 @@
""" 初始化队列 """
# 在 Python 中,我们一般将双向队列类 deque 看作队列使用
# 虽然 queue.Queue() 是纯正的队列类,但不太好用,因此不建议
que = collections.deque()
que: Deque[int] = collections.deque()
""" 元素入队 """
que.append(1)
@ -90,16 +90,16 @@
que.append(4)
""" 访问队首元素 """
front = que[0];
front: int = que[0];
""" 元素出队 """
pop = que.popleft()
pop: int = que.popleft()
""" 获取队列的长度 """
size = len(que)
size: int = len(que)
""" 判断队列是否为空 """
is_empty = len(que) == 0
is_empty: bool = len(que) == 0
```
=== "Go"

View file

@ -81,7 +81,7 @@
```python title="stack.py"
""" 初始化栈 """
# Python 没有内置的栈类,可以把 List 当作栈来使用
stack = []
stack: List[int] = []
""" 元素入栈 """
stack.append(1)
@ -91,16 +91,16 @@
stack.append(4)
""" 访问栈顶元素 """
peek = stack[-1]
peek: int = stack[-1]
""" 元素出栈 """
pop = stack.pop()
pop: int = stack.pop()
""" 获取栈的长度 """
size = len(stack)
size: int = len(stack)
""" 判断是否为空 """
is_empty = len(stack) == 0
is_empty: bool = len(stack) == 0
```
=== "Go"

View file

@ -27,9 +27,9 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit
```java title=""
/* AVL 树结点类 */
class TreeNode {
public int val; // 结点值
public int height; // 结点高度
public TreeNode left; // 左子结点
public int val; // 结点值
public int height; // 结点高度
public TreeNode left; // 左子结点
public TreeNode right; // 右子结点
public TreeNode(int x) { val = x; }
}
@ -40,10 +40,10 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit
```cpp title=""
/* AVL 树结点类 */
struct TreeNode {
int val{}; // 结点值
int height = 0; // 结点高度
TreeNode *left{}; // 左子结点
TreeNode *right{}; // 右子结点
int val{}; // 结点值
int height = 0; // 结点高度
TreeNode *left{}; // 左子结点
TreeNode *right{}; // 右子结点
TreeNode() = default;
explicit TreeNode(int x) : val(x){}
};
@ -54,11 +54,11 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit
```python title=""
""" AVL 树结点类 """
class TreeNode:
def __init__(self, val=None, left=None, right=None):
self.val = val # 结点值
self.height = 0 # 结点高度
self.left = left # 左子结点引用
self.right = right # 右子结点引用
def __init__(self, val: int):
self.val: int = val # 结点值
self.height: int = 0 # 结点高度
self.left: Optional[TreeNode] = None # 左子结点引用
self.right: Optional[TreeNode] = None # 右子结点引用
```
=== "Go"

View file

@ -5,7 +5,7 @@
=== "Java"
```java title=""
/* 链表结点类 */
/* 二叉树结点类 */
class TreeNode {
int val; // 结点值
TreeNode left; // 左子结点指针
@ -17,7 +17,7 @@
=== "C++"
```cpp title=""
/* 链表结点结构体 */
/* 二叉树结点结构体 */
struct TreeNode {
int val; // 结点值
TreeNode *left; // 左子结点指针
@ -29,18 +29,18 @@
=== "Python"
```python title=""
""" 链表结点类 """
""" 二叉树结点类 """
class TreeNode:
def __init__(self, val=None, left=None, right=None):
self.val = val # 结点值
self.left = left # 左子结点指针
self.right = right # 右子结点指针
def __init__(self, val: int):
self.val: int = val # 结点值
self.left: Optional[TreeNode] = None # 左子结点指针
self.right: Optional[TreeNode] = None # 右子结点指针
```
=== "Go"
```go title=""
/* 链表结点结构体 */
/* 二叉树结点结构体 */
type TreeNode struct {
Val int
Left *TreeNode
@ -59,7 +59,7 @@
=== "JavaScript"
```javascript title=""
/* 链表结点类 */
/* 二叉树结点类 */
function TreeNode(val, left, right) {
this.val = (val === undefined ? 0 : val); // 结点值
this.left = (left === undefined ? null : left); // 左子结点指针
@ -70,7 +70,7 @@
=== "TypeScript"
```typescript title=""
/* 链表结点类 */
/* 二叉树结点类 */
class TreeNode {
val: number;
left: TreeNode | null;
@ -93,7 +93,7 @@
=== "C#"
```csharp title=""
/* 链表结点类 */
/* 二叉树结点类 */
class TreeNode {
int val; // 结点值
TreeNode? left; // 左子结点指针
@ -105,7 +105,7 @@
=== "Swift"
```swift title=""
/* 链表结点类 */
/* 二叉树结点类 */
class TreeNode {
var val: Int // 结点值
var left: TreeNode? // 左子结点指针