问题描述
我刚在python中遇到一个奇怪的问题: 下面是对合并排序算法的一种表示,如果尝试运行它,它会给我一个索引错误。
def mergesort(s1,s2,S):
i,j = 0,0
while i+j < len(s1)+len(s2):
if (i < len(s1) and s1[i] < s2[j]) or j == len(s2):
S.append(s1[i])
i += 1
else:
S.append(s2[j])
j += 1
return S
s2 = [1,5,7]
s1 = [2,3,4,6,8]
S = []
print(mergesort(s1,S))
该程序的输出为:
Traceback (most recent call last):
File "new.py",line 15,in <module>
print(mergesort(s1,S))
File "new.py",line 4,in mergesort
if (i < len(s1) and s1[i] < s2[j]) or j == len(s2):
IndexError: list index out of range
现在只需在j == len(s2)
语句中键入if
即可,程序运行正常:
def mergesort(s1,0
while i+j < len(s1)+len(s2):
if j == len(s2) or (i < len(s1) and s1[i] < s2[j]):
S.append(s1[i])
i += 1
else:
S.append(s2[j])
j += 1
return S
s2 = [1,S))
输出:[1,2,7,8]
这真让我感到惊讶,因为这两个程序完全相同,但是前一个给我一个错误。
此外,有问题的程序在c ++中可以正常运行:
#include <iostream>
using namespace std;
int main() {
int s1[10] = { 2,8 },s2[10] = { 1,7 },s[20],i = 0,x = 0;
while (i + j < 8) {
if ((i < 5 && s1[i] < s2[j]) || j == 3) {
s[x++] = s1[i];
i++;
} else {
s[x++] = s2[j];
j++;
}
}
for (int i = 0; i < 8; i++) {
cout << s[i];
}
return 0;
}
输出:12345678
为什么在python中给我一个错误的程序在c ++中运行完全正常?
python的if
语句与c ++的if
语句工作不同吗?
解决方法
第一个python程序确实不正确:如果if (i < len(s1) and s1[i] < s2[j]) or j == len(s2):
在s2[j]
之前达到j
的长度,s2
将导致对i
的无限制访问。到达s1
的结尾。
解决方法是在您正确发现自己之前,先测试j == len(s2)
之前 (i < len(s1) and s1[i] < s2[j])
。
C ++程序具有相同的问题,但是C ++不会检测到超出范围的访问。读s2[3]
只是具有未定义的行为,在您的情况下,只会返回未指定的值。无论如何,由于j == 3
,该测试将评估为true,因此算法将输出预期结果。
未定义的行为有时会产生预期的结果,而不会引起注意。但是在更大的分配数组上使用该算法可能会产生明显的副作用,例如分段错误。