算法导论
2.1 插入排序
def insertion_sort(arr):
"""
插入排序算法
:param arr: 待排序的列表
:return: 排序后的列表
"""
for j in range(1, len(arr)):
# 从第二个元素开始进行处理
key = arr[j]
i = j - 1
# 将大于key的元素向后移动一位
while i >= 0 and arr[i] > key:
arr[i + 1] = arr[i]
i -= 1
# 放置key
arr[i + 1] = key
return arr
# 示例用法
if __name__ == "__main__":
arr = [5, 2, 4, 6, 1, 3]
print("排序前:", arr)
sorted_arr = insertion_sort(arr)
print("排序后:", sorted_arr)
2.3 归并算法
import math
from typing import List
def merge(A: List[int], p: int, q: int, r: int) -> None:
"""
合并两个已排序的子数组 A[p..q] 和 A[q+1..r]
参数:
A (List[int]): 原始数组(列表),将被原地修改。
p (int): 左边子数组的起始索引(包含)
q (int): 中间索引,左边子数组的结束位置(包含)
r (int): 右边子数组的结束索引(包含)
返回:
None: 此函数直接修改输入数组 A,不返回任何值。
备注:
- 时间复杂度:O(n),其中 n = r - p + 1
- 空间复杂度:O(n)
- 使用哨兵值 float('inf') 来简化边界判断逻辑
"""
# 计算左右子数组长度
n1 = q - p + 1
n2 = r - q
# 初始化临时数组 L 和 R
L = [0] * (n1 + 1)
R = [0] * (n2 + 1)
# 拷贝数据到临时数组
for i in range(n1):
L[i] = A[p + i]
for j in range(n2):
R[j] = A[q + 1 + j]
# 添加哨兵值
L[n1] = float('inf')
R[n2] = float('inf')
# 初始化指针
i = 0
j = 0
# 合并回原数组 A
for k in range(p, r + 1):
if L[i] <= R[j]:
A[k] = L[i]
i += 1
else:
A[k] = R[j]
j += 1
def merge_sort(A: List[int], p: int, r: int) -> None:
"""
归并排序的递归主函数,对数组 A 的 p 到 r 区间进行排序
参数:
A (List[int]): 待排序数组
p (int): 排序范围的起始索引(包含)
r (int): 排序范围的结束索引(包含)
返回:
None: 原地排序,不返回新数组
"""
if p < r:
q = (p + r) // 2 # 找中点(整数除法)
merge_sort(A, p, q) # 对左半部分排序
merge_sort(A, q + 1, r) # 对右半部分排序
merge(A, p, q, r) # 合并两个有序子数组
Exercise 2.3-2
重写过程 MERGE, 使之不使用哨兵, 而是一旦数组 L 或 R 的所有元素均被复制回 A 就 立刻停止, 然后把另一个数组的剩余部分复制回A
from typing import List
def merge_sort(arr: List[int]) -> List[int]:
"""
归并排序主函数
:param arr: 待排序的整数列表
:return: 已排序的整数列表
"""
if len(arr) <= 1:
return arr
# 划分数组为两部分
mid = len(arr) // 2
left = merge_sort(arr[:mid])
right = merge_sort(arr[mid:])
# 合并两个有序数组
return merge(left, right)
def merge(left: List[int], right: List[int]) -> List[int]:
result = []
i = j = 0
# 依次比较,归并
while i < len(left) and j < len(right):
if left[i] <= right[j]:
result.append(left[i])
i += 1
else:
result.append(right[j])
j += 1
# 将剩余部分加入结果
result.extend(left[i:])
result.extend(right[j:])
return result
Exercise 2.3-3
使用数学归纳法证明:当 nnn 是 222 的幂时,递归式的解为:
T(n)=nlgn T(n) = n \lg n T(n)=nlgn
其中递归式定义如下:
T(n)={ 1,当 n=12T(n2)+n,当 n>1 T(n) = \begin{cases} 1, & \text{当 } n = 1 \\ 2T\left(\frac{n}{2}\right) + n, & \text{当 } n > 1 \end{cases} T(n)={ 1,2T(2n)+n,当 n=1当 n>1
解:设 n=2kn = 2^kn=2k,由于题设中说明 nnn 是 222 的幂,因此我们可以令 n=2kn = 2^kn=2k。
验证初始情况(Base Case):
当 k=1k=1k=1 时,有
T(2)=2=2lg2 T(2) = 2 = 2 \lg 2 T(2)=2=2lg2
因为 lg2=1\lg 2 = 1lg2=1,所以等式成立。
归纳假设(Inductive Hypothesis):
假设对于某个正整数 kkk,结论成立,即
T(2k)=2klg(2k) T(2^k) = 2^k \lg(2^k) T(2k)=2klg(2k)
归纳步骤(Inductive Step):
我们来验证 k+1k+1k+

最低0.47元/天 解锁文章
1561

被折叠的 条评论
为什么被折叠?



