铲斗排序比Quicksort快

时间:2014-09-05 16:22:02

标签: python algorithm sorting

我在Python中创建了一个程序,该程序对包含5000个不同算法的数字的随机创建列表进行排序并比较时间。
Quicksort 通常比 Bucket sort 慢,为什么? 我认为Quicksort更快。

这是我的计划:

快速排序

def quicksort(seq):
    wall = 0
    pivot = seq[-1]
    for index, num in enumerate(seq):
        if num < pivot:
            seq[wall], seq[index] = seq[index], seq[wall]
            wall += 1
    seq[wall], seq[-1] = seq[-1], seq[wall]
    left = seq[:wall]
    if len(left) > 0:
        left = quicksort(left)
    right = seq[(wall + 1):]
    if len(right) > 0:
        right = quicksort(right)
    return left + [pivot] + right

Bucket sort

def bucket_sort(seq):
    biggest = 0
    for number in seq:
        if number > biggest:
            biggest = number
    buckets = []
    buckets.append([]) * (biggest / 10 + 1)
    for number in seq:
        buckets[number / 10].append(number)
    for index, bucket in enumerate(buckets):
        #Using quicksort to sort individual buckets
        buckets[index] = quicksort(bucket)
    new_list = [number for number in bucket for bucket in buckets]
    return new_list

3 个答案:

答案 0 :(得分:3)

如您所知,当您需要对很多元素进行排序时,快速排序是一个不错的选择。当您使用较小的集合时, Bucket Sort 可能是更好的选择。

Quicksort是一个分而治之算法的例子,它在之前完成了它的主要工作 递归调用,分割数据(使用分区)。在这种情况下,你的算法不是pythonic,也不是一个真正的快速排序算法!

因此我建议使用此算法代替:

def quicksort(seq):
    if len(seq) <= 1: 
        return seq
    lo, pi, hi = partition(seq)
    return quicksort(lo) + [pi] + quicksort(hi)

def partition(seq):
    pi, seq = seq[0], seq[1:]
    lo = [x for x in seq if x <= pi]
    hi = [x for x in seq if x > pi]
    return lo, pi, hi

答案 1 :(得分:2)

好的。首先,尽量不要命名已具有键名的变量,例如list。 list已内置于python中,并将覆盖过去被视为list的内容。

Bucket sort
我们假设我们有一个列表[29, 25, 3, 49, 9, 37, 21, 43]。使用存储桶排序,它会将其中一些值分组到存储区中,如下所示。

buckets

此案例中的分组值为[0,9][10-19][20-29][30-39][40-49]。 一旦创建了存储桶,就会在每个存储桶上使用排序算法,此算法可以是包括存储桶排序在内的任何内容。通常在桶排序中,算法将查看最高有效位并将其与另一个值的最高有效位进行比较,如果它们匹配,则将逐位逐滴地逐滴向下,直到它清楚哪个更大。这种类型的排序也可以用于字符,列表等。

最重要位(MSB)比较的快速示例: 3对9 二进制3是0011 二进制9是1001
在这种情况下从最左边的位开始,我们看到0为3,1为9,因此9更大 在对每个铲斗进行分类后,您将得到以下结果:
sorted buckets

Bucket sort的另一个例子可以在这里找到:Bucket Sort

Quicksort
通过快速排序,您可以选择一个枢轴元素 之后,重新排序数组,以便任何值小于枢轴的元素位于枢轴之前,任何值大于枢轴的元素都位于枢轴之后。
然后递归地执行到具有较小值的元素列表和具有较大值的列表。这个概念非常简单,但如果您不熟悉算法,那么选择一个好的支点也是一个挑战。

现在......为什么铲斗排序更快?
由于快速排序涉及的递归和枢轴点,您通常只限于O(n*log(n))

由于bucket sort中的桶的排序算法是MSB,因此该排序算法的时间复杂度为O(n+k)

现在,如果您选择较慢的排序算法来对存储桶排序中的存储桶进行排序,则可以让quicksort更快。

我知道这是一个非常高级别的概述,可能有点令人困惑,但希望它足以帮助您理解为什么存储桶排序比快速排序更快,而且快速排序可以比桶排序更快。< / p>

答案 2 :(得分:0)

https://stackoverflow.com/posts/25690572/revisions

由于此处为快速排序提供了代码,因此使用了两个新列表。即lo&hi

  

QuickSort的特长是 不使用新的MemorySpace

因此,回答的代码是一个很好的解决方案,但是它确实打破了逻辑差异b / w快速合并合并

(该代码是修改后的版本,摘自下面的源代码)

def quickSort(alist):
    quickSortHelper(alist,0,len(alist)-1)

def quickSortHelper(alist,first,last):
    if first<last:
        splitpoint = partition(alist,first,last)
        quickSortHelper(alist,first,splitpoint-1)
        quickSortHelper(alist,splitpoint+1,last)

def partition(alist,first,last):
    pivotvalue = alist[first]
    leftmark,rightmark = first+1,last
    done = False
    while not done:
        while leftmark <= rightmark and alist[leftmark] <= pivotvalue:
            leftmark = leftmark + 1

        while alist[rightmark] >= pivotvalue and rightmark >= leftmark:
            rightmark = rightmark -1

        if rightmark < leftmark:
            done = True
        else:
            alist[first],alist[rightmark] = alist[rightmark],alist[first]

    alist[first],alist[rightmark] = alist[rightmark],alist[first]
    return rightmark

alist = [54,26,93,17,77,31,44,55,20]
quickSort(alist)
print(alist)

来源:https://runestone.academy/runestone/static/pythonds/SortSearch/TheQuickSort.html