Java'nın Arrays.sort yöntemi neden farklı türler için iki farklı sıralama algoritması kullanıyor?


121

Java 6'nın Arrays.sortyöntemi, ilkel diziler için Quicksort kullanır ve nesne dizileri için birleştirme sıralaması kullanır. Quicksort'un çoğu zaman birleşik sıralamadan daha hızlı olduğuna ve daha az belleğe mal olduğuna inanıyorum. Her iki algoritma da O (n log (n)) olmasına rağmen deneylerim bunu destekliyor. Öyleyse neden farklı türler için farklı algoritmalar kullanılıyor?


14
Quicksort en kötü durumu N ^ 2 değil NlogN'dir.
codaddict

Bekle, bir dizi Integers filan varsa ne olur ?
Tikhon Jelvis

1
Bu anlatmadık mı içinde okuduğunuz kaynağı?
Humphrey Bogart

5
Bu bilgiler artık güncel değil. Java SE 7'den başlayarak, MergeSort, TimSort ile değiştirildi ve QuickSort, Dual-Pivot QuickSort ile değiştirildi . Java API belgelerine bağlantılar için aşağıdaki cevabıma bakın.
Will Byrne

Yanıtlar:


200

En olası neden: hızlı sıralama sabit değildir , yani eşit girişler sıralama sırasında göreceli konumlarını değiştirebilir; diğer şeylerin yanı sıra, bu, önceden sıralanmış bir diziyi sıralarsanız, değişmeden kalmayabileceği anlamına gelir.

İlkel türlerin kimliği olmadığından (aynı değere sahip iki girişi ayırt etmenin bir yolu yoktur), bu onlar için önemli değildir. Ancak referans türleri için bazı uygulamalarda sorunlara neden olabilir. Bu nedenle, bunlar için kararlı bir birleştirme sıralaması kullanılır.

OTOH, ilkel türler için (garantili n * log (n)) kararlı birleştirme sıralaması kullanmamanın bir nedeni, dizinin bir klonunu oluşturmayı gerektirmesi olabilir. Başvurulan nesnelerin genellikle başvuru dizisinden çok daha fazla bellek kapladığı başvuru türleri için, bu genellikle önemli değildir. Ancak ilkel türler için diziyi klonlamak bellek kullanımını iki katına çıkarır.


1
Quicksort kullanmanın bir başka nedeni, ortalama durumda, quicksort'un birleştirmeden daha hızlı olmasıdır. Quicksort, birleştirmeye göre daha fazla karşılaştırma yapsa da, çok daha az dizi erişimi sağlar. 3 yollu hızlı sıralama, giriş pratik uygulamalarda olağandışı olmayan çok sayıda yinelenen giriş içeriyorsa doğrusal zaman elde edebilir (Benim tahminim, ikili pivot hızlı sıralamanın da bu özelliğe sahip olmasıdır).
Jingguo Yao

İlkel türler için diziyi klonlamaz, onları yerinde sıralayabilir, bu yüzden bence tek neden kararlılık sözleşmesi, temelde ...
rogerdpack

27

Bu cevapta belirtilen Java 7 API belgelerine göre , Arrays#Sort()nesne dizileri için artık MergeSort ve InsertionSort'un bir melezi olan TimSort'u kullanıyor . Öte yandan, Arrays#sort()ilkel diziler için artık Dual-Pivot QuickSort kullanıyor . Bu değişiklikler Java SE 7'den başlayarak uygulandı.


2
Cevap değil, neden 2 farklı algoritma seçildi.
Alexandr

12

Aklıma gelen bir neden, Quicksort'un en kötü durum zaman karmaşıklığına sahip olması ( n ^ 2 ) iken, mergesort'un O ( n log n ) en kötü durum zamanını tutmasıdır . Nesne dizileri için birden çok yinelenen nesne başvurusu olacağı konusunda makul bir beklenti vardır ki bu, hızlı sıralamanın en kötü yaptığı durumdur.

Çeşitli algoritmaların iyi bir görsel karşılaştırması var, farklı algoritmalar için en sağdaki grafiğe özellikle dikkat edin.


2
Java quicksort (n ^ 2), dokümanlardan "Bu algoritma teklifler n * kuadratik performansına dejenere diğer quicksorts neden birçok veri setlerinde günlüğü (n) performans" O kadar derade olmayan bir modifiye quicksort olduğunu
sbridges

7

Algoritmalar üzerine Coursera dersi alıyordum ve derslerden birinde Profesör Bob Sedgewick, Java sistemi sıralaması için değerlendirmeden bahsediyor:

"Bir programcı nesneler kullanıyorsa, alan kritik öneme sahip bir değerlendirme değildir ve bir birleştirme sıralaması tarafından kullanılan fazladan alan bir sorun olmayabilir. Ve bir programcı ilkel türleri kullanıyorsa, belki de performans en önemli şeydir, bu yüzden kullanıyorlar hızlı sıralama."


4
Asıl sebep bu değil. Bu cümlenin hemen ardından, "Referans türleri için neden MergeSort kullanılıyor?" Videosuna gömülü bir soru vardı. (çünkü kararlı). Sanırım Sedgewick, soruya bırakmak için videoda bundan bahsetmedi.
likern

1

java.util.Arrays , Comparable uygulayan veya Comparator kullanan nesneler için int ve mergesort gibi ilkel türler için quicksort kullanır . İki farklı yöntem kullanılarak fikri olduğuna dair bir programcı kullanarak nesneleri belki uzay hayati öneme sahip bir husus değildir ve kullandığı ekstra alan eğer öyleyse MergeSort belki bir sorun değil ve programcı en ilkel türleri kullanarak belki performans kullanımı bu yüzden en önemli şey quicksort .

Örneğin: Bu, kararlılığın önemli olduğu sıralamanın örneğidir.

görüntü açıklamasını buraya girin

Bu nedenle kararlı sıralama, nesne türleri için, özellikle de değiştirilebilir nesne türleri ve sıralama anahtarından daha fazla veriye sahip nesne türleri için anlamlıdır ve birleştirme sıralaması böyle bir sıralamadır. Ancak ilkel tipler için istikrar sadece konu dışı değildir. Anlamsız.

Kaynak: INFO


0

Java'nın Arrays.sortyöntemi, hızlı sıralama, ekleme sıralama ve birleştirme sıralaması kullanır. OpenJDK kodunda uygulanan hem tek hem de çift pivot hızlı sıralaması bile vardır. En hızlı sıralama algoritması koşullara bağlıdır ve kazananlar şunlardır: küçük diziler için ekleme sıralaması (şu anda seçili olan 47), çoğunlukla sıralanmış diziler için birleştirme ve kalan diziler için hızlı sıralama, böylece Java'nın Array.sort () en iyi algoritmayı seçmeye çalışır. bu kriterlere göre uygulayın.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.