You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python实现归并排序遇索引越界及timeit相关错误求助

问题修复与优化建议

1. 修复Merge函数的索引越界错误

你的merge函数初始化了空列表S = []后直接用S[k] = ...赋值,这会触发索引越界——空列表没有可访问的下标。正确做法是用append()添加元素,或是预先分配对应长度的列表:

修复后的merge函数(简洁版):

def merge(S1, S2):
    i = j = 0
    S = []
    while i < len(S1) and j < len(S2):
         if S1[i] < S2[j]:
             S.append(S1[i])
             i += 1
         else:
             S.append(S2[j])
             j += 1
    # 追加剩余未处理的元素
    S.extend(S1[i:])
    S.extend(S2[j:])          
    return S

预先分配空间版(更高效):

def merge(S1, S2):
    i = j = 0
    len1, len2 = len(S1), len(S2)
    S = [0] * (len1 + len2)
    while i < len1 and j < len2:
        if S1[i] < S2[j]:
            S[i+j] = S1[i]
            i += 1
        else:
            S[i+j] = S2[j]
            j += 1
    # 处理剩余元素
    while i < len1:
        S[i+j] = S1[i]
        i += 1
    while j < len2:
        S[i+j] = S2[j]
        j += 1
    return S

2. 修复numpy数组与Python列表的类型冲突

代码混合使用numpy数组和Python列表,导致递归时类型不兼容:

  • mergesort里用S.size(numpy数组属性),但merge返回的是Python列表,列表没有size属性,会触发新错误。
  • 统一用Python列表避免混乱:

修改测试数据生成代码:

# 生成纯Python随机列表,避免内存溢出,调整长度范围到10^1到10^6
d = [random.sample(range(10**6), 10**i) for i in range(1, 7)]

修改mergesort的长度获取方式:

def mergesort(S):
    n = len(S)  # 用len()适配列表
    if n <= 1:
        return S
    else:
        S1, S2 = split(S)
        S1sorted = mergesort(S1)
        S2sorted = mergesort(S2)
        Ssorted = merge(S1sorted, S2sorted)
        return Ssorted

3. 修复timeit计时逻辑错误

timeit的setup无法正确获取循环变量s,改用lambda包装排序操作,同时复制列表保证每次输入都是未排序状态:

修改计时代码:

for s in d:
    # 复制列表避免原列表被排序后影响后续计时
    execution_time = timeit.timeit(stmt=lambda: mergesort(s.copy()), number=5)
    time_list.append(execution_time)
    length_list.append(len(s))
    print(f"列表长度: {len(s)}, 平均执行时间: {execution_time/5:.6f}秒")

4. 优化绘图以直观展示时间复杂度

添加O(N)、O(N²)和O(NlogN)的参考曲线,并用对数坐标放大趋势差异:

plt.scatter(length_list, time_list, label='归并排序实际耗时')
n_array = np.array(length_list)
# 计算系数让参考曲线与实际耗时匹配
coeff_n = time_list[-1] / n_array[-1]
coeff_n2 = time_list[-1] / (n_array[-1]**2)
coeff_nlogn = time_list[-1] / (n_array[-1] * np.log2(n_array[-1]))

plt.plot(n_array, coeff_n * n_array, label='O(N)', linestyle='--', color='red')
plt.plot(n_array, coeff_n2 * n_array**2, label='O(N²)', linestyle='--', color='green')
plt.plot(n_array, coeff_nlogn * n_array * np.log2(n_array), label='O(NlogN)', linestyle='--', color='orange')

plt.xlabel("列表长度N")
plt.ylabel("执行时间(秒)")
plt.legend()
plt.xscale('log')
plt.yscale('log')
plt.show()

完整修复后代码

import random
import timeit
import matplotlib.pyplot as plt
import numpy as np

def mergesort(S):
    n = len(S)
    if n <= 1:
        return S
    else:
        S1, S2 = split(S)
        S1sorted = mergesort(S1)
        S2sorted = mergesort(S2)
        Ssorted = merge(S1sorted, S2sorted)
        return Ssorted

def split(S):
    l = len(S)//2
    S1 = S[:l]
    S2 = S[l:]
    return S1, S2

def merge(S1, S2):
    i = j = 0
    S = []
    while i < len(S1) and j < len(S2):
         if S1[i] < S2[j]:
             S.append(S1[i])
             i += 1
         else:
             S.append(S2[j])
             j += 1
    S.extend(S1[i:])
    S.extend(S2[j:])          
    return S

if __name__ == '__main__':
    random.seed(5)
    d = [random.sample(range(10**6), 10**i) for i in range(1, 7)]
    time_list = []
    length_list = []
    for s in d:
        execution_time = timeit.timeit(stmt=lambda: mergesort(s.copy()), number=5)
        time_list.append(execution_time)
        length_list.append(len(s))
        print(f"列表长度: {len(s)}, 平均执行时间: {execution_time/5:.6f}秒")

    plt.scatter(length_list, time_list, label='归并排序实际耗时')
    n_array = np.array(length_list)
    coeff_n = time_list[-1] / n_array[-1]
    coeff_n2 = time_list[-1] / (n_array[-1]**2)
    coeff_nlogn = time_list[-1] / (n_array[-1] * np.log2(n_array[-1]))
    
    plt.plot(n_array, coeff_n * n_array, label='O(N)', linestyle='--', color='red')
    plt.plot(n_array, coeff_n2 * n_array**2, label='O(N²)', linestyle='--', color='green')
    plt.plot(n_array, coeff_nlogn * n_array * np.log2(n_array), label='O(NlogN)', linestyle='--', color='orange')

    plt.xlabel("列表长度N")
    plt.ylabel("执行时间(秒)")
    plt.legend()
    plt.xscale('log')
    plt.yscale('log')
    plt.show()

内容的提问来源于stack exchange,提问作者user996159

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 00:46:00