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

View File

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

View File

@ -12,31 +12,31 @@ class MyList:
""" 列表类简易实现 """ """ 列表类简易实现 """
def __init__(self): def __init__(self):
""" 构造方法 """ """ 构造方法 """
self.__capacity = 10 # 列表容量 self.__capacity: int = 10 # 列表容量
self.__nums = [0] * self.__capacity # 数组(存储列表元素) self.__nums: List[int] = [0] * self.__capacity # 数组(存储列表元素)
self.__size = 0 # 列表长度(即当前元素数量) self.__size: int = 0 # 列表长度(即当前元素数量)
self.__extend_ratio = 2 # 每次列表扩容的倍数 self.__extend_ratio: int = 2 # 每次列表扩容的倍数
def size(self): def size(self) -> int:
""" 获取列表长度(即当前元素数量) """ """ 获取列表长度(即当前元素数量) """
return self.__size return self.__size
def capacity(self): def capacity(self) -> int:
""" 获取列表容量 """ """ 获取列表容量 """
return self.__capacity return self.__capacity
def get(self, index): def get(self, index: int) -> int:
""" 访问元素 """ """ 访问元素 """
# 索引如果越界则抛出异常,下同 # 索引如果越界则抛出异常,下同
assert index >= 0 and index < self.__size, "索引越界" assert index >= 0 and index < self.__size, "索引越界"
return self.__nums[index] return self.__nums[index]
def set(self, num, index): def set(self, num: int, index: int) -> None:
""" 更新元素 """ """ 更新元素 """
assert index >= 0 and index < self.__size, "索引越界" assert index >= 0 and index < self.__size, "索引越界"
self.__nums[index] = num self.__nums[index] = num
def add(self, num): def add(self, num: int) -> None:
""" 尾部添加元素 """ """ 尾部添加元素 """
# 元素数量超出容量时,触发扩容机制 # 元素数量超出容量时,触发扩容机制
if self.size() == self.capacity(): if self.size() == self.capacity():
@ -44,7 +44,7 @@ class MyList:
self.__nums[self.__size] = num self.__nums[self.__size] = num
self.__size += 1 self.__size += 1
def insert(self, num, index): def insert(self, num: int, index: int) -> None:
""" 中间插入元素 """ """ 中间插入元素 """
assert index >= 0 and index < self.__size, "索引越界" assert index >= 0 and index < self.__size, "索引越界"
# 元素数量超出容量时,触发扩容机制 # 元素数量超出容量时,触发扩容机制
@ -57,7 +57,7 @@ class MyList:
# 更新元素数量 # 更新元素数量
self.__size += 1 self.__size += 1
def remove(self, index): def remove(self, index: int) -> int:
""" 删除元素 """ """ 删除元素 """
assert index >= 0 and index < self.__size, "索引越界" assert index >= 0 and index < self.__size, "索引越界"
num = self.__nums[index] num = self.__nums[index]
@ -69,14 +69,14 @@ class MyList:
# 返回被删除元素 # 返回被删除元素
return num return num
def extend_capacity(self): def extend_capacity(self) -> None:
""" 列表扩容 """ """ 列表扩容 """
# 新建一个长度为 self.__size 的数组,并将原数组拷贝到新数组 # 新建一个长度为 self.__size 的数组,并将原数组拷贝到新数组
self.__nums = self.__nums + [0] * self.capacity() * (self.__extend_ratio - 1) self.__nums = self.__nums + [0] * self.capacity() * (self.__extend_ratio - 1)
# 更新列表容量 # 更新列表容量
self.__capacity = len(self.__nums) self.__capacity = len(self.__nums)
def to_array(self): def to_array(self) -> List[int]:
""" 返回有效长度的列表 """ """ 返回有效长度的列表 """
return self.__nums[:self.__size] 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 i in range(len(nums) - 1):
for j in range(i + 1, len(nums)): for j in range(i + 1, len(nums)):
if nums[i] + nums[j] == target: if nums[i] + nums[j] == target:
return i, j return [i, j]
return [] return []
def two_sum_hash_table(nums: List[int], target: int) -> List[int]: 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) # 单层循环,时间复杂度 O(n)
for i in range(len(nums)): for i in range(len(nums)):
if target - nums[i] in dic: if target - nums[i] in dic:
return dic[target - nums[i]], i return [dic[target - nums[i]], i]
dic[nums[i]] = i dic[nums[i]] = i
return [] return []
@ -37,8 +37,8 @@ if __name__ == '__main__':
# ====== Driver Code ====== # ====== Driver Code ======
# 方法一 # 方法一
res = two_sum_brute_force(nums, target) res: List[int] = two_sum_brute_force(nums, target)
print("方法一 res =", res) print("方法一 res =", res)
# 方法二 # 方法二
res = two_sum_hash_table(nums, target) res: List[int] = two_sum_hash_table(nums, target)
print("方法二 res =", res) 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__)))) sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import * from modules import *
def function(): def function() -> int:
""" 函数 """ """ 函数 """
# do something # do something
return 0 return 0
def constant(n): def constant(n: int) -> None:
""" 常数阶 """ """ 常数阶 """
# 常量、变量、对象占用 O(1) 空间 # 常量、变量、对象占用 O(1) 空间
a = 0 a: int = 0
nums = [0] * 10000 nums: List[int] = [0] * 10000
node = ListNode(0) node = ListNode(0)
# 循环中的变量占用 O(1) 空间 # 循环中的变量占用 O(1) 空间
for _ in range(n): for _ in range(n):
c = 0 c: int = 0
# 循环中的函数占用 O(1) 空间 # 循环中的函数占用 O(1) 空间
for _ in range(n): for _ in range(n):
function() function()
def linear(n): def linear(n: int) -> None:
""" 线性阶 """ """ 线性阶 """
# 长度为 n 的列表占用 O(n) 空间 # 长度为 n 的列表占用 O(n) 空间
nums = [0] * n nums: List[int] = [0] * n
# 长度为 n 的哈希表占用 O(n) 空间 # 长度为 n 的哈希表占用 O(n) 空间
mapp = {} mapp: Dict = {}
for i in range(n): for i in range(n):
mapp[i] = str(i) mapp[i] = str(i)
def linear_recur(n): def linear_recur(n: int) -> None:
""" 线性阶(递归实现) """ """ 线性阶(递归实现) """
print("递归 n =", n) print("递归 n =", n)
if n == 1: return if n == 1: return
linear_recur(n - 1) linear_recur(n - 1)
def quadratic(n): def quadratic(n: int) -> None:
""" 平方阶 """ """ 平方阶 """
# 二维列表占用 O(n^2) 空间 # 二维列表占用 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 if n <= 0: return 0
# 数组 nums 长度为 n, n-1, ..., 2, 1 # 数组 nums 长度为 n, n-1, ..., 2, 1
nums = [0] * n nums: List[int] = [0] * n
return quadratic_recur(n - 1) return quadratic_recur(n - 1)
def build_tree(n): def build_tree(n: int) -> Optional[TreeNode]:
""" 指数阶(建立满二叉树) """ """ 指数阶(建立满二叉树) """
if n == 0: return None if n == 0: return None
root = TreeNode(0) root = TreeNode(0)
@ -74,5 +74,5 @@ if __name__ == "__main__":
quadratic(n) quadratic(n)
quadratic_recur(n) quadratic_recur(n)
# 指数阶 # 指数阶
root = build_tree(n) root: Optional[TreeNode] = build_tree(n)
print_tree(root) 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__)))) sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import * from modules import *
def constant(n): def constant(n: int) -> int:
""" 常数阶 """ """ 常数阶 """
count = 0 count: int = 0
size = 100000 size: int = 100000
for _ in range(size): for _ in range(size):
count += 1 count += 1
return count return count
def linear(n): def linear(n: int) -> int:
""" 线性阶 """ """ 线性阶 """
count = 0 count: int = 0
for _ in range(n): for _ in range(n):
count += 1 count += 1
return count return count
def array_traversal(nums): def array_traversal(nums: List[int]) -> int:
""" 线性阶(遍历数组)""" """ 线性阶(遍历数组)"""
count = 0 count: int = 0
# 循环次数与数组长度成正比 # 循环次数与数组长度成正比
for num in nums: for num in nums:
count += 1 count += 1
return count return count
def quadratic(n): def quadratic(n: int) -> int:
""" 平方阶 """ """ 平方阶 """
count = 0 count: int = 0
# 循环次数与数组长度成平方关系 # 循环次数与数组长度成平方关系
for i in range(n): for i in range(n):
for j in range(n): for j in range(n):
count += 1 count += 1
return count return count
def bubble_sort(nums): def bubble_sort(nums: List[int]) -> int:
""" 平方阶(冒泡排序)""" """ 平方阶(冒泡排序)"""
count = 0 # 计数器 count: int = 0 # 计数器
# 外循环:待排序元素数量为 n-1, n-2, ..., 1 # 外循环:待排序元素数量为 n-1, n-2, ..., 1
for i in range(len(nums) - 1, 0, -1): for i in range(len(nums) - 1, 0, -1):
# 内循环:冒泡操作 # 内循环:冒泡操作
for j in range(i): for j in range(i):
if nums[j] > nums[j + 1]: if nums[j] > nums[j + 1]:
# 交换 nums[j] 与 nums[j + 1] # 交换 nums[j] 与 nums[j + 1]
tmp = nums[j] tmp: int = nums[j]
nums[j] = nums[j + 1] nums[j] = nums[j + 1]
nums[j + 1] = tmp nums[j + 1] = tmp
count += 3 # 元素交换包含 3 个单元操作 count += 3 # 元素交换包含 3 个单元操作
return count 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) # cell 每轮一分为二,形成数列 1, 2, 4, 8, ..., 2^(n-1)
for _ in range(n): for _ in range(n):
for _ in range(base): for _ in range(base):
@ -66,37 +67,37 @@ def exponential(n):
# count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1 # count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1
return count return count
def exp_recur(n): def exp_recur(n: int) -> int:
""" 指数阶(递归实现)""" """ 指数阶(递归实现)"""
if n == 1: return 1 if n == 1: return 1
return exp_recur(n - 1) + exp_recur(n - 1) + 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: while n > 1:
n = n / 2 n = n / 2
count += 1 count += 1
return count return count
def log_recur(n): def log_recur(n: float) -> int:
""" 对数阶(递归实现)""" """ 对数阶(递归实现)"""
if n <= 1: return 0 if n <= 1: return 0
return log_recur(n / 2) + 1 return log_recur(n / 2) + 1
def linear_log_recur(n): def linear_log_recur(n: float) -> int:
""" 线性对数阶 """ """ 线性对数阶 """
if n <= 1: return 1 if n <= 1: return 1
count = linear_log_recur(n // 2) + \ count: int = linear_log_recur(n // 2) + \
linear_log_recur(n // 2) linear_log_recur(n // 2)
for _ in range(n): for _ in range(n):
count += 1 count += 1
return count return count
def factorial_recur(n): def factorial_recur(n: int) -> int:
""" 阶乘阶(递归实现)""" """ 阶乘阶(递归实现)"""
if n == 0: return 1 if n == 0: return 1
count = 0 count: int = 0
# 从 1 个分裂出 n 个 # 从 1 个分裂出 n 个
for _ in range(n): for _ in range(n):
count += factorial_recur(n - 1) count += factorial_recur(n - 1)
@ -109,32 +110,32 @@ if __name__ == "__main__":
n = 8 n = 8
print("输入数据大小 n =", n) print("输入数据大小 n =", n)
count = constant(n) count: int = constant(n)
print("常数阶的计算操作数量 =", count) print("常数阶的计算操作数量 =", count)
count = linear(n) count: int = linear(n)
print("线性阶的计算操作数量 =", count) print("线性阶的计算操作数量 =", count)
count = array_traversal([0] * n) count: int = array_traversal([0] * n)
print("线性阶(遍历数组)的计算操作数量 =", count) print("线性阶(遍历数组)的计算操作数量 =", count)
count = quadratic(n) count: int = quadratic(n)
print("平方阶的计算操作数量 =", count) print("平方阶的计算操作数量 =", count)
nums = [i for i in range(n, 0, -1)] # [n,n-1,...,2,1] nums: List[int] = [i for i in range(n, 0, -1)] # [n,n-1,...,2,1]
count = bubble_sort(nums) count: int = bubble_sort(nums)
print("平方阶(冒泡排序)的计算操作数量 =", count) print("平方阶(冒泡排序)的计算操作数量 =", count)
count = exponential(n) count: int = exponential(n)
print("指数阶(循环实现)的计算操作数量 =", count) print("指数阶(循环实现)的计算操作数量 =", count)
count = exp_recur(n) count: int = exp_recur(n)
print("指数阶(递归实现)的计算操作数量 =", count) print("指数阶(递归实现)的计算操作数量 =", count)
count = logarithmic(n) count: int = logarithmic(n)
print("对数阶(循环实现)的计算操作数量 =", count) print("对数阶(循环实现)的计算操作数量 =", count)
count = log_recur(n) count: int = log_recur(n)
print("对数阶(递归实现)的计算操作数量 =", count) print("对数阶(递归实现)的计算操作数量 =", count)
count = linear_log_recur(n) count: int = linear_log_recur(n)
print("线性对数阶(递归实现)的计算操作数量 =", count) print("线性对数阶(递归实现)的计算操作数量 =", count)
count = factorial_recur(n) count: int = factorial_recur(n)
print("阶乘阶(递归实现)的计算操作数量 =", count) print("阶乘阶(递归实现)的计算操作数量 =", count)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -4,16 +4,18 @@ Created Time: 2023-02-23
Author: Krahets (krahets@163.com) 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__)))) sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import * 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) # 元素入堆 heapq.heappush(heap, flag * val) # 元素入堆
print(f"\n元素 {val} 入堆后") print(f"\n元素 {val} 入堆后")
print_heap([flag * val for val in heap]) 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) # 堆顶元素出堆 val = flag * heapq.heappop(heap) # 堆顶元素出堆
print(f"\n堆顶元素 {val} 出堆后") print(f"\n堆顶元素 {val} 出堆后")
print_heap([flag * val for val in heap]) print_heap([flag * val for val in heap])
@ -37,7 +39,7 @@ if __name__ == "__main__":
test_push(max_heap, 4, flag) test_push(max_heap, 4, flag)
""" 获取堆顶元素 """ """ 获取堆顶元素 """
peek = flag * max_heap[0] peek: int = flag * max_heap[0]
print(f"\n堆顶元素为 {peek}") print(f"\n堆顶元素为 {peek}")
""" 堆顶元素出堆 """ """ 堆顶元素出堆 """
@ -48,16 +50,16 @@ if __name__ == "__main__":
test_pop(max_heap, flag) test_pop(max_heap, flag)
""" 获取堆大小 """ """ 获取堆大小 """
size = len(max_heap) size: int = len(max_heap)
print(f"\n堆元素数量为 {size}") print(f"\n堆元素数量为 {size}")
""" 判断堆是否为空 """ """ 判断堆是否为空 """
is_empty = not max_heap is_empty: bool = not max_heap
print(f"\n堆是否为空 {is_empty}") print(f"\n堆是否为空 {is_empty}")
""" 输入列表并建堆 """ """ 输入列表并建堆 """
# 时间复杂度为 O(n) ,而非 O(nlogn) # 时间复杂度为 O(n) ,而非 O(nlogn)
min_heap = [1, 3, 2, 5, 4] min_heap: List[int] = [1, 3, 2, 5, 4]
heapq.heapify(min_heap) heapq.heapify(min_heap)
print("\n输入列表并建立小顶堆后") print("\n输入列表并建立小顶堆后")
print_heap(min_heap) 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__)))) sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import * from modules import *
def binary_search(nums, target): def binary_search(nums: List[int], target: int) -> int:
""" 二分查找(双闭区间) """ """ 二分查找(双闭区间) """
# 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素 # 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
i, j = 0, len(nums) - 1 i, j = 0, len(nums) - 1
@ -23,7 +23,7 @@ def binary_search(nums, target):
return -1 # 未找到目标元素,返回 -1 return -1 # 未找到目标元素,返回 -1
def binary_search1(nums, target): def binary_search1(nums: List[int], target: int) -> int:
""" 二分查找(左闭右开) """ """ 二分查找(左闭右开) """
# 初始化左闭右开 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1 # 初始化左闭右开 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
i, j = 0, len(nums) i, j = 0, len(nums)
@ -41,13 +41,13 @@ def binary_search1(nums, target):
""" Driver Code """ """ Driver Code """
if __name__ == '__main__': if __name__ == '__main__':
target = 6 target: int = 6
nums = [1, 3, 6, 8, 12, 15, 23, 67, 70, 92] 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) print("目标元素 6 的索引 = ", index)
# 二分查找(左闭右开) # 二分查找(左闭右开)
index = binary_search1(nums, target) index: int = binary_search1(nums, target)
print("目标元素 6 的索引 = ", index) 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__)))) sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import * from modules import *
def hashing_search_array(mapp, target): def hashing_search_array(mapp: Dict[int, int], target: int) -> int:
""" 哈希查找(数组) """ """ 哈希查找(数组) """
# 哈希表的 key: 目标元素value: 索引 # 哈希表的 key: 目标元素value: 索引
# 若哈希表中无此 key ,返回 -1 # 若哈希表中无此 key ,返回 -1
return mapp.get(target, -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: 目标元素value: 结点对象
# 若哈希表中无此 key ,返回 -1 # 若哈希表中无此 key ,返回 None
return mapp.get(target, -1) return mapp.get(target, None)
""" Driver Code """ """ Driver Code """
if __name__ == '__main__': 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)): for i in range(len(nums)):
mapp[nums[i]] = i # key: 元素value: 索引 mapp[nums[i]] = i # key: 元素value: 索引
index = hashing_search_array(mapp, target) index: int = hashing_search_array(mapp, target)
print("目标元素 3 的索引 =", index) print("目标元素 3 的索引 =", index)
# 哈希查找(链表) # 哈希查找(链表)
head = list_to_linked_list(nums) head: ListNode = list_to_linked_list(nums)
# 初始化哈希表 # 初始化哈希表
map1 = {} map1: Dict[int, ListNode] = {}
while head: while head:
map1[head.val] = head # key: 结点值value: 结点 map1[head.val] = head # key: 结点值value: 结点
head = head.next head = head.next
node = hashing_search_linkedlist(map1, target) node: ListNode = hashing_search_linkedlist(map1, target)
print("目标结点值 3 的对应结点对象为", node) 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__)))) sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import * 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)): for i in range(len(nums)):
@ -16,7 +16,7 @@ def linear_search_array(nums, target):
return i return i
return -1 # 未找到目标元素,返回 -1 return -1 # 未找到目标元素,返回 -1
def linear_search_linkedlist(head, target): def linear_search_linkedlist(head: ListNode, target: int) -> Optional[ListNode]:
""" 线性查找(链表) """ """ 线性查找(链表) """
# 遍历链表 # 遍历链表
while head: while head:
@ -28,14 +28,14 @@ def linear_search_linkedlist(head, target):
""" Driver Code """ """ Driver Code """
if __name__ == '__main__': 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]
index = linear_search_array(nums, target) index: int = linear_search_array(nums, target)
print("目标元素 3 的索引 =", index) print("目标元素 3 的索引 =", index)
# 在链表中执行线性查找 # 在链表中执行线性查找
head = list_to_linked_list(nums) head: ListNode = list_to_linked_list(nums)
node = linear_search_linkedlist(head, target) node: Optional[ListNode] = linear_search_linkedlist(head, target)
print("目标结点值 3 的对应结点对象为", node) 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__)))) sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import * 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 # 外循环:待排序元素数量为 n-1, n-2, ..., 1
for i in range(n - 1, 0, -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], nums[j + 1] = nums[j + 1], nums[j] 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 # 外循环:待排序元素数量为 n-1, n-2, ..., 1
for i in range(n - 1, 0, -1): for i in range(n - 1, 0, -1):
flag = False # 初始化标志位 flag: bool = False # 初始化标志位
# 内循环:冒泡操作 # 内循环:冒泡操作
for j in range(i): for j in range(i):
if nums[j] > nums[j + 1]: if nums[j] > nums[j + 1]:
@ -37,10 +37,10 @@ def bubble_sort_with_flag(nums):
""" Driver Code """ """ Driver Code """
if __name__ == '__main__': if __name__ == '__main__':
nums = [4, 1, 3, 1, 5, 2] nums: List[int] = [4, 1, 3, 1, 5, 2]
bubble_sort(nums) bubble_sort(nums)
print("排序后数组 nums =", 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) bubble_sort_with_flag(nums1)
print("排序后数组 nums =", 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__)))) sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import * from modules import *
def insertion_sort(nums): def insertion_sort(nums: List[int]) -> None:
""" 插入排序 """ """ 插入排序 """
# 外循环base = nums[1], nums[2], ..., nums[n-1] # 外循环base = nums[1], nums[2], ..., nums[n-1]
for i in range(1, len(nums)): for i in range(1, len(nums)):
base = nums[i] base: int = nums[i]
j = i - 1 j: int = i - 1
# 内循环:将 base 插入到左边的正确位置 # 内循环:将 base 插入到左边的正确位置
while j >= 0 and nums[j] > base: while j >= 0 and nums[j] > base:
nums[j + 1] = nums[j] # 1. 将 nums[j] 向右移动一位 nums[j + 1] = nums[j] # 1. 将 nums[j] 向右移动一位
@ -23,6 +23,6 @@ def insertion_sort(nums):
""" Driver Code """ """ Driver Code """
if __name__ == '__main__': if __name__ == '__main__':
nums = [4, 1, 3, 1, 5, 2] nums: List[int] = [4, 1, 3, 1, 5, 2]
insertion_sort(nums) insertion_sort(nums)
print("排序后数组 nums =", 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__)))) sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import * from modules import *
def merge(nums, left, mid, right): def merge(nums: List[int], left: int, mid: int, right: int) -> None:
""" 合并左子数组和右子数组 """ """ 合并左子数组和右子数组 """
# 左子数组区间 [left, mid] # 左子数组区间 [left, mid]
# 右子数组区间 [mid + 1, right] # 右子数组区间 [mid + 1, right]
# 初始化辅助数组 借助 copy模块 # 初始化辅助数组 借助 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 分别指向左子数组、右子数组的首元素
i, j = left_start, right_start i: int = left_start
j: int = right_start
# 通过覆盖原数组 nums 来合并左子数组和右子数组 # 通过覆盖原数组 nums 来合并左子数组和右子数组
for k in range(left, right + 1): for k in range(left, right + 1):
# 若“左子数组已全部合并完”,则选取右子数组元素,并且 j++ # 若“左子数组已全部合并完”,则选取右子数组元素,并且 j++
@ -35,13 +38,13 @@ def merge(nums, left, mid, right):
nums[k] = tmp[j] nums[k] = tmp[j]
j += 1 j += 1
def merge_sort(nums, left, right): def merge_sort(nums: List[int], left: int, right: int) -> None:
""" 归并排序 """ """ 归并排序 """
# 终止条件 # 终止条件
if left >= right: if left >= right:
return # 当子数组长度为 1 时终止递归 return # 当子数组长度为 1 时终止递归
# 划分阶段 # 划分阶段
mid = (left + right) // 2 # 计算中点 mid: int = (left + right) // 2 # 计算中点
merge_sort(nums, left, mid) # 递归左子数组 merge_sort(nums, left, mid) # 递归左子数组
merge_sort(nums, mid + 1, right) # 递归右子数组 merge_sort(nums, mid + 1, right) # 递归右子数组
# 合并阶段 # 合并阶段
@ -50,6 +53,6 @@ def merge_sort(nums, left, right):
""" Driver Code """ """ Driver Code """
if __name__ == '__main__': 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) merge_sort(nums, 0, len(nums) - 1)
print("归并排序完成后 nums =", nums) print("归并排序完成后 nums =", nums)

View File

@ -10,7 +10,7 @@ from modules import *
class QuickSort: class QuickSort:
""" 快速排序类 """ """ 快速排序类 """
def partition(self, nums, left, right): def partition(self, nums: List[int], left: int, right: int) -> int:
""" 哨兵划分 """ """ 哨兵划分 """
# 以 nums[left] 作为基准数 # 以 nums[left] 作为基准数
i, j = left, right i, j = left, right
@ -25,20 +25,20 @@ class QuickSort:
nums[i], nums[left] = nums[left], nums[i] nums[i], nums[left] = nums[left], nums[i]
return i # 返回基准数的索引 return i # 返回基准数的索引
def quick_sort(self, nums, left, right): def quick_sort(self, nums: List[int], left: int, right: int) -> None:
""" 快速排序 """ """ 快速排序 """
# 子数组长度为 1 时终止递归 # 子数组长度为 1 时终止递归
if left >= right: if left >= right:
return 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, left, pivot - 1)
self.quick_sort(nums, pivot + 1, right) self.quick_sort(nums, pivot + 1, right)
class QuickSortMedian: 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 # 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1
@ -48,10 +48,10 @@ class QuickSortMedian:
return mid return mid
return right return right
def partition(self, nums, left, right): def partition(self, nums: List[int], left: int, right: int) -> int:
""" 哨兵划分(三数取中值) """ """ 哨兵划分(三数取中值) """
# 以 nums[left] 作为基准数 # 以 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], nums[med] = nums[med], nums[left]
# 以 nums[left] 作为基准数 # 以 nums[left] 作为基准数
@ -67,19 +67,20 @@ class QuickSortMedian:
nums[i], nums[left] = nums[left], nums[i] nums[i], nums[left] = nums[left], nums[i]
return i # 返回基准数的索引 return i # 返回基准数的索引
def quick_sort(self, nums, left, right): def quick_sort(self, nums: List[int], left: int, right: int) -> None:
""" 快速排序 """ """ 快速排序 """
# 子数组长度为 1 时终止递归 # 子数组长度为 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, left, pivot - 1)
self.quick_sort(nums, pivot + 1, right) self.quick_sort(nums, pivot + 1, right)
class QuickSortTailCall: class QuickSortTailCall:
""" 快速排序类(尾递归优化) """ """ 快速排序类(尾递归优化) """
def partition(self, nums, left, right): def partition(self, nums: List[int], left: int, right: int) -> int:
""" 哨兵划分 """ """ 哨兵划分 """
# 以 nums[left] 作为基准数 # 以 nums[left] 作为基准数
i, j = left, right i, j = left, right
@ -94,12 +95,12 @@ class QuickSortTailCall:
nums[i], nums[left] = nums[left], nums[i] nums[i], nums[left] = nums[left], nums[i]
return i # 返回基准数的索引 return i # 返回基准数的索引
def quick_sort(self, nums, left, right): def quick_sort(self, nums: List[int], left: int, right: int) -> None:
""" 快速排序(尾递归优化) """ """ 快速排序(尾递归优化) """
# 子数组长度为 1 时终止 # 子数组长度为 1 时终止
while left < right: while left < right:
# 哨兵划分操作 # 哨兵划分操作
pivot = self.partition(nums, left, right) pivot: int = self.partition(nums, left, right)
# 对两个子数组中较短的那个执行快排 # 对两个子数组中较短的那个执行快排
if pivot - left < right - pivot: if pivot - left < right - pivot:
self.quick_sort(nums, left, pivot - 1) # 递归排序左子数组 self.quick_sort(nums, left, pivot - 1) # 递归排序左子数组
@ -112,16 +113,16 @@ class QuickSortTailCall:
""" Driver Code """ """ Driver Code """
if __name__ == '__main__': 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) QuickSort().quick_sort(nums, 0, len(nums) - 1)
print("快速排序完成后 nums =", nums) 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) QuickSortMedian().quick_sort(nums1, 0, len(nums1) - 1)
print("快速排序(中位基准数优化)完成后 nums =", nums1) 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) QuickSortTailCall().quick_sort(nums2, 0, len(nums2) - 1)
print("快速排序(尾递归优化)完成后 nums =", nums2) print("快速排序(尾递归优化)完成后 nums =", nums2)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -9,20 +9,20 @@ sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import * 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) queue.append(root)
# 初始化一个列表,用于保存遍历序列 # 初始化一个列表,用于保存遍历序列
res = [] res: List[int] = []
while queue: while queue:
node = queue.popleft() # 队列出队 node: TreeNode = queue.popleft() # 队列出队
res.append(node.val) # 保存结点值 res.append(node.val) # 保存结点值
if node.left is not None: if node.left is not None:
queue.append(node.left) # 左子结点入队 queue.append(node.left) # 左子结点入队
if node.right is not None: if node.right is not None:
queue.append(node.right) # 右子结点入队 queue.append(node.right) # 右子结点入队
return res return res
@ -30,11 +30,11 @@ def level_order(root: Optional[TreeNode]):
if __name__ == "__main__": 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("\n初始化二叉树\n")
print_tree(root) print_tree(root)
# 层序遍历 # 层序遍历
res = level_order(root) res: List[int] = level_order(root)
print("\n层序遍历的结点打印序列 = ", res) print("\n层序遍历的结点打印序列 = ", res)
assert res == [1, 2, 3, 4, 5, 6, 7] 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 * from modules import *
def pre_order(root: Optional[TreeNode]): def pre_order(root: Optional[TreeNode]) -> None:
""" 前序遍历 """ """ 前序遍历 """
if root is None: if root is None:
return return
@ -18,7 +18,7 @@ def pre_order(root: Optional[TreeNode]):
pre_order(root=root.left) pre_order(root=root.left)
pre_order(root=root.right) pre_order(root=root.right)
def in_order(root: Optional[TreeNode]): def in_order(root: Optional[TreeNode]) -> None:
""" 中序遍历 """ """ 中序遍历 """
if root is None: if root is None:
return return
@ -27,7 +27,7 @@ def in_order(root: Optional[TreeNode]):
res.append(root.val) res.append(root.val)
in_order(root=root.right) in_order(root=root.right)
def post_order(root: Optional[TreeNode]): def post_order(root: Optional[TreeNode]) -> None:
""" 后序遍历 """ """ 后序遍历 """
if root is None: if root is None:
return return
@ -36,7 +36,6 @@ def post_order(root: Optional[TreeNode]):
post_order(root=root.right) post_order(root=root.right)
res.append(root.val) res.append(root.val)
res = []
""" Driver Code """ """ Driver Code """
if __name__ == "__main__": if __name__ == "__main__":
@ -47,7 +46,7 @@ if __name__ == "__main__":
print_tree(root) print_tree(root)
# 前序遍历 # 前序遍历
res.clear() res = []
pre_order(root) pre_order(root)
print("\n前序遍历的结点打印序列 = ", res) print("\n前序遍历的结点打印序列 = ", res)
assert res == [1, 2, 4, 5, 3, 6, 7] assert res == [1, 2, 4, 5, 3, 6, 7]

View File

@ -5,7 +5,7 @@ import queue
import random import random
import functools import functools
import collections 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 .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 .binary_tree import TreeNode, list_to_tree, tree_to_list, get_tree_node
from .vertex import Vertex, vals_to_vets, vets_to_vals from .vertex import Vertex, vals_to_vets, vets_to_vals

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -133,7 +133,7 @@
heapq.heappush(max_heap, flag * 4) 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 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) heapq.heapify(min_heap)
``` ```

View File

@ -64,43 +64,9 @@
=== "C++" === "C++"
```cpp title="merge_sort.cpp" ```cpp title="merge_sort.cpp"
/* 合并左子数组和右子数组 */ [class]{}-[func]{merge}
// 左子数组区间 [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]{mergeSort}
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);
}
``` ```
=== "Python" === "Python"
@ -114,139 +80,25 @@
=== "Go" === "Go"
```go title="merge_sort.go" ```go title="merge_sort.go"
/* [class]{}-[func]{merge}
合并左子数组和右子数组
左子数组区间 [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++
}
}
}
func mergeSort(nums []int, left, right int) { [class]{}-[func]{mergeSort}
// 终止条件
if left >= right {
return
}
// 划分阶段
mid := (left + right) / 2
mergeSort(nums, left, mid)
mergeSort(nums, mid+1, right)
// 合并阶段
merge(nums, left, mid, right)
}
``` ```
=== "JavaScript" === "JavaScript"
```javascript title="merge_sort.js" ```javascript title="merge_sort.js"
/* 合并左子数组和右子数组 */ [class]{}-[func]{merge}
// 左子数组区间 [left, mid]
// 右子数组区间 [mid + 1, right] [class]{}-[func]{mergeSort}
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);
}
``` ```
=== "TypeScript" === "TypeScript"
```typescript title="merge_sort.ts" ```typescript title="merge_sort.ts"
/* 合并左子数组和右子数组 */ [class]{}-[func]{merge}
// 左子数组区间 [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]{mergeSort}
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);
}
``` ```
=== "C" === "C"
@ -266,62 +118,17 @@
=== "Swift" === "Swift"
```swift title="merge_sort.swift" ```swift title="merge_sort.swift"
/** [class]{}-[func]{merge}
* 合并左子数组和右子数组
* 左子数组区间 [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]{mergeSort}
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)
}
``` ```
=== "Zig" === "Zig"
```zig title="merge_sort.zig" ```zig title="merge_sort.zig"
[class]{}-[func]{merge}
[class]{}-[func]{mergeSort}
``` ```
下面重点解释一下合并方法 `merge()` 的流程: 下面重点解释一下合并方法 `merge()` 的流程:

View File

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

View File

@ -80,7 +80,7 @@
""" 初始化队列 """ """ 初始化队列 """
# 在 Python 中,我们一般将双向队列类 deque 看作队列使用 # 在 Python 中,我们一般将双向队列类 deque 看作队列使用
# 虽然 queue.Queue() 是纯正的队列类,但不太好用,因此不建议 # 虽然 queue.Queue() 是纯正的队列类,但不太好用,因此不建议
que = collections.deque() que: Deque[int] = collections.deque()
""" 元素入队 """ """ 元素入队 """
que.append(1) que.append(1)
@ -90,16 +90,16 @@
que.append(4) 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" === "Go"

View File

@ -81,7 +81,7 @@
```python title="stack.py" ```python title="stack.py"
""" 初始化栈 """ """ 初始化栈 """
# Python 没有内置的栈类,可以把 List 当作栈来使用 # Python 没有内置的栈类,可以把 List 当作栈来使用
stack = [] stack: List[int] = []
""" 元素入栈 """ """ 元素入栈 """
stack.append(1) stack.append(1)
@ -91,16 +91,16 @@
stack.append(4) 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" === "Go"

View File

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

View File

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