python中的If语句只是通过改变条件的位置而起作用



我刚刚在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,s2,S))

该程序的输出为:

Traceback (most recent call last):
File "new.py", line 15, in <module>
print(mergesort(s1,s2,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

现在,只需在if语句中键入j == len(s2),程序就可以运行得很好:

def mergesort(s1,s2,S):
i,j = 0,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,5,7]
s1 = [2,3,4,6,8]
S = []
print(mergesort(s1,s2,S))

输出:[1, 2, 3, 4, 5, 6, 7, 8]

这真的让我很惊讶,因为这两个程序完全相同,但前一个给了我一个错误。

此外,有问题的程序在c++中运行良好:

#include <iostream>
using namespace std;
int main() { 
int s1[10] = { 2, 3, 4, 6, 8 }, s2[10] = { 1, 5, 7 }, s[20], i = 0, j = 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程序确实不正确:如果ji到达s1的末尾之前达到s2的长度,则if (i < len(s1) and s1[i] < s2[j]) or j == len(s2):将导致对s2[j]的越界访问。

修复方法是在(i < len(s1) and s1[i] < s2[j])之前测试j == len(s2),因为您正确地发现了自己。

C++程序也有同样的问题,但C++不会检测到越界访问。读取s2[3]只是有未定义的行为,在您的情况下只是返回一个未指定的值。由于j == 3,测试无论如何都会评估为true,因此算法会输出预期结果。

未定义的行为有时会产生预期的结果,而不会引起注意。但在分配较大的阵列上使用该算法可能会产生明显的副作用,例如分割错误。

最新更新