एक समाधान केवल 1 मेगाबाइट और 1 मिलियन बाइट्स के बीच अंतर के कारण संभव है। अनुमति के बारे में 2 से बिजली 8093729.5 अलग-अलग तरीके हैं 1 मिलियन 8-अंकीय संख्याओं को चुनने के लिए डुप्लिकेट अनुमत और आदेश महत्वहीन है, इसलिए केवल 1 मिलियन बाइट के साथ एक मशीन में सभी संभावनाओं का प्रतिनिधित्व करने के लिए पर्याप्त राज्य नहीं हैं। लेकिन 1M (टीसीपी / आईपी के लिए कम 2k) 1022 * 1024 * 8 = 8372224 बिट्स है, इसलिए एक समाधान संभव है।
भाग 1, प्रारंभिक समाधान
इस दृष्टिकोण को 1M से थोड़ा अधिक की आवश्यकता है, मैं इसे 1M में बाद में फिट करने के लिए परिष्कृत करूंगा।
मैं ० से ९९९९९९ में numbers-बिट नंबरों के सब्लिस्ट के अनुक्रम में संख्याओं की एक कॉम्पैक्ट सॉर्ट की गई सूची को संग्रहीत करूंगा। पहली सबलिस्ट 0 से 127 तक की संख्या रखती है, दूसरी सबलिस्ट 128 से 255 तक की संख्या रखती है, आदि 100000000/128 बिल्कुल 781250 है, इसलिए 781250 ऐसे सब्लिस्ट की आवश्यकता होगी।
प्रत्येक सबलिस्ट में एक 2-बिट सबलिस्ट हेडर होता है, उसके बाद एक सब-लिस्ट बॉडी होती है। सबलिस्ट बॉडी में 7 बिट प्रति सब्बल एंट्री होती है। सब्लिस्ट्स को एक साथ समेटा जाता है, और प्रारूप यह बताना संभव बनाता है कि एक सबलिस्ट कहां समाप्त होता है और अगला शुरू होता है। पूरी तरह से आबादी वाली सूची के लिए आवश्यक कुल संग्रहण 2 * 781250 + 7 * 1000000 = 8562500 बिट्स है, जो लगभग 1.021 एम-बाइट्स है।
4 संभावित सबलिस्ट हेडर मान हैं:
00 खाली सबलिस्ट, कुछ भी नहीं है।
01 सिंगलटन, सबलिस्ट में केवल एक प्रविष्टि है और अगले 7 बिट्स इसे पकड़ते हैं।
10 सबलिस्ट में कम से कम 2 अलग-अलग संख्याएँ होती हैं। प्रविष्टियों को गैर-घटते क्रम में संग्रहीत किया जाता है, सिवाय इसके कि अंतिम प्रविष्टि पहले की तुलना में कम या बराबर है। यह सबलिस्ट के अंत की पहचान करने की अनुमति देता है। उदाहरण के लिए, संख्या 2,4,6 को (4,6,2) के रूप में संग्रहीत किया जाएगा। संख्या 2,2,3,4,4 को (2,3,4,4,2) के रूप में संग्रहीत किया जाएगा।
11 सबलिस्ट एक संख्या के 2 या अधिक दोहराव रखती है। अगले 7 बिट नंबर देते हैं। फिर मान 1 के साथ शून्य या अधिक 7-बिट प्रविष्टियां आते हैं, जिसके बाद मान 0. के साथ 7-बिट प्रविष्टि होती है। सबलिस्ट बॉडी की लंबाई दोहराव की संख्या निर्धारित करती है। उदाहरण के लिए, संख्या 12,12 को (12,0) के रूप में संग्रहीत किया जाएगा, संख्या 12,12,12 को (12,1,0), 12,12,12 के रूप में संग्रहीत किया जाएगा (12,1) , 1,0) और इसी तरह।
मैं एक खाली सूची के साथ शुरू करता हूं, संख्याओं का एक समूह पढ़ता हूं और उन्हें 32 बिट पूर्णांक के रूप में संग्रहीत करता हूं, नए नंबर को जगह में सॉर्ट करता हूं (हेस्पोर्ट का उपयोग करते हुए, शायद) और फिर उन्हें एक नई कॉम्पैक्ट सॉर्ट की गई सूची में विलय कर देता हूं। तब तक दोहराएं जब तक कि पढ़ने के लिए अधिक संख्या न हो, तब आउटपुट उत्पन्न करने के लिए एक बार फिर कॉम्पैक्ट सूची पर जाएं।
नीचे दी गई सूची सूची मर्ज ऑपरेशन की शुरुआत से ठीक पहले मेमोरी का प्रतिनिधित्व करती है। "O" वह क्षेत्र है जो 32-बिट पूर्णांक को सॉर्ट करता है। "X" क्षेत्र पुरानी कॉम्पैक्ट सूची रखने वाले क्षेत्र हैं। "=" संकेत कॉम्पैक्ट सूची के लिए विस्तार कक्ष हैं, "ओ" एस में प्रत्येक पूर्णांक के लिए 7 बिट्स हैं। "Z" अन्य यादृच्छिक ओवरहेड हैं।
ZZZOOOOOOOOOOOOOOOOOOOOOOOOOO==========XXXXXXXXXXXXXXXXXXXXXXXXXX
मर्ज दिनचर्या बाईं ओर "O" और सबसे बाईं ओर "X" पढ़ना शुरू करती है, और बाईं ओर "=" लिखना शुरू करती है। जब तक सभी नए पूर्णांक नहीं मिल जाते, तब तक लिखने वाला पॉइंटर कॉम्पेक्ट लिस्ट पॉइंटर को नहीं पकड़ता, क्योंकि दोनों पॉइंटर्स प्रत्येक सबलिस्ट के लिए 2 बिट्स एडवांस करते हैं और पुरानी कॉम्पेक्ट लिस्ट में प्रत्येक एंट्री के लिए 7 बिट्स होते हैं, और इसके लिए पर्याप्त अतिरिक्त जगह होती है। नए नंबरों के लिए 7-बिट प्रविष्टियां।
भाग 2, यह 1M में cramming
1M में उपरोक्त समाधान को निचोड़ने के लिए, मुझे कॉम्पैक्ट सूची प्रारूप को थोड़ा और अधिक कॉम्पैक्ट बनाने की आवश्यकता है। मैं एक सबलिस्ट प्रकार से छुटकारा पाऊंगा, जिससे कि केवल 3 अलग-अलग संभव सबलिस्ट हेडर मान होंगे। तब मैं "00", "01" और "1" को सबलिस्ट हेडर मान के रूप में उपयोग कर सकता हूं और कुछ बिट्स को बचा सकता हूं। निम्न प्रकार हैं:
एक खाली सबलिस्ट, कुछ भी नहीं है।
बी सिंगलटन, सबलिस्ट में केवल एक प्रविष्टि है और अगले 7 बिट्स इसे पकड़ते हैं।
C उपसूची में कम से कम 2 अलग-अलग संख्याएँ हैं। प्रविष्टियों को गैर-घटते क्रम में संग्रहीत किया जाता है, सिवाय इसके कि अंतिम प्रविष्टि पहले की तुलना में कम या बराबर है। यह सबलिस्ट के अंत की पहचान करने की अनुमति देता है। उदाहरण के लिए, 2,4,6 की संख्या (4,6,2) के रूप में संग्रहीत की जाएगी। संख्या 2,2,3,4,4 को (2,3,4,4,2) के रूप में संग्रहीत किया जाएगा।
डी सबलिस्ट में एक ही संख्या के 2 या अधिक दोहराव होते हैं।
मेरे 3 सबलिस्ट हेडर मान "ए", "बी" और "सी" होंगे, इसलिए मुझे डी-टाइप सबस्टलिस्ट का प्रतिनिधित्व करने का एक तरीका चाहिए।
मान लीजिए मेरे पास सी-टाइप सबलिस्ट शीर्षक है, जिसके बाद 3 प्रविष्टियाँ हैं, जैसे कि "C [17] [101] [58]"। यह ऊपर वर्णित के रूप में मान्य सी-टाइप सबलिस्ट का हिस्सा नहीं हो सकता है, क्योंकि तीसरी प्रविष्टि दूसरी से कम है लेकिन पहली से अधिक है। मैं इस प्रकार के निर्माण का उपयोग डी-टाइप सबलिस्ट को दर्शाने के लिए कर सकता हूं। थोड़े शब्दों में, कहीं भी मेरे पास "C {00 ?????}} {1 ?????}} {01 ?????}" एक असंभव सी-टाइप सबलिस्ट है। मैं इसका उपयोग किसी एकल संख्या के 3 या अधिक दोहराव वाले सबलिस्ट को दर्शाने के लिए करूंगा। पहले दो 7-बिट शब्द संख्या को (नीचे "एन" बिट्स) को एन्कोड करते हैं और उसके बाद शून्य या अधिक {0100001} शब्दों के बाद {0100000} शब्द आते हैं।
For example, 3 repetitions: "C{00NNNNN}{1NN0000}{0100000}", 4 repetitions: "C{00NNNNN}{1NN0000}{0100001}{0100000}", and so on.
यह सिर्फ उन सूचियों को छोड़ देता है जो एक ही संख्या के 2 दोहराव रखती हैं। मैं एक और असंभव सी-टाइप सबलिस्ट पैटर्न के साथ उन लोगों का प्रतिनिधित्व करता हूं: "C {0 ??????} {11 ?????} {10 ?????}"। पहले 2 शब्दों में संख्या के 7 बिट्स के लिए बहुत जगह है, लेकिन यह पैटर्न उस सबलिस्ट से अधिक लंबा है जो यह प्रतिनिधित्व करता है, जो चीजों को थोड़ा अधिक जटिल बनाता है। अंत में पांच प्रश्न-चिह्नों को पैटर्न का हिस्सा नहीं माना जा सकता है, इसलिए मेरे पास: "C {0NNNNNN} {11N ????} 10" मेरे पैटर्न के रूप में, जिस संख्या को "N" में दोहराया जाना है। "है। वह भी 2 बिट्स लंबा।
मुझे 2 बिट्स उधार लेने होंगे और उन्हें इस पैटर्न में 4 अप्रयुक्त बिट्स से वापस भुगतान करना होगा। पढ़ते समय, "C {0NNNNNN} {11N00AB} 10", एन "s" में संख्या के आउटपुट 2 इंस्टेंस, बिट्स A और B के साथ अंत में "10" को ओवरराइट करें, और 2 से रीड पॉइंटर को रिवाइंड करें। बिट्स। इस एल्गोरिथ्म के लिए विनाशकारी रीड्स ठीक हैं, क्योंकि प्रत्येक कॉम्पैक्ट सूची केवल एक बार चली जाती है।
एक एकल संख्या के 2 दोहराव का एक सबलिस्ट लिखने के दौरान, "C {0NNNNN} 11N00" लिखें और उधार बिट्स काउंटर को 2 पर सेट करें। प्रत्येक लेखन में जहां उधार बिट्स काउंटर गैर-शून्य है, यह प्रत्येक बिट लिखित के लिए अस्वीकृत है और "10" तब लिखा जाता है जब काउंटर शून्य से टकराता है। तो अगले 2 बिट लिखे गए स्लॉट ए और बी में जाएंगे, और फिर "10" अंत में छोड़ दिया जाएगा।
"00", "01" और "1" द्वारा दर्शाए गए 3 सबलिस्ट हेडर मूल्यों के साथ, मैं "1" को सबसे लोकप्रियलिस्ट प्रकार में असाइन कर सकता हूं। मुझे सबलिस्ट प्रकारों को सबलिस्ट प्रकारों को मैप करने के लिए एक छोटी तालिका की आवश्यकता होगी, और मुझे प्रत्येक सबलिस्ट प्रकार के लिए एक घटना काउंटर की आवश्यकता होगी ताकि मुझे पता चले कि सबसे अच्छा सबलिस्ट हेडर मैपिंग क्या है।
पूरी तरह से आबादी वाली कॉम्पैक्ट सूची में सबसे खराब स्थिति न्यूनतम प्रतिनिधित्व तब होती है जब सभी सबलिस्ट प्रकार समान रूप से लोकप्रिय होते हैं। उस स्थिति में मैं प्रत्येक 3 सबलिस्ट हेडर के लिए 1 बिट बचाता हूं, इसलिए सूची का आकार 2 * 781250 + 7 * 1000000 - 781250/3 = 8302083.3 बिट्स है। 32 बिट शब्द सीमा तक राउंडिंग, 8302112 बिट्स, या 1037764 बाइट्स।
टीसीपी / आईपी राज्य के लिए 1 एम माइनस 2k और बफ़र्स 1022 * 1024 = 1046528 बाइट्स हैं, जिससे मुझे खेलने के लिए 8764 बाइट्स मिलेंगे।
लेकिन सबलिस्ट हेडर मैपिंग को बदलने की प्रक्रिया के बारे में क्या? नीचे दिए गए स्मृति मानचित्र में, "Z" यादृच्छिक ओवरहेड है, "=" मुक्त स्थान है, "X" कॉम्पैक्ट सूची है।
ZZZ=====XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
बाईं ओर "X" पढ़ना शुरू करें और बाईं ओर "=" लिखना शुरू करें और दाएं काम करें। जब यह किया जाता है तो कॉम्पैक्ट सूची थोड़ी छोटी हो जाएगी और यह मेमोरी के गलत छोर पर होगा:
ZZZXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX=======
तो मैं इसे सही करने के लिए अलग करने की आवश्यकता होगी:
ZZZ=======XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
हेडर मैपिंग परिवर्तन प्रक्रिया में, सबलिस्ट हेडर के 1/3 तक 1-बिट से 2-बिट में बदल जाएगा। सबसे खराब स्थिति में ये सभी सूची के प्रमुख होंगे, इसलिए मुझे शुरू करने से पहले कम से कम 781250/3 बिट्स मुफ्त भंडारण की आवश्यकता होगी, जो मुझे कॉम्पैक्ट सूची के पिछले संस्करण की स्मृति आवश्यकताओं पर वापस ले जाता है: (
उस के आसपास जाने के लिए, मैं 7812 सब्लिस्ट्स को 78125 सबलिस्ट्स के 10 सबलिस्ट समूहों में विभाजित करूँगा। प्रत्येक समूह का अपना स्वतंत्र सबलिस्ट हेडर मैपिंग होता है। समूहों के लिए A से J अक्षर का उपयोग करना:
ZZZ=====AAAAAABBCCCCDDDDDEEEFFFGGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
प्रत्येक सबलिस्ट समूह सिकुड़ता हैडर मैपिंग परिवर्तन के दौरान सिकुड़ता या ठहरता है:
ZZZ=====AAAAAABBCCCCDDDDDEEEFFFGGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAA=====BBCCCCDDDDDEEEFFFGGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABB=====CCCCDDDDDEEEFFFGGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCC======DDDDDEEEFFFGGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCCDDDDD======EEEFFFGGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCCDDDDDEEE======FFFGGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCCDDDDDEEEFFF======GGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCCDDDDDEEEFFFGGGGGGGGGG=======HHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCCDDDDDEEEFFFGGGGGGGGGGHH=======IJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCCDDDDDEEEFFFGGGGGGGGGGHHI=======JJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCCDDDDDEEEFFFGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ=======
ZZZ=======AAAAAABBCCCDDDDDEEEFFFGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
मैपिंग परिवर्तन के दौरान एक सबलिस्ट समूह का सबसे खराब मामला 4k के तहत 78125/3 = 26042 बिट्स है। अगर मैं पूरी तरह से आबादी वाली कॉम्पैक्ट सूची के लिए 4k प्लस 1037764 बाइट्स की अनुमति देता हूं, तो मुझे स्मृति मानचित्र में "जेड" के लिए 8764 - 4096 = 4668 बाइट्स छोड़ देता है।
10 सबलिस्ट हेडर मैपिंग टेबल, 30 सबलिस्ट हेडर घटना काउंट और अन्य कुछ काउंटर्स, पॉइंटर्स और छोटे बफ़र्स जिनकी मुझे आवश्यकता होगी, और स्पेस मैंने नोट किए बिना उपयोग किया है, जैसे फंक्शन कॉल रिटर्न एड्रेस के लिए स्टैक स्पेस और स्थानीय चर।
भाग 3, इसे चलाने में कितना समय लगेगा?
खाली कॉम्पैक्ट सूची के साथ 1-बिट सूची शीर्ष लेख का उपयोग रिक्त सबलिस्ट के लिए किया जाएगा, और सूची का प्रारंभिक आकार 78,505 बिट्स होगा। सबसे खराब स्थिति में सूची में जोड़े गए प्रत्येक नंबर के लिए 8 बिट्स बढ़ते हैं, इसलिए 32-बिट संख्याओं में से प्रत्येक के लिए 32 + 8 = 40 बिट्स रिक्त स्थान की आवश्यकता होती है जिसे सूची बफर के शीर्ष पर रखा जाता है और फिर सॉर्ट और मर्ज किया जाता है। सबसे खराब स्थिति में, 2 * 781250 + 7 * प्रविष्टियों के अंतरिक्ष उपयोग में सबलिस्ट हेडर मैपिंग को बदलना - 781250/3 बिट्स।
सूची में कम से कम 800000 नंबर होने के बाद प्रत्येक पाँचवें मर्ज के बाद सबलिस्ट हेडर मैपिंग को बदलने की नीति के साथ, एक सबसे खराब स्थिति में कुल 30M कॉम्पैक्ट सूची पढ़ने और लिखने की गतिविधि शामिल होगी।
स्रोत:
http://nick.cleaton.net/ramsortsol.html