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

CLRS归并排序实现遇索引越界及排序失败问题排查求助

CLRS归并排序实现遇索引越界及排序失败问题排查求助

为什么这段代码无法对随机数组排序?
我试着调整了索引但没用,也考虑了Python的零基索引做了调整,但还是得不到有序数组。我是按照《算法导论》(第三版)31页的算法实现的。

import numpy as np
import math

X = np.random.randint(0,10,10).tolist()

def merge(a, p, q, r):
    n1 = q - p + 1
    n2 = r - q

    L = [0] * (n1 + 1)
    R = [0] * (n2 + 1)

    for i in range(0, n1):
        L[i] = a[p + i - 1]

    for j in range(0, n2):
        R[j] = a[q + j]

    L.append(math.inf)
    R.append(math.inf)

    i = 0
    j = 0

    for k in range(p, r):
        print(k)
        if L[i] <= R[j]:
            a[k] = L[i]
            i += 1
        else:
            a[k] = R[j]
            j += 1

def mergesort(a, p, r):
    if p < r:
        q = (p + r)//2
        mergesort(a, p, q)
        mergesort(a, q+1, r)
        merge(a, p, q, r)

print("Before: {}\n".format(X))
mergesort(X,0,10)
print("After: {}".format(X))

我帮你排查了几个核心问题,全都是因为把CLRS里的1基索引直接套用到Python的零基索引上导致的,逐个拆解:

1. 左子数组L的填充索引错误

CLRS伪代码用的是1基索引,所以原代码里L[i] = a[p + i - 1]是1基的写法,但Python是零基,当p=0时,p+i-1会变成-1,直接取数组最后一个元素,完全偏离了要取的左子数组范围。修正为:

for i in range(0, n1):
    L[i] = a[p + i]

这样零基下的a[p], a[p+1], ..., a[q]会被正确填充到L数组中。

2. 右子数组R的填充索引错误

同样是1基转零基的问题,右子数组应该从q+1开始到r,原代码R[j] = a[q + j]会把左子数组的最后一个元素a[q]也包含进来,导致数据重复和遗漏。修正为:

for j in range(0, n2):
    R[j] = a[q + 1 + j]

3. 哨兵元素的添加方式错误

你先初始化L为[0]*(n1+1)(长度为n1+1),然后又用L.append(math.inf),这样L的长度会变成n1+2,哨兵位置完全错位。CLRS里是把哨兵放在子数组的最后一个位置,直接覆盖初始化的最后一个0即可,不用append:

# 替换原来的append语句
L[n1] = math.inf
R[n2] = math.inf

4. 归并循环的范围错误

原代码for k in range(p, r)是左闭右开的范围,会漏掉r位置的元素。我们需要覆盖从p到r的所有索引(包含r),所以改成:

for k in range(p, r + 1):

5. 归并排序的调用参数错误

你的数组X长度是10,索引范围是0-9,但调用mergesort(X,0,10)时,r=10已经超出了数组的最大索引(9),会导致后续递归中访问a[10]触发索引越界。修正为:

mergesort(X, 0, len(X)-1)

修正后的完整代码:

import numpy as np
import math

X = np.random.randint(0,10,10).tolist()

def merge(a, p, q, r):
    n1 = q - p + 1
    n2 = r - q

    L = [0] * (n1 + 1)
    R = [0] * (n2 + 1)

    for i in range(0, n1):
        L[i] = a[p + i]

    for j in range(0, n2):
        R[j] = a[q + 1 + j]

    L[n1] = math.inf
    R[n2] = math.inf

    i = 0
    j = 0

    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 mergesort(a, p, r):
    if p < r:
        q = (p + r)//2
        mergesort(a, p, q)
        mergesort(a, q+1, r)
        merge(a, p, q, r)

print("Before: {}\n".format(X))
mergesort(X, 0, len(X)-1)
print("After: {}".format(X))

运行这个版本就能得到正确的排序结果了~

备注:内容来源于stack exchange,提问作者Brady

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 18:43:14