Python ile Hızlı Sırala
Gerçek hayatta, her zaman Python tarafından sağlanan yerleşik sıralamayı kullanmalıyız. Bununla birlikte, hızlı sıralama algoritmasını anlamak öğreticidir.
Buradaki amacım, konuyu, okuyucu tarafından referans materyallere geri dönmek zorunda kalmadan kolayca anlaşılacak ve kopyalanabilecek şekilde parçalamaktır.
Hızlı sıralama algoritması esasen aşağıdaki gibidir:
- Bir pivot veri noktası seçin.
- Pivotun altındaki (altındaki) tüm veri noktalarını pivotun altındaki bir konuma taşıyın - pivottan büyük veya ona eşit olanları (yukarısında) bir konuma taşıyın.
- Algoritmayı pivotun üstündeki ve altındaki alanlara uygulayın
Veriler rastgele dağıtılmışsa, pivot olarak ilk veri noktasını seçmek rastgele bir seçime eşdeğerdir.
Okunabilir örnek:
İlk olarak, ara değerlere işaret etmek için yorumlar ve değişken adları kullanan okunabilir bir örneğe bakalım:
def quicksort(xs):
"""Given indexable and slicable iterable, return a sorted list"""
if xs:
pivot = xs[0]
below = [i for i in xs[1:] if i < pivot]
above = [i for i in xs[1:] if i >= pivot]
return quicksort(below) + [pivot] + quicksort(above)
else:
return xs
Burada gösterilen algoritmayı ve kodu yeniden ifade etmek için - pivotun üzerindeki değerleri sağa ve pivotun altındaki değerleri sola taşırız ve daha sonra bu bölümleri daha fazla sıralanmak üzere aynı işleve aktarırız.
Golf oynadı:
Bu 88 karaktere golf oynanabilir:
q=lambda x:x and q([i for i in x[1:]if i<=x[0]])+[x[0]]+q([i for i in x[1:]if i>x[0]])
Oraya nasıl geldiğimizi görmek için önce okunabilir örneğimizi alın, yorumları ve dokümanları kaldırın ve pivotu yerinde bulun:
def quicksort(xs):
if xs:
below = [i for i in xs[1:] if i < xs[0]]
above = [i for i in xs[1:] if i >= xs[0]]
return quicksort(below) + [xs[0]] + quicksort(above)
else:
return xs
Şimdi aşağıda ve yukarıda, yerinde bulun:
def quicksort(xs):
if xs:
return (quicksort([i for i in xs[1:] if i < xs[0]] )
+ [xs[0]]
+ quicksort([i for i in xs[1:] if i >= xs[0]]))
else:
return xs
Şimdi, bunun and
yanlışsa önceki öğeyi döndürdüğünü bildiğimiz halde, eğer doğruysa, aşağıdaki öğeyi değerlendirir ve döndürür:
def quicksort(xs):
return xs and (quicksort([i for i in xs[1:] if i < xs[0]] )
+ [xs[0]]
+ quicksort([i for i in xs[1:] if i >= xs[0]]))
Lambdalar tek bir ifade döndürdüğünden ve tek bir ifadeye sadeleştirdiğimizden (daha okunamaz hale gelse bile) artık bir lambda kullanabiliriz:
quicksort = lambda xs: (quicksort([i for i in xs[1:] if i < xs[0]] )
+ [xs[0]]
+ quicksort([i for i in xs[1:] if i >= xs[0]]))
Örneğimize indirgemek için, işlev ve değişken adlarını bir harfe kısaltın ve gerekli olmayan boşlukları kaldırın.
q=lambda x:x and q([i for i in x[1:]if i<=x[0]])+[x[0]]+q([i for i in x[1:]if i>x[0]])
Çoğu kod golfü gibi bu lambda'nın da oldukça kötü bir stil olduğunu unutmayın.
Hoare Bölümleme şemasını kullanarak yerinde Hızlı Sıralama
Önceki uygulama, birçok gereksiz ekstra liste yaratır. Bunu yerinde yapabilirsek, yer israfından kaçınırız.
Aşağıdaki uygulama , Wikipedia'da daha fazla bilgi edinebileceğiniz Hoare bölümleme şemasını kullanır (ancak görünüşe göre partition()
, do-while yerine while döngüsü semantiğini kullanarak ve daraltma adımlarını sonuna taşıyarak çağrı başına 4'e kadar fazlalık hesaplamayı kaldırdık . dış while döngüsü.).
def quicksort(a_list):
"""Hoare partition scheme, see https://en.wikipedia.org/wiki/Quicksort"""
def _quicksort(a_list, low, high):
if low < high:
p = partition(a_list, low, high)
_quicksort(a_list, low, p)
_quicksort(a_list, p+1, high)
def partition(a_list, low, high):
pivot = a_list[low]
while True:
while a_list[low] < pivot:
low += 1
while a_list[high] > pivot:
high -= 1
if low >= high:
return high
a_list[low], a_list[high] = a_list[high], a_list[low]
low += 1
high -= 1
_quicksort(a_list, 0, len(a_list)-1)
return a_list
Yeterince test edip etmediğimden emin değilim:
def main():
assert quicksort([1]) == [1]
assert quicksort([1,2]) == [1,2]
assert quicksort([1,2,3]) == [1,2,3]
assert quicksort([1,2,3,4]) == [1,2,3,4]
assert quicksort([2,1,3,4]) == [1,2,3,4]
assert quicksort([1,3,2,4]) == [1,2,3,4]
assert quicksort([1,2,4,3]) == [1,2,3,4]
assert quicksort([2,1,1,1]) == [1,1,1,2]
assert quicksort([1,2,1,1]) == [1,1,1,2]
assert quicksort([1,1,2,1]) == [1,1,1,2]
assert quicksort([1,1,1,2]) == [1,1,1,2]
Sonuç
Bu algoritma genellikle bilgisayar bilimleri derslerinde öğretilir ve iş görüşmeleri istenir. Özyineleme ve böl ve yönet hakkında düşünmemize yardımcı olur.
Quicksort Python'da çok pratik değildir çünkü yerleşik zaman sıralaması algoritmamız oldukça verimli ve özyineleme limitlerimiz var. Listeleri yerinde list.sort
sıralamayı veya yeni sıralı listeler oluşturmayı bekleriz sorted
- her ikisi de bir key
ve reverse
argüman alır.
my_list = list1 + list2 + ...
. Veya listeleri yeni listeyemy_list = [*list1, *list2]