简体   繁体   English

快速排序,在这个就地实现中我哪里出错了?

[英]Quicksort, where am I going wrong in this in-place implementation?

I'm trying to implement in-place partitioning for quicksort, but am stuck.我正在尝试为快速排序实现就地分区,但被卡住了。

This is my code:这是我的代码:

def quicksort(b):
    print("Passed b is : ",b)
    if len(b)<=1 :
        return
    p=b[0]

    i=1
    for j in range(0,len(b)):
        if b[j]<p:
            temp=b[j]
            b[j]=b[i]
            b[i]=temp
            i=i+1
    temp2=b[0]
    b[0]=b[i-1]
    b[i-1]=temp2
    print("Parially sorted b is :",b)
    print("Left half is :", b[:i-1], " Pivot is ",b[i-1], " Right half is ",b[i:])
    print("\n")
    quicksort(b[:i-1])
    quicksort(b[i:])

b=[3,1,7,2,6,5,9]
quicksort(b)
print(b)

What am I missing?我错过了什么?

First of all, please use whitespace around operators so your code is comprehensible.首先,请在运算符周围使用空格,以便您的代码易于理解。 Use black if you aren't sure how to format your code.如果您不确定如何格式化代码,请使用黑色

As mentioned in the comments , your implementation isn't in-place .正如评论中提到的,您的实现不是就地的 An in-place algorithm is one that doesn't use auxiliary space and instead moves the elements around on the existing data structure.就地算法是一种不使用辅助空间而是在现有数据结构上移动元素的算法。 Slicing (the [:] syntax) makes a copy of your list, an immediate breach of contract.切片( [:]语法)会复制您的列表,立即违反合同。

You probably got steered off course beginning with your function parameters: def quicksort(b): .您可能从函数参数开始就偏离了方向: def quicksort(b): This pretty much forces you to slice.这几乎迫使你切片。 The correct parameters for an in-place algorithm are def quicksort(lst, start_index, end_index): , where the indices designate the subsequence of the list that a particular quicksort call should operate on.就地算法的正确参数是def quicksort(lst, start_index, end_index): ,其中索引指定特定快速排序调用应操作的列表的子序列。 Each function call must not touch any other portion of the list outside the designated range.每个函数调用不得触及指定范围之外的列表的任何其他部分。 The code should set all indices relative to these parameters.代码应设置与这些参数相关的所有索引。

Of course, you don't want to burden the client with having to specify these initial indices correctly, so the normal approach is to use default arguments:当然,您不想让客户端承担必须正确指定这些初始索引的负担,因此通常的方法是使用默认参数:

def quicksort(lst, start_index=0, end_index=None):
    if end_index is None:
        end_index = len(lst)
    ...

...or a wrapper call: ...或包装器调用:

def quicksort(lst):
    def qsort(lst, start_index, end_index):
        ...

    qsort(lst, 0, len(lst))

With that in place, you're ready for the logic, which looks generally OK.有了这些,你就可以准备好逻辑了,看起来一般都可以。 After a cleanup and some spot tests, we have:经过清理和一些现场测试后,我们有:

def quicksort(lst):
    def qsort(lst, start_i, end_i):
        if end_i - start_i <= 1:
            return

        pivot = lst[start_i]
        i = start_i + 1

        for j in range(start_i + 1, end_i):
            if lst[j] < pivot:
                lst[j], lst[i] = lst[i], lst[j]
                i += 1

        lst[i-1], lst[start_i] = lst[start_i], lst[i-1]
        qsort(lst, start_i, i - 1)
        qsort(lst, i, end_i)

    qsort(lst, 0, len(lst))


if __name__ == "__main__":
    from random import randint

    for _ in range(3000):
        lst = [randint(-3000, 3000) for _ in range(1000)]
        cpy = lst[:]
        quicksort(lst)

        if sorted(cpy) != lst:
            print("FAIL")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM