Python中的Quicksort实现

时间:2014-10-29 15:38:24

标签: python recursion quicksort

我试图在python中实现quicksort。但是,我的代码没有正确排序(不完全)。例如,在输入数组[5,3,4,2,7,6,1]上,我的代码输出[1,2,3,5,4,6,7]。因此,最终结果介于4和5.我承认我在python上有点生疏,因为我一直在研究ML(在此之前对python来说还是比较新的)。我已经了解了quicksort的其他python实现,以及关于python和quicksort的Stack Overflow上的其他类似问题,但我试图理解我自己写的这段代码有什么问题:

#still broken 'quicksort'

def partition(array):
    pivot = array[0]
    i = 1 
    for j in range(i, len(array)):
        if array[j] < array[i]:
            temp = array[i]
            array[i] = array[j]
            array[j] = temp
            i += 1
    array[0] = array[i]
    array[i] = pivot
    return array[0:(i)], pivot, array[(i+1):(len(array))]

def quick_sort(array):
    if len(array) <= 1: #if i change this to if len(array) == 1 i get an index out of bound error
        return array 

    low, pivot, high = partition(array)
    #quick_sort(low)
    #quick_sort(high)

    return quick_sort(low) + [pivot] + quick_sort(high)

array = [5,3,4,2,7,6,1]

print quick_sort(array)
# prints [1,2,3,5,4,6,7]

6 个答案:

答案 0 :(得分:6)

我对算法与quicksort的连接有点困惑。在快速排序中,您通常会将所有条目与数据透视表进行比较,因此您可以获得越来越高的组; quick_sort函数显然希望你的分区函数能够做到这一点。

但是,在分区函数中,您永远不会将任何内容与您命名pivot的值进行比较。所有比较都在索引i和j之间,其中j由for循环递增,如果发现一个项目乱序,则i递增。这些比较包括检查项目与自己。该算法更像是一种选择排序,其复杂性略逊于冒泡排序。所以只要左边有足够多的物品,你就会得到冒充左边的物品,第一件物品最后在最后一个被移动的物品去掉之后被抛弃;因为它从未与任何东西进行过比较,所以我们知道如果还有剩下的物品,这必须是乱序的,只是因为它取代了有序的物品。

稍微考虑一下,这些物品只是部分订购,因为一旦它被交换到左边,你就不会返回一个物品,并且只检查它所替换的物品(现在发现它已经被检查过了)无序)。我认为在没有索引争论的情况下编写预期函数会更容易:

def partition(inlist):
    i=iter(inlist)
    pivot=i.next()
    low,high=[],[]
    for item in i:
        if item<pivot:
            low.append(item)
        else:
            high.append(item)
    return low,pivot,high

答案 1 :(得分:2)

在尝试理解您自己的参考实现时,您可能会发现这些参考实现很有用。


返回新列表:

def qsort(array):
    if len(array) < 2:
        return array
    head, *tail = array
    less = qsort([i for i in tail if i < head])
    more = qsort([i for i in tail if i >= head])
    return less + [head] + more

对列表进行排序:

def quicksort(array):
    _quicksort(array, 0, len(array) - 1)

def _quicksort(array, start, stop):
    if stop - start > 0:
        pivot, left, right = array[start], start, stop
        while left <= right:
            while array[left] < pivot:
                left += 1
            while array[right] > pivot:
                right -= 1
            if left <= right:
                array[left], array[right] = array[right], array[left]
                left += 1
                right -= 1
        _quicksort(array, start, right)
        _quicksort(array, left, stop)

从可迭代中生成已排序的项目:

def qsort(sequence):
    iterator = iter(sequence)
    head = next(iterator)
    try:
        tail, more = chain(next(iterator), iterator), []
        yield from qsort(split(head, tail, more))
        yield head
        yield from qsort(more)
    except StopIteration:
        yield head

def chain(head, iterator):
    yield head
    yield from iterator

def split(head, tail, more):
    for item in tail:
        if item < head:
            yield item
        else:
            more.append(item)

答案 2 :(得分:1)

如果pivot最终需要保持在初始位置(b / c它是最低值),则无论如何都要将其与其他元素交换。

答案 3 :(得分:1)

阅读精细手册:

快速排序说明和python实现:

http://interactivepython.org/courselib/static/pythonds/SortSearch/TheQuickSort.html

答案 4 :(得分:1)

很抱歉,这应该是一条评论,但它的评论结构太复杂了。

查看数组为[7, 8]会发生什么:

  • pivot = 7
  • i = 1
  • for循环无效
  • array[0]变为array[i],即8
  • array[i]变为pivot即7
  • 您返回array[0:1]pivot[8, 7]7(忽略第三个子表达式)...

如果在连接中明确包含返回的pivot,则应在返回的数组中跳过它。

答案 5 :(得分:1)

好的我&#34;修复&#34;它,至少在 one 输入上我已经尝试过了(并且idk为什么...... python问题)

def partition(array):   
    pivot = array[0]   
    i = 1   
    for j in range(i, len(array)):   
        if array[j] < pivot:   
            temp = array[i]   
            array[i] = array[j]   
            array[j] = temp   
            i += 1   
    array[0] = array[i-1]  
    array[i-1] = pivot  
    return array[0:i-1], pivot, array[i:(len(array))]  


def quick_sort(array):  
    if len(array) <= 1:  
        return array   

    low, pivot, high = partition(array)  
    #quick_sort (low)  
    #quick_sort (high)  

    return quick_sort (low) + [pivot] + quick_sort (high)  



array = [5,3,4,2,7,6,1]  

print quick_sort(array)  
# prints [1,2,3,4,5,6,7]