用Python实现快速排序

114

我完全是Python的新手,正在尝试在其中实现快速排序算法。 请问是否有人能帮我完成我的代码呢?

我不知道如何将这三个数组连接起来并打印出它们。

def sort(array=[12,4,5,6,7,3,1,15]):
    less = []
    equal = []
    greater = []

    if len(array) > 1:
        pivot = array[0]
        for x in array:
            if x < pivot:
                less.append(x)
            if x == pivot:
                equal.append(x)
            if x > pivot:
                greater.append(x)
            sort(less)
            sort(pivot)
            sort(greater)

要合并列表,您可以使用加号运算符 my_list = list1 + list2 + ...。或者将列表解包到新列表中 my_list = [*list1, *list2] - Mark Mishyn
2
快速排序算法应该是一种原地算法,但你的代码并不是。此外,追加操作不一定在常数时间内执行。 - user1196549
37个回答

0
def is_sorted(arr): #check if array is sorted
    for i in range(len(arr) - 2):
        if arr[i] > arr[i + 1]:
            return False
    return True

def qsort_in_place(arr, left, right): #arr - given array, #left - first element index, #right - last element index
    if right - left < 1: #if we have empty or one element array - nothing to do
        return
    else:
        left_point = left #set left pointer that points on element that is candidate to swap with element under right pointer or pivot element
        right_point = right - 1 #set right pointer that is candidate to swap with element under left pointer

        while left_point <= right_point: #while we have not checked all elements in the given array
            swap_left = arr[left_point] >= arr[right] #True if we have to move that element after pivot
            swap_right = arr[right_point] < arr[right] #True if we have to move that element before pivot

            if swap_left and swap_right: #if both True we can swap elements under left and right pointers
                arr[right_point], arr[left_point] = arr[left_point], arr[right_point]
                left_point += 1
                right_point -= 1
            else: #if only one True we don`t have place for to swap it
                if not swap_left: #if we dont need to swap it we move to next element
                    left_point += 1
                if not swap_right: #if we dont need to swap it we move to prev element
                    right_point -= 1

        arr[left_point], arr[right] = arr[right], arr[left_point] #swap left element with pivot

        qsort_in_place(arr, left, left_point - 1) #execute qsort for left part of array (elements less than pivot)
        qsort_in_place(arr, left_point + 1, right) #execute qsort for right part of array (elements most than pivot)

def main():
    import random
    arr = random.sample(range(1, 4000), 10) #generate random array
    print(arr)
    print(is_sorted(arr))
    qsort_in_place(arr, 0, len(arr) - 1)
    print(arr)
    print(is_sorted(arr))

if __name__ == "__main__":
    main()

1
请提供一些解释抱歉,您的请求不太清楚。请提供需要翻译的具体内容和所需的解释,以便我能够更好地为您服务。谢谢! - Harshith Rai

0
我发现这些解决方案难以阅读,而且大多数似乎没有考虑到数组中的重复元素。
这是我的快速排序算法:
def qs(lst):
  if len(lst) <= 1:
    return lst

  pivot = lst[len(lst)//2]
  sml = [x for x in lst if x < pivot]
  mid = [x for x in lst if x == pivot]
  big = [x for x in lst if x > pivot]

  return qs(sml) + mid + qs(big)

这是使用该算法的输入和输出示例:
lst = [1, 9, 8, 4, 5, 3, 5, 7]
qs(lst)
>>> [1, 3, 4, 5, 5, 7, 8, 9]

-1

我将使用numpy库完成快速排序。我认为这是一个非常有用的库。他们已经实现了快排算法,但你也可以实现自定义方法。

import numpy
array = [3,4,8,1,2,13,28,11,99,76] #The array what we want to sort

indexes = numpy.argsort( array , None, 'quicksort', None)
index_list = list(indexes)

temp_array = []

for index in index_list:
    temp_array.append( array[index])

array = temp_array

print array #it will show sorted array

-1

不要使用三个不同的数组来存储小于、等于和大于的元素,而是尝试传统的概念(分区方法):

http://pythonplanet.blogspot.in/2015/08/quick-sort-using-traditional-partition.html

这是不使用任何内置函数的代码。
分区功能 -
def partitn(alist, left, right):  
 i=left  
 j=right  
 mid=(left+right)/2   

pivot=alist[mid]  
while i <= j:  
    while alist[i] < pivot:  
        i=i+1   

    while alist[j] > pivot:  
        j=j-1   

    if i <= j:  
        temp = alist[i]  
        alist[i] = alist[j]  
        alist[j] = temp  
        i = i + 1   
        j = j - 1   

欢迎来到 Stack Overflow。建议您在回答中包含代码,因为链接可能会随着时间的推移而失效。 - rnevius
2
欢迎来到 Stack Overflow。在 Python 中,一种好的惯用语是在一行中交换对象而不引入临时名称,如下所示:alist[i],alist[j] = alist[j],alist[i] - alisianoi

-2
def quick_sort(list):
    if len(list) ==0:
        return []

    return  quick_sort(filter( lambda item: item < list[0],list)) + [v for v in list if v==list[0] ]  +  quick_sort( filter( lambda item: item > list[0], list))

-2

原地排序

def qsort(a, b=0, e=None):
    # partitioning
    def part(a, start, end):
        p = start
        for i in xrange(start+1, end):
            if a[i] < a[p]:
                a[i], a[p+1] = a[p+1], a[i]
                a[p+1], a[p] = a[p], a[p+1]
                p += 1
        return p

    if e is None:
        e = len(a)
    if e-b <= 1: return

    p = part(a, b, e)
    qsort(a, b, p)
    qsort(a, p+1, e)

不使用递归:

deq = collections.deque()
deq.append((b, e))
while len(deq):
    el = deq.pop()
    if el[1] - el[0] > 1:
        p = part(a, el[0], el[1])
        deq.append((el[0], p))
        deq.append((p+1, el[1]))

1
请提供一些解释或背景信息,而不是简单的代码。 - m02ph3u5
这很简单。我们选择任何一个元素,首先以第一个为例。然后将列表分成两部分(左边是小于选定元素的部分,右边是大于选定元素的部分)。对左右两部分重复此操作,依此类推。 - dimonb

-3
def quicksort(items):
    if not len(items) > 1:
        return items
    items, pivot = partition(items)
    return quicksort(items[:pivot]) + [items[pivot]] + quicksort(items[pivot + 1:])


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

1
虽然这段代码片段可能回答了问题,但它没有提供任何上下文来解释如何或为什么。请考虑添加一两句话来解释你的答案。 - brandonscript

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接