Patolojik Sıralama


15

Patolojik Sıralama

Patronunuz, şirketinizin uygulamasının performansını artırmak için bir sıralama algoritması geliştirmenizi istedi. Ancak, uygulamayı yazdıktan sonra, önemli ölçüde daha hızlı hale getirme olasılığınızın olmadığını biliyorsunuz. Patronunuzu hayal kırıklığına uğratmak istemiyorsanız, belirli veri kümelerinde * sıralamadan daha iyi çalışan yeni bir algoritma geliştirmeye karar verdiniz. Tabii ki, algoritmanın sadece bazı durumlarda çalıştığını açıkça belirtemezsiniz, bu yüzden mümkün olduğunca belirsiz hale getirmek istersiniz.

Bu yarışmanın amacı, seçtiğiniz dilde, belirli veri kümelerinde diğerlerinden daha iyi performans gösteren ve tekrarlanabilir sonuçlarla bir sıralama rutini yazmaktır. Hızı belirleyen sınıflandırma ne kadar spesifik olursa, o kadar iyidir. Algoritma bir tür sıralama yapmalıdır, bu nedenle zaten tamamen sıralanan verilere (hiçbir şey yapmayan bir algoritmaya) dayanan bir algoritma veya tamamen ters sıralanan verilere bağlı bir algoritma geçersizdir. Sıralama algoritması herhangi bir veri kümesini doğru şekilde sıralamalıdır.

Rutinizi sunduktan sonra, lütfen neden yalnızca belirli veri kümelerinde çalıştığını açıklayın ve en az bir iyi (hızlı) veri kümesi ve bir kötü (yavaş) veri kümesi üzerinde test çalışmaları ekleyin. Buradaki nokta, patronunuza sıralamanın daha iyi bir yolunu bulduğunuzu kanıtlayabilmektir, bu nedenle daha fazla test verisi daha iyidir. Elbette, patronunuza sadece iyi verilerden test sonuçlarını göstereceksiniz, bu nedenle gerekli test verilerindeki kusur çok açık olamaz. Diliniz için geçerliyse, lütfen algoritmanızın dilinizin yerleşik sıralama algoritmasından daha hızlı olduğunu gösterin.

Örneğin, ekleme sıralaması neredeyse sıralanan verilerde O (n) ile yaklaştığından, iyi veriler zaten sıralanan veriler ve kötü veriler tamamen rastgele veriler olmak üzere bir ekleme sıralama algoritması gönderilebilir. Ancak, bu çok iyi değil, çünkü patronum muhtemelen tüm test verilerinin neredeyse başlamak üzere sıralandığını fark edecekti.

Bu bir , bu nedenle 7 gün sonra (21 Mayıs) en çok oyu alan cevap kazanır.

Kimse beni yenemezse, eşit dağıtılmış veri kümelerinden yararlanan bir topluluk wiki yanıtı göndermek istiyorum.


Bu soruya yaklaşanlar için muhtemelen yararlı / ilginç bir kaynak: "Medyum Sıralama Algoritmaları" (Feragat: bu makalenin yazarı ve ben çok yakınız. :-P)
HostileFork, SE'nin

Yanıtlar:


9

Oldukça uzun zaman oldu, ama Algoritmalar 101'de rasgeleleştirmeyi kullanan bir sıralama algoritması öğretildiğimizi hatırlıyorum. Çok iyi bir öğrenci değildim, bu yüzden nasıl gittiğini veya neden ortalama olarak hızlı çalıştığını gerçekten hatırlamıyorum.

Yine de, bu sorunun rastgele ortalama kullanan bir çözüm gerektirdiğine karar verdim.

import random

def arrayIsSorted (arr) :
    for i in range(len(arr)-1) :
        if arr[i]>arr[i+1] : return False
    return True

def rSort (arr) :
    random.seed (42)
    counter = 0
    while not arrayIsSorted(arr) :
        random.shuffle (arr)
        counter+=1
    print ("Sorted in %d iterations." % counter)
    return arr

Gerçek randomizasyon önemli olduğundan, RNG'yi Yaşam, Evren ve Her Şeyin cevabı ile tohumladığımdan emin olurum. Biraz test yaptıktan sonra bunun akıllı bir hamle olduğu ortaya çıktı! Bu tamamen keyfi listelerin ne kadar hızlı sıralandığını kontrol edin:

rSort ([6,1,4,2,3,7,5])
rSort ([8,9,6,1,4,7,2,3,5])

Bunların her ikisi de sadece 1 yinelemede sıralanır - muhtemelen bundan daha hızlı bir işlev isteyemezdiniz!

Şimdi, bazı listeler biraz daha kötü sonuçlar veriyor ...

rSort ([5,1,4,2,3,7,6])
rSort ([8,9,6,1,4,7,2,5,3])

Bunlar sırasıyla 4,176 ve 94,523 yinelemelerinde sıralanır, ki bu aslında bir saniyeden fazla sürer ... ama kimseyi bu algoritmanın ne kadar şaşırtıcı olduğundan rahatsız etmemek için kendimize saklayalım!

Düzenle:

Algoritmamın verimliliğini 100 öğelik bir listede kanıtlamam istendi, işte burada:

rSort ([70, 6, 52, 97, 85, 61, 62, 48, 30, 3, 11, 88, 39, 91, 98, 8, 54, 92, 44, 65, 69, 21, 58, 41, 60, 76, 27, 82, 93, 81, 20, 94, 22, 29, 49, 95, 40, 19, 55, 42, 43, 1, 0, 67, 35, 15, 51, 31, 16, 25, 5, 53, 37, 74, 86, 12, 13, 72, 56, 32, 47, 46, 59, 33, 80, 4, 45, 63, 57, 89, 7, 77, 14, 10, 34, 87, 18, 79, 9, 66, 24, 99, 64, 26, 78, 38, 90, 28, 83, 75, 68, 2, 17, 73, 96, 71, 23, 84, 36, 50])

Bu uzun ve tamamen keyfi liste bile anında sıralanır! Gerçekten dünyadaki en iyi sıralama algoritmasına rastlamalıydım!


3
Biraz daha büyük veri kümelerinde test sonuçları alabilir miyiz? Belki 100 elementli? ;)
Geobits

@Geobits Sorun değil, işte burada :)
Tal

1
@ Geobits Evet öyle. Sonuçta.
Tal

3
Bu bir streç, ancak yeterli zaman verildiğinde diziyi sıralayacak olan bogosort'u kullandığı söylenebilir. İyi bir sıralama olmasa da, 'karıştır ve tekrarla' değerlerini sıraya koyma olarak bahse girmeye hazırım.
millinon

1
Eğer gerçek rastgele karıştırırsa, belki. PRNG'lerin bir döngüsü var, bu yüzden tüm permütasyonların denendiğini nasıl garanti edebileceğinizi göremiyorum.
Geobits

2

Kendi verilerinizi oluşturabiliyorsanız, oldukça basittir - rastgele görünen, ancak daha hızlı sıralama için bir anahtar içeren veriler alın. Diğer tüm veriler orijinal sıralama yöntemini kullanır, bu nedenle ortalama süreler daha iyidir.

Kolay bir yol, her veri öğesinin benzersiz bir anahtara sahip olduğundan emin olmak ve daha sonra anahtarları hash etmektir. Örneğin 1-10.000 arasındaki sayıların tümü 16 ile çarpılan ve 0-15 arası rastgele bir sayı eklenmiş bir liste alın (aşağıdaki fillArray () 'a bakın). Rastgele görünecekler, ancak her birinin benzersiz bir sıralı anahtarı var. Sıralama için 16'ya bölün (C'de >> 4 çok hızlıdır) ve ardından sonuç olarak elde edilen anahtarı dizin olarak kullanarak bir diziye yerleştirin. Bir geçiş ve işiniz bitti. Testlerde, quicksort'un on milyon numarada 30 kat daha yavaş olduğunu gördüm.

void fillArray(int *a,int len)
{
  for (int i=0;i<len;++i)
    a[i]=(i<<4)|(rand()&0xF);
  // shuffle later
}
void sortArray(int *a,int len)
{
  int key=0;
  int *r=new int[len];
  for (int i=0;i<len;++i)
  {
    key=a[i]>>4;
    r[key]=a[i];
  }
  memcpy(a,r,len*sizeof(int));
  delete[] r;
}
void shuffleArray(int *a,int len)
{
  int swap=0, k=0;
  for (int i=0;i<len;++i)
  {
    k=rand()%len;
    swap=a[k];
    a[k]=a[i];
    a[i]=swap;
  }
}
int qCompare(const void*a,const void*b)
{
  int result=*((int*)a)-*((int*)b);
  return result;
}
void main()
{
  int aLen=10000;
  int *a=new int[aLen];
  srand (time(NULL));
  fillArray(a,aLen);
  // time them
  long t0=0, d0=0, d1=0;
  // qsort
  shuffleArray(a,aLen);
  t0=::GetTickCount();
  qsort(a,aLen,sizeof(int),&qCompare);
  d0=::GetTickCount()-t0;
  // oursort
  shuffleArray(a,aLen);
  t0=::GetTickCount();
  sortArray(a,aLen);
  d1=::GetTickCount()-t0;
  delete[] a;
}

Benzersiz bir anahtarı olan her şey bu şekilde sıralanabilir - eğer saklayacak belleğiniz varsa, elbette. Örneğin, birçok veritabanı benzersiz bir sayısal müşteri kimliği kullanır - eğer liste yeterince küçük / sıralıysa bu bellekte tutulabilir. Veya bir kaydı benzersiz bir sayıya çevirmenin başka bir yolu. Daha fazla bilgi için Hash Sorts'u araştırın, çünkü bu ...

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.