作为一个相当新的编程人员,我正在尝试在Python中实现quicksort。但是,我试图以某种方式实现它,这似乎不是最常见的方式。我正在使用CS50在此视频中解释的技术:https://www.youtube.com/watch?v=aQiWF4E8flQ
此版本的算法在数组末尾选择一个数据透视表,在开头放置一个“墙”并开始迭代列表。当它找到一个小于枢轴的项目时,它会将该项目与墙壁右侧的项目交换,并将墙壁向右移动一个位置。当所有物品与枢轴相比较时,它将枢轴放在墙上,墙壁向右移动一个位置。这一直持续到墙壁位于阵列的末端。
到目前为止,我已经想出了这个:
def quicksort(alist):
quicksort_helper(alist)
print alist
def quicksort_helper(alist):
wall = 0
while wall < (len(alist) - 1):
pivot = len(alist) - 1
for current in range(wall, pivot):
if alist[current] < alist[pivot]:
alist[current], alist[wall] = alist[wall], alist[current]
wall = wall + 1
alist[wall], alist[pivot] = alist[pivot], alist[wall]
wall = wall + 1
当我尝试运行程序时,我一直遇到墙和数据透视的数组索引问题,因为这是我得到的错误消息:
IndexError: list index out of range
我已经尝试了很多索引,但我似乎无法弄明白。
答案 0 :(得分:3)
Quicksort的工作方式如下:首先对数组进行分区,以便有三个子数组:左数组包含所有小于pivot的元素,无序。中间的“数组”只是一个元素,即枢轴*。右侧数组包含大于或等于数据透视表的所有元素。
现在已知枢轴处于正确位置。然后,您必须对左右子阵列进行排序。
分区是在墙的帮助下完成的。枢轴的位置是固定的;它始终是最合适的元素。然后,您将每个元素与枢轴相对应,如果它更小,则将其移动到墙的左侧。您必须将墙壁向右移动,以便为元素腾出空间。
在查看了所有元素后,您有三个子阵列,但顺序错误:左,右,枢轴。 (墙壁是左右子阵列之间的屏障。)为了使其按正确的顺序排列,请使用枢轴将元素交换到墙的右侧,但不要移动墙壁。在分区循环之后,这只需要完成一次。 (请注意,如果枢轴恰好是最大的元素,那么您可以将枢轴与自身交换,如果浪费的话,这是可以的。)
您的算法使用0并且数组的ength作为绑定。这适用于整个阵列。如果要对子阵列进行排序,则必须调整这些边界。因此,最好将边界传递给快速排序助手,以便您可以递归。 (使下限为包含且上限为独占,这是sutomary,正如索引len(a)
在索引从零开始时超出a
的有效索引范围一样。)
这是一个有效的解决方案:
def quicksort(alist):
quicksort_helper(alist, 0, len(alist))
def quicksort_helper(alist, l, r):
if l < r:
wall = l
pivot = r - 1
for current in range(wall, pivot):
if alist[current] < alist[pivot]:
alist[current], alist[wall] = alist[wall], alist[current]
wall = wall + 1
alist[wall], alist[pivot] = alist[pivot], alist[wall]
quicksort_helper(alist, l, wall)
quicksort_helper(alist, wall + 1, r)
*)有一个三向Quicksort将相同值的所有支点组合在一起,以便通过只有少数独特元素的数组来改善Quicksort的糟糕性能。
答案 1 :(得分:0)
在某些情况下,alist[wall], alist[pivot] = alist[pivot], alist[wall]
值增加后会执行第wall
行并导致len(alist)
触发IndexError
。
您可以使用pdb
调试代码,在函数中添加行import pdb;pdb.set_trace()
以跟踪变量值。