算法导论第三版代码python实现与部分习题答案-第二章:算法基础

算法导论

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

使用数学归纳法证明:当 nnn222 的幂时,递归式的解为:
T(n)=nlg⁡n 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,由于题设中说明 nnn222 的幂,因此我们可以令 n=2kn = 2^kn=2k

验证初始情况(Base Case):

k=1k=1k=1 时,有
T(2)=2=2lg⁡2 T(2) = 2 = 2 \lg 2 T(2)=2=2lg2
因为 lg⁡2=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+

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值