Bir çözüm ancak 1 megabayt ile 1 milyon bayt arasındaki farktan dolayı mümkündür. 8093729.5 gücüne yaklaşık 2 tane var, kopyalara izin verilen 1 milyon 8 haneli sayıları seçmek ve önemsiz sipariş etmek, böylece sadece 1 milyon bayt RAM'e sahip bir makinenin tüm olasılıkları temsil etmek için yeterli durumu yok. Ancak 1M (TCP / IP için daha az 2k) 1022 * 1024 * 8 = 8372224 bittir, bu nedenle bir çözüm mümkündür.
Bölüm 1, ilk çözüm
Bu yaklaşım 1M'den biraz daha fazlasına ihtiyaç duyuyor, daha sonra 1M'ye sığacak şekilde rafine edeceğim.
7 bitlik sayıların alt listelerinden oluşan bir dizi olarak 0 ile 99999999 aralığındaki sıralı bir sayı listesi saklayacağım. İlk alt liste 0 ila 127 arasındaki sayıları, ikinci alt liste 128 ila 255 arasındaki sayıları içerir. 100000000/128 tam olarak 781250'dir, bu nedenle bu tür alt listelere ihtiyaç olacaktır.
Her alt liste 2 bitlik bir alt liste başlığından sonra bir alt liste gövdesinden oluşur. Alt liste gövdesi, alt liste girişi başına 7 bit alır. Alt listelerin tümü bir araya getirilir ve biçim, bir alt listenin nerede biteceğini ve diğerinin nerede başladığını söylemeyi mümkün kılar. Tamamen doldurulmuş bir liste için gereken toplam depolama alanı 2 * 781250 + 7 * 1000000 = 8562500 bit'tir, bu yaklaşık 1.021 M bayttır.
4 olası alt liste başlık değeri:
00 Boş alt liste, hiçbir şey takip etmiyor.
01 Singleton, alt listede sadece bir giriş var ve sonraki 7 bit bunu tutuyor.
10 Alt liste en az 2 ayrı numara içerir. Girişler, son girişin birinciden küçük veya ona eşit olması dışında, azalmayan bir sırada saklanır. Bu, alt listenin sonunun tanımlanmasını sağlar. Örneğin, 2,4,6 sayıları (4,6,2) olarak depolanır. 2,2,3,4,4 sayıları (2,3,4,4,2) olarak depolanır.
11 Alt liste, tek bir sayının 2 veya daha fazla tekrarını içerir. Sonraki 7 bit sayıyı verir. Sonra sıfır veya daha fazla 7-bit girişi 1 değeri, ardından 7-bit girişi 0 değeri ile gelir. Alt liste gövdesinin uzunluğu tekrar sayısını belirler. Örneğin, 12,12 sayıları (12,0), 12,12,12 sayıları (12,1,0), 12,12,12,12 (12,1) , 1,0) vb.
Boş bir listeyle başlıyorum, bir grup sayıyı okudum ve 32 bit tamsayı olarak saklıyorum, yeni sayıları yerinde sıralıyorum (muhtemelen heapsort kullanarak) ve sonra bunları yeni bir kompakt sıralı listeye birleştiriyorum. Okunacak başka sayı kalmayıncaya kadar tekrarlayın, ardından çıktıyı oluşturmak için kompakt listeyi bir kez daha yürütün.
Aşağıdaki satır, liste birleştirme işleminin başlamasından hemen önceki belleği temsil eder. "O" lar, sıralanan 32 bit tamsayıları barındıran bölgedir. "X" ler eski kompakt listenin bulunduğu bölgedir. "=" İşaretleri, kompakt listenin genişletme odasıdır, "O" larda her tamsayı için 7 bittir. "Z" ler diğer rastgele yüklerdir.
ZZZOOOOOOOOOOOOOOOOOOOOOOOOOO==========XXXXXXXXXXXXXXXXXXXXXXXXXX
Birleştirme yordamı en soldaki "O" ve en soldaki "X" de okumaya başlar ve en soldaki "=" ile yazmaya başlar. Yazma işaretçisi, tüm yeni tamsayılar birleştirilene kadar küçük liste okuma işaretçisini yakalamaz, çünkü her iki işaretçi de her bir alt liste için 2 bit, eski kompakt listedeki her giriş için 7 bit ilerler ve Yeni numaralar için 7 bitlik girişler.
Bölüm 2, 1M içine tıka basa dolu
Yukarıdaki çözümü 1M'ye sıkıştırmak için, kompakt liste formatını biraz daha kompakt hale getirmem gerekiyor. Sadece 3 farklı olası alt liste başlık değeri olacak şekilde alt liste türlerinden birini kaldıracağım. Sonra alt liste başlık değerleri olarak "00", "01" ve "1" kullanabilir ve birkaç bit kaydedebilirsiniz. Alt liste türleri:
Boş bir alt liste, hiçbir şey gelmez.
B Singleton, alt listede yalnızca bir giriş vardır ve sonraki 7 bit tarafından tutulur.
C Alt liste en az 2 ayrı numara içerir. Girişler, son girişin birinciden küçük veya ona eşit olması dışında, azalmayan bir sırada saklanır. Bu, alt listenin sonunun tanımlanmasını sağlar. Örneğin, 2,4,6 sayıları (4,6,2) olarak depolanır. 2,2,3,4,4 sayıları (2,3,4,4,2) olarak depolanır.
D Alt liste, tek bir sayının 2 veya daha fazla tekrarından oluşur.
Benim 3 alt liste başlık değerleri "A", "B" ve "C" olacaktır, bu yüzden D-tipi alt listeleri temsil etmek için bir yol gerekir.
Diyelim ki C tipi alt liste başlığının ardından "C [17] [101] [58]" gibi 3 giriş var. Üçüncü giriş ikinciden daha az, ancak ilkinden daha fazla olduğundan, bu, yukarıda açıklandığı gibi geçerli bir C tipi alt listenin parçası olamaz. Bu tür bir yapıyı D-tipi alt listeyi temsil etmek için kullanabilirim. Bit terimleriyle, her yerde "C {00 ?????} {1 ??????} {01 ?????}" imkansız bir C tipi alt listedir. Bunu, tek bir sayının 3 veya daha fazla tekrarından oluşan bir alt listeyi temsil etmek için kullanacağım. İlk iki 7-bit kelime sayıyı kodlar (aşağıdaki "N" bitleri) ve ardından sıfır veya daha fazla {0100001} kelime ve ardından {0100000} kelime gelir.
For example, 3 repetitions: "C{00NNNNN}{1NN0000}{0100000}", 4 repetitions: "C{00NNNNN}{1NN0000}{0100001}{0100000}", and so on.
Bu, tek bir sayının tam olarak 2 tekrarını içeren listeler bırakır. Başka bir imkansız C tipi alt liste modeline sahip olanları temsil edeceğim: "C {0 ??????} {11 ?????} {10 ?????}". İlk 2 kelimede sayının 7 biti için bolca yer var, ancak bu desen temsil ettiği alt listeden daha uzun, bu da işleri biraz daha karmaşık hale getiriyor. Sondaki beş soru işareti kalıbın bir parçası olarak değerlendirilemez, bu yüzden: "C {0NNNNNN} {11N ????} 10", kalıbım olarak tekrarlanacak sayı ile "N "s. Bu 2 bit çok uzun.
2 bit ödünç almam ve bunları bu kalıpta kullanılmayan 4 bitten geri ödemem gerekecek. Okurken, "C {0NNNNNN} {11N00AB} 10" ile karşılaştığınızda, "N" lerde sayının 2 örneğini çıktılayın, A ve B bitleri ile sondaki "10" un üzerine yazın ve okuma işaretçisini 2 geri sarar bit. Her bir küçük liste sadece bir kez yürüdüğü için yıkıcı okumalar bu algoritma için uygundur.
Tek bir sayının 2 tekrarından oluşan bir alt liste yazarken, "C {0NNNNNN} 11N00" yazın ve ödünç verilen bit sayacını 2 olarak ayarlayın. Ödünç verilen bit sayacının sıfır olmadığı her yazmada, yazılan her bit için azaltılır ve Sayaç sıfıra ulaştığında "10" yazılır. Böylece, yazılan sonraki 2 bit A ve B yuvalarına girecek ve daha sonra "10" sonuna düşecektir.
"00", "01" ve "1" ile temsil edilen 3 alt liste başlık değeriyle, en popüler alt liste türüne "1" atayabilirim. Alt liste başlık değerlerini alt liste türlerine eşlemek için küçük bir tabloya ihtiyacım olacak ve her alt liste türü için bir oluşum sayacına ihtiyacım olacak, böylece en iyi alt liste başlık eşlemesinin ne olduğunu biliyorum.
Tamamen doldurulmuş bir kompakt listenin en kötü durumu, tüm alt liste türleri eşit derecede popüler olduğunda oluşur. Bu durumda, her 3 alt liste başlığı için 1 bit kaydederim, böylece liste boyutu 2 * 781250 + 7 * 1000000 - 781250/3 = 8302083.3 bit olur. 32 bit sözcük sınırına yuvarlama, 8302112 bit veya 1037764 bayt.
1M eksi TCP / IP durumu ve arabellekler için 2k, 1022 * 1024 = 1046528 bayt, bana oynamak için 8764 bayt bırakıyor.
Peki, alt liste başlık eşlemesini değiştirme işlemi ne olacak? Aşağıdaki bellek haritasında "Z" rastgele yük, "=" boş alan, "X" kompakt listedir.
ZZZ=====XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
En soldaki "X" de okumaya başlayın ve en soldaki "=" de yazmaya başlayın ve sağa doğru çalışın. Tamamlandığında, kompakt liste biraz daha kısa olacak ve belleğin yanlış ucunda olacak:
ZZZXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX=======
O zaman sağa doğru çevirmem gerekecek:
ZZZ=======XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Üstbilgi eşleme değiştirme işleminde, alt liste üstbilgilerinin 1 / 3'üne kadar 1 bit ile 2 bit arasında değişir. En kötü durumda, bunlar listenin başında olacak, bu yüzden başlamadan önce en az 781250/3 bit ücretsiz depolama alanına ihtiyacım olacak, bu da beni kompakt listenin önceki sürümünün bellek gereksinimlerine geri götürüyor: (
Bu sorunu çözmek için, 781250 alt listelerini her biri 78125 alt listeden oluşan 10 alt liste grubuna ayıracağım. Her grubun kendi bağımsız alt liste başlık eşlemesi vardır. Gruplar için A'dan J'ye kadar olan harfleri kullanarak:
ZZZ=====AAAAAABBCCCCDDDDDEEEFFFGGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
Her bir alt liste grubu, bir alt liste başlık eşlemesi değişikliği sırasında küçülür veya aynı kalır:
ZZZ=====AAAAAABBCCCCDDDDDEEEFFFGGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAA=====BBCCCCDDDDDEEEFFFGGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABB=====CCCCDDDDDEEEFFFGGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCC======DDDDDEEEFFFGGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCCDDDDD======EEEFFFGGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCCDDDDDEEE======FFFGGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCCDDDDDEEEFFF======GGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCCDDDDDEEEFFFGGGGGGGGGG=======HHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCCDDDDDEEEFFFGGGGGGGGGGHH=======IJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCCDDDDDEEEFFFGGGGGGGGGGHHI=======JJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCCDDDDDEEEFFFGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ=======
ZZZ=======AAAAAABBCCCDDDDDEEEFFFGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
Bir eşleme değişikliği sırasında bir alt liste grubunun en kötü durum geçici genişlemesi 4k altında 78125/3 = 26042 bittir. Tam dolu bir kompakt liste için 4k artı 1037764 bayta izin verirsem, bu beni bellek haritasındaki "Z" ler için 8764 - 4096 = 4668 bayt bırakır.
Bu, 10 alt liste üstbilgi eşleme tablosu, 30 alt liste üstbilgi oluşum sayısı ve ihtiyaç duyacağım diğer birkaç sayaç, işaretçi ve küçük arabellek ve fark etmeden kullandığım, işlev çağrısı dönüş adresleri için yığın alanı ve yerel değişkenler.
Bölüm 3, çalıştırmak ne kadar sürer?
Boş bir küçük liste ile 1 bitlik liste başlığı boş bir alt liste için kullanılır ve listenin başlangıç boyutu 781250 bit olur. En kötü durumda, liste eklenen her sayı için 8 bit büyür, bu nedenle liste tamponunun üstüne yerleştirilecek 32 bitlik sayıların her biri için 32 + 8 = 40 bit boş alan gerekir ve ardından sıralanır ve birleştirilir. En kötü durumda, alt liste başlık eşlemesinin değiştirilmesi 2 * 781250 + 7 * giriş - 781250/3 bit alan kullanımı ile sonuçlanır.
Listede en az 800000 sayı olduğunda, her beşinci birleştirme işleminden sonra alt liste üstbilgisi eşlemesini değiştirme politikasıyla, en kötü durum toplamda yaklaşık 30 milyon kompakt liste okuma ve yazma etkinliği içerir.
Kaynak:
http://nick.cleaton.net/ramsortsol.html