做QuickSort是为了好玩,但有一点我不明白

时间:2011-06-17 04:04:53

标签: python quicksort

只是想确保你一个家庭作业问题。我这样做只是为了一些乐趣,可能是博客。

我根据此wiki page实施了“快速排序”的“就地”版本。

这是我写的代码:

# solution 2

def swap(arr, left, right):
    try:
        tmp = arr[left]
        arr[left] = arr[right]
        arr[right] = tmp
    except IndexError:
        print "!IndexError: left, right", left, right
        raise

def partition(arr, left, right, pindex):
    pivot = arr[pindex]
    swap(arr, right, pindex)
    npindex = left
    for i in range(left, right+1): # +1 so the last item is included
        if arr[i] < pivot:
            swap(arr, i, npindex)   
            npindex += 1
    swap(arr, npindex, right)
    return npindex

def qs(arr):
    qs2(arr, 0, len(arr)-1)
    return arr

def qs2(arr, left, right):
    if left < right:
        # midpoint = (right - left) / 2
        midpoint = left # this works.
        nindex = partition(arr, left, right, midpoint)
        qs2(arr, left, nindex-1)
        qs2(arr, nindex+1, right)

def test():
    test = [23, 45, 12, 1, 3, -9, 67, 122, 8, 2, 0]
    res = qs(list(test))
    print "start\t", test
    print "end\t", res

if __name__ == "__main__":
    test() 

我不明白的是,根据维基百科的说法,只要它位于维基百科中,枢轴的选择(函数 qs2 中的变量中点)可以是随机的界限。

但是,如果我只取中点(即(左+右)/ 2),则快速排序不起作用。使用值,它可以正常工作。

在理解算法时我是否遗漏了什么?

编辑:我刚刚意识到stackoverflow中有一个'quicksort'标记。如果之前已经问过这个问题,我的道歉并请告诉我。我将结束这个问题。与此同时,我将通过快速标记

来解决这些问题

2 个答案:

答案 0 :(得分:2)

你有midpoint = (right - left) / 2。我认为你的意思是(right + left) / 2,否则你的中点超出给定范围。

答案 1 :(得分:2)

  

由于存在整数溢出,选择枢轴元素也很复杂。如果被排序的子数组的边界索引足够大,则中间索引(左+右)/ 2的朴素表达式将导致溢出并提供无效的数据透视索引。这可以通过使用例如左+(右 - 左)/ 2来索引中间元素来克服,代价是更复杂的算术。在选择枢轴元素的其他一些方法中也会出现类似的问题。

应该是(left + right) / 2,而不是(right - left) / 2。维基百科解释说,使用left + (right - left) / 2是为了避免整数溢出。