簡體   English   中英

在 Python 中排序的最快方法

[英]Fastest way to sort in Python

在 Python 中對大於 0 且小於 100000 的整數數組進行排序的最快方法是什么? 但不使用像 sort 這樣的內置函數。

我正在考慮根據輸入大小組合 2 項運動功能的可能性。

如果您對漸近時間感興趣,則對sort或radix排序進行計數可以提供良好的性能。

但是,如果您對掛鍾時間感興趣,則需要使用特定數據集比較不同算法之間的性能,因為不同算法對不同數據集的執行方式會有所不同。 在這種情況下,總是值得嘗試快速排序:

def qsort(inlist):
    if inlist == []: 
        return []
    else:
        pivot = inlist[0]
        lesser = qsort([x for x in inlist[1:] if x < pivot])
        greater = qsort([x for x in inlist[1:] if x >= pivot])
        return lesser + [pivot] + greater

來源: http//rosettacode.org/wiki/Sorting_algorithms/Quicksort#Python

由於您知道數字的范圍,因此可以使用“ 計數排序” ,它在時間上是線性的。

Radix排序理論上以線性時間運行(排序時間大致與數組大小成正比增長),但是實際上,除非您要對大量數組進行排序,否則Quicksort可能更適合。

如果要使快速排序更快一些,可以在數組大小變小時使用插入排序]。

理解算法復雜性和Big-O表示法的概念也可能會有所幫助。

Python的早期版本使用samplesort (具有大樣本量的samplesort的變體)和二進制插入排序的混合作為內置排序算法。 事實證明這有些不穩定。 從python 2.3開始的S0使用adaptive mergesort算法。

mergesort的順序(平均值)= O(nlogn) mergesort的順序(最差)= O(nlogn) 但是快速排序的順序(最差)= n * 2

如果您使用list=[ .............. ]

list.sort()使用mergesort algorithm.

對於排序算法之間的比較,您可以閱讀Wiki

對於細節比較補償

我們可以使用字典來進行計數排序,以最大程度地減少額外的空間使用,並保持較低的運行時間。 對於小尺寸的輸入數組,由於python vs C的實現開銷,計數排序要慢得多。 當數組(COUNT)的大小約為100萬時,計數排序開始超過常規排序。

如果您真的想為較小的輸入提供巨大的加速,請在C中實現count排序,然后從Python調用它。

(修復了Aaron(+1)幫助捕獲的錯誤...)下面的僅python實現比較了兩種方法...

import random
import time

COUNT = 3000000

array = [random.randint(1,100000) for i in range(COUNT)]
random.shuffle(array)

array1 = array[:]

start = time.time()
array1.sort()
end = time.time()
time1 = (end-start)
print 'Time to sort = ', time1*1000, 'ms'

array2 = array[:]

start = time.time()
ardict = {}
for a in array2:
    try:
        ardict[a] += 1
    except:
        ardict[a] = 1

indx = 0
for a in sorted(ardict.keys()):
    b = ardict[a]
    array2[indx:indx+b] = [a for i in xrange(b)]
    indx += b

end = time.time()
time2 = (end-start)
print 'Time to count sort = ', time2*1000, 'ms'

print 'Ratio =', time2/time1

我可能會晚一點,但是有一篇有趣的文章比較了https://www.linkedin.com/pulse/sorting-ficiently-python-lakshmi-prakash

主要優點之一是,盡管默認排序效果很好,但我們可以使用Quicksort的編譯版本做得更好。 這需要Numba程序包。

在此處輸入圖片說明

這是Github存儲庫的鏈接: https : //github.com/lprakash/Sorting-Algorithms/blob/master/sorts.ipynb

def sort(l):
    p = 0
    while(p<len(l)-1):
        if(l[p]>l[p+1]):
            l[p],l[p+1] = l[p+1],l[p]
            if(not(p==0)):
                p = p-1
        else:
            p += 1
    return l

這是我創建的算法,但是速度很快。 只需將sort(l)作為您要排序的列表即可。

內置函數是最好的,但是由於您無法使用它們,因此請查看以下內容:

http://en.wikipedia.org/wiki/Quicksort

@fmark我針對來自http://rosettacode.org/wiki/Sorting_algorithms/Quicksort#Python和最高答案的python quicksorts編寫的python merge-sort實現的一些基准測試。

  1. 列表的大小與列表中數字的大小無關

合並排序獲勝,但是它使用內置int()

import numpy as np
x = list(np.random.rand(100))


# TEST 1, merge_sort 
def merge(l, p, q, r):
    n1 = q - p + 1
    n2 = r - q
    left = l[p : p + n1]
    right = l[q + 1 : q + 1 + n2]

    i = 0
    j = 0
    k = p
    while k < r + 1:
        if i == n1:
            l[k] = right[j]
            j += 1
        elif j == n2:
            l[k] = left[i]
            i += 1
        elif  left[i] <= right[j]:
            l[k] = left[i]
            i += 1
        else:
            l[k] = right[j]
            j += 1
        k += 1

def _merge_sort(l, p, r):
    if p < r:
        q = int((p + r)/2)
        _merge_sort(l, p, q)
        _merge_sort(l, q+1, r)
        merge(l, p, q, r)

def merge_sort(l):
    _merge_sort(l, 0, len(l)-1)

# TEST 2
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)

# TEST 3
def qsort(inlist):
    if inlist == []: 
        return []
    else:
        pivot = inlist[0]
        lesser = qsort([x for x in inlist[1:] if x < pivot])
        greater = qsort([x for x in inlist[1:] if x >= pivot])
        return lesser + [pivot] + greater

def test1():
    merge_sort(x)

def test2():
    quicksort(x)

def test3():
    qsort(x)

if __name__ == '__main__':
    import timeit
    print('merge_sort:', timeit.timeit("test1()", setup="from __main__ import test1, x;", number=10000))
    print('quicksort:', timeit.timeit("test2()", setup="from __main__ import test2, x;", number=10000))
    print('qsort:', timeit.timeit("test3()", setup="from __main__ import test3, x;", number=10000))

桶大小為 1 的桶排序。內存為 O(m),其中 m = 被排序的值的范圍。 運行時間為 O(n),其中 n = 排序的項目數。 當用於記錄計數的整數類型有界時,如果任何值出現超過 MAXINT 次,則此方法將失敗。

def sort(items):
  seen = [0] * 100000
  for item in items:
    seen[item] += 1
  index = 0
  for value, count in enumerate(seen):
    for _ in range(count):
      items[index] = value
      index += 1

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM