实现快速排序CS50样式时的IndexError

时间:2016-03-08 16:48:52

标签: python algorithm sorting computer-science quicksort

作为一个相当新的编程人员,我正在尝试在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

我已经尝试了很多索引,但我似乎无法弄明白。

2 个答案:

答案 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()以跟踪变量值。