我试图在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]
答案 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]
会发生什么:
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]