这个问题让我很感兴趣,但我不确定这是否是学习numpy 的好方法。像这样的迭代过程并没有很好地利用数组的独特品质。它只是把它当作一个列表来对待,很明显它不太合适。
这是一个小列表的运行:
In [608]: alist=[3,2];arr=np.array(alist)
In [609]: mergeSort(alist)
Splitting [3, 2]
Splitting [3]
Merging [3]
Splitting [2]
Merging [2]
Merging [2, 3]
In [610]: mergeSort(arr)
Splitting [3 2]
Splitting [3]
Merging [3]
Splitting [2]
Merging [2]
Merging [2 2]
区别在于最后一个合并步骤。
我修改了代码以添加更多诊断打印
def mergeSort(alist):
print("Splitting ",alist)
if len(alist)>1:
mid = len(alist)//2
lefthalf = alist[:mid]
righthalf = alist[mid:]
mergeSort(lefthalf)
mergeSort(righthalf)
i=0
j=0
k=0
while i < len(lefthalf) and j < len(righthalf):
if lefthalf[i] < righthalf[j]:
alist[k]=lefthalf[i]
print('1',i,j,alist)
i=i+1
else:
alist[k]=righthalf[j]
print('2',i,j,alist)
j=j+1
k=k+1
while i < len(lefthalf):
alist[k]=lefthalf[i]
print('3',i,j,alist)
i=i+1
k=k+1
while j < len(righthalf):
alist[k]=righthalf[j]
print('4',i,j,alist)
j=j+1
k=k+1
print("Merging ",alist)
运行:
In [623]: alist=[3,2];arr=np.array(alist)
In [624]: mergeSort(alist)
Splitting [3, 2]
Splitting [3]
Merging [3]
Splitting [2]
Merging [2]
2 0 0 [2, 2]
3 0 1 [2, 3]
Merging [2, 3]
In [625]: mergeSort(arr)
Splitting [3 2]
Splitting [3]
Merging [3]
Splitting [2]
Merging [2]
2 0 0 [2 2]
3 0 1 [2 2]
Merging [2 2]
所以它在列表的 1 和 4 处“合并”,对于数组,它在 2 和 3 处“合并”。我们能弄清楚为什么吗?我怀疑if 测试存在差异。
看起来修复是:
lefthalf = alist[:mid].copy()
righthalf = alist[mid:].copy()
正如@duhamp 对数组所指出的,对lefthalf 的更改将更改righthalf。对于列表,lefthalf 和 righthalf 是 alist 的副本。但是索引alist[:mid] 会返回view,而不是副本。这是列表和数组之间的一个重要区别。
更重要的是,当您遇到 Python 代码(尤其是 numpy 代码)问题时,它有助于在可疑问题点添加诊断打印。您可以使用调试器,或者像我们一样临时修改代码。无论哪种方式,问题通常是您在编写代码时忽略的小细节。