मर्ज़ सॉर्ट: Difference between revisions
No edit summary |
No edit summary |
||
Line 11: | Line 11: | ||
|space=<math>O(n)</math> total with <math>O(n)</math> auxiliary, <math>O(1)</math> auxiliary with linked lists<ref>{{Harvtxt|Skiena|2008|p=122}}</ref> | |space=<math>O(n)</math> total with <math>O(n)</math> auxiliary, <math>O(1)</math> auxiliary with linked lists<ref>{{Harvtxt|Skiena|2008|p=122}}</ref> | ||
}} | }} | ||
[[कंप्यूटर विज्ञान]] में, मर्ज सॉर्ट (मर्जसॉर्ट के रूप में भी लिखा जाता है) कुशल, सामान्य-उद्देश्य और तुलना-आधारित सॉर्टिंग एल्गोरिथम है। अधिकांश कार्यान्वयन [[छँटाई एल्गोरिथ्म]] स्थिरता उत्पन्न करते हैं, जिसका अर्थ है कि समान तत्वों का क्रम इनपुट और आउटपुट में एक ही होता है। मर्ज सॉर्ट विभाजन-और-विजय एल्गोरिथम है जिसका आविष्कार [[जॉन वॉन न्यूमैन]] ने 1945 में किया था।<ref>{{Harvtxt|Knuth|1998|p=158}}</ref> विस्तृत विवरण और नीचे से उपर तक मर्ज सॉर्ट का[[हरमन गोल्डस्टाइन|विश्लेषण गोल्डस्टाइन]] और वन न्यूमैन की रिपोर्ट में 1948 में प्रकट हुआ था।<ref>{{cite conference |chapter=A meticulous analysis of mergesort programs |date=March 1997 |first1=Jyrki |last1=Katajainen |first2=Jesper Larsson |last2=Träff |title=Algorithms and Complexity |series=Lecture Notes in Computer Science |volume=1203 |conference=Italian Conference on Algorithms and Complexity |location=Rome |book-title=Proceedings of the 3rd Italian Conference on Algorithms and Complexity |pages=217–228 |doi=10.1007/3-540-62592-5_74 |isbn=978-3-540-62592-6 |citeseerx=10.1.1.86.3154 |chapter-url=http://hjemmesider.diku.dk/~jyrki/Paper/CIAC97.pdf}}</ref> | [[कंप्यूटर विज्ञान]] में, मर्ज सॉर्ट (मर्जसॉर्ट के रूप में भी लिखा जाता है) कुशल, सामान्य-उद्देश्य और तुलना-आधारित सॉर्टिंग एल्गोरिथम है। अधिकांश कार्यान्वयन [[छँटाई एल्गोरिथ्म|सॉर्ट एल्गोरिथ्म]] स्थिरता उत्पन्न करते हैं, जिसका अर्थ है कि समान तत्वों का क्रम इनपुट और आउटपुट में एक ही होता है। मर्ज सॉर्ट विभाजन-और-विजय एल्गोरिथम है जिसका आविष्कार [[जॉन वॉन न्यूमैन]] ने 1945 में किया था।<ref>{{Harvtxt|Knuth|1998|p=158}}</ref> विस्तृत विवरण और नीचे से उपर तक मर्ज सॉर्ट का[[हरमन गोल्डस्टाइन|विश्लेषण गोल्डस्टाइन]] और वन न्यूमैन की रिपोर्ट में 1948 में प्रकट हुआ था।<ref>{{cite conference |chapter=A meticulous analysis of mergesort programs |date=March 1997 |first1=Jyrki |last1=Katajainen |first2=Jesper Larsson |last2=Träff |title=Algorithms and Complexity |series=Lecture Notes in Computer Science |volume=1203 |conference=Italian Conference on Algorithms and Complexity |location=Rome |book-title=Proceedings of the 3rd Italian Conference on Algorithms and Complexity |pages=217–228 |doi=10.1007/3-540-62592-5_74 |isbn=978-3-540-62592-6 |citeseerx=10.1.1.86.3154 |chapter-url=http://hjemmesider.diku.dk/~jyrki/Paper/CIAC97.pdf}}</ref> | ||
== एल्गोरिथम == | == एल्गोरिथम == | ||
Line 19: | Line 19: | ||
=== टॉप-डाउन कार्यान्वयन === | === टॉप-डाउन कार्यान्वयन === | ||
उदाहरण सी-जैसे कोड जो टॉप-डाउन मर्ज सॉर्ट एल्गोरिथम के लिए सूचकांकों का उपयोग करता है जो सूची को पुनरावर्ती रूप से उप-सूचियों में विभाजित करता है (इस उदाहरण में रन कहा जाता है) जब तक उप-सूची का आकार 1 नहीं हो जाता है, तब तक उन उप-सूची को सॉर्ट की गई सूची बनाने के लिए मर्ज कर देता है। प्रत्यावर्तन के प्रत्येक स्तर के साथ मर्ज की दिशा को वैकल्पिक करके कॉपी बैक चरण से बचा जाता है (प्रारंभिक एक बार की प्रतिलिपि को छोड़कर, इससे भी बचा जा सकता है)। इसे समझने में सहायता के लिए, दो तत्वों वाली सरणी पर विचार करें। तत्वों को B [] में कॉपी किया जाता है, फिर वापस A [] में | उदाहरण सी-जैसे कोड जो टॉप-डाउन मर्ज सॉर्ट एल्गोरिथम के लिए सूचकांकों का उपयोग करता है जो सूची को पुनरावर्ती रूप से उप-सूचियों में विभाजित करता है (इस उदाहरण में रन कहा जाता है) जब तक उप-सूची का आकार 1 नहीं हो जाता है, तब तक उन उप-सूची को सॉर्ट की गई सूची बनाने के लिए मर्ज कर देता है। प्रत्यावर्तन के प्रत्येक स्तर के साथ मर्ज की दिशा को वैकल्पिक करके कॉपी बैक चरण से बचा जाता है (प्रारंभिक एक बार की प्रतिलिपि को छोड़कर, इससे भी बचा जा सकता है)। इसे समझने में सहायता के लिए, दो तत्वों वाली सरणी पर विचार करें। तत्वों को B [] में कॉपी किया जाता है, फिर वापस A [] में मर्ज कर दिया जाता है। यदि चार तत्व हैं, जब रिकर्सन स्तर के निचले भाग पर पहुंच जाता है, तो A [] से चलने वाला एकल तत्व B[] में मर्ज कर दिया जाता है, और फिर रिकर्सन के अगले उच्च स्तर पर, उन दो-तत्व रन को A[ में मर्ज कर दिया जाता है। ]. यह पैटर्न प्रत्यावर्तन के प्रत्येक स्तर के साथ जारी रहता है। | ||
// Array A[] has the items to sort; array B[] is a work array. | // Array A[] has the items to sort; array B[] is a work array. | ||
void TopDownMergeSort(A[], B[], n) | void TopDownMergeSort(A[], B[], n) | ||
Line 119: | Line 119: | ||
=== सूचियों का उपयोग करते हुए टॉप-डाउन कार्यान्वयन === | === सूचियों का उपयोग करते हुए टॉप-डाउन कार्यान्वयन === | ||
टॉप-डाउन मर्ज सॉर्ट एल्गोरिथम के लिए [[स्यूडोकोड]] जो इनपुट सूची को पुनरावर्ती रूप से छोटी उपसूचियों में विभाजित करता है जब तक कि उपसूचियां तुच्छ रूप से | टॉप-डाउन मर्ज सॉर्ट एल्गोरिथम के लिए [[स्यूडोकोड]] जो इनपुट सूची को पुनरावर्ती रूप से छोटी उपसूचियों में विभाजित करता है जब तक कि उपसूचियां तुच्छ रूप से सॉर्टेड नहीं हो जाती हैं, और फिर कॉल श्रृंखला को वापस करते समय उपसूचियों को मर्ज कर देता है। | ||
'''function''' merge_sort(''list'' m) '''is''' | '''function''' merge_sort(''list'' m) '''is''' | ||
// ''Base case. A list of zero or one elements is sorted, by definition.'' | // ''Base case. A list of zero or one elements is sorted, by definition.'' | ||
Line 165: | Line 165: | ||
=== सूचियों का उपयोग करके नीचे-ऊपर कार्यान्वयन === | === सूचियों का उपयोग करके नीचे-ऊपर कार्यान्वयन === | ||
बॉटम-अप मर्ज सॉर्ट एल्गोरिथ्म के लिए स्यूडोकोड जो नोड्स के संदर्भों के छोटे निश्चित आकार के सरणी का उपयोग करता है, जहां सरणी [i] या तो आकार 2<sup>i</sup> या [[नल पॉइंटर]] की सूची का संदर्भ है। नोड एक नोड का संदर्भ या सूचक है। मर्ज () फ़ंक्शन टॉप-डाउन मर्ज सूचियों के उदाहरण के समान होगा, यह पहले से ही | बॉटम-अप मर्ज सॉर्ट एल्गोरिथ्म के लिए स्यूडोकोड जो नोड्स के संदर्भों के छोटे निश्चित आकार के सरणी का उपयोग करता है, जहां सरणी [i] या तो आकार 2<sup>i</sup> या [[नल पॉइंटर]] की सूची का संदर्भ है। नोड एक नोड का संदर्भ या सूचक है। मर्ज () फ़ंक्शन टॉप-डाउन मर्ज सूचियों के उदाहरण के समान होगा, यह पहले से ही सॉर्टेड सूचियों को मर्ज करता है, और खाली सूचियों को संभालता है। इस स्थिति में, मर्ज () अपने इनपुट पैरामीटर और रिटर्न वैल्यू के लिए नोड का उपयोग करेगा। | ||
'''function''' merge_sort(''node'' head) '''is''' | '''function''' merge_sort(''node'' head) '''is''' | ||
// return if empty list | // return if empty list | ||
Line 208: | Line 208: | ||
== प्राकृतिक मर्ज सॉर्ट == | == प्राकृतिक मर्ज सॉर्ट == | ||
प्राकृतिक मर्ज सॉर्ट बॉटम-अप मर्ज सॉर्ट के समान है, सिवाय इसके कि इनपुट में अनुक्रम (सॉर्ट | प्राकृतिक मर्ज सॉर्ट बॉटम-अप मर्ज सॉर्ट के समान होता है, सिवाय इसके कि इनपुट में अनुक्रम (सॉर्ट गए सॉर्टेड अनुक्रम) के किसी भी स्वाभाविक रूप से होने वाले रन का शोषण किया जाता है। दोनों मोनोटोनिक और बिटोनिक (वैकल्पिक ऊपर/नीचे) रन का शोषण किया जा सकता है, सूचियों (या समकक्ष टेप या फाइलों) के साथ सुविधाजनक डेटा संरचनाएं ([[कतार (सार डेटा प्रकार)]] या स्टैक (सार डेटा प्रकार) के रूप में उपयोग की जाती हैं)।<ref>{{cite report |last1=Powers |first1=David M. W. |last2=McMahon |first2=Graham B. |date=1983 |section=A compendium of interesting prolog programs |title=DCS Technical Report 8313 |publisher=Department of Computer Science, University of New South Wales}}</ref> बॉटम-अप मर्ज सॉर्ट में, शुरुआती बिंदु मानता है कि प्रत्येक रन आइटम लंबा है। व्यवहार में, यादृच्छिक इनपुट डेटा में कई छोटे रन होंगे जो अभी सॉर्ट किए जाते हैं। विशिष्ट मामले में, प्राकृतिक मर्ज सॉर्ट को उतने पास की आवश्यकता नहीं हो सकती है क्योंकि मर्ज करने के लिए कम रन होते हैं। सबसे अच्छे मामले में, इनपुट पहले से ही सॉर्टेड होता है (अर्थात यह एक रन होता है), इसलिए प्राकृतिक मर्ज सॉर्ट को डेटा के माध्यम से केवल पास बनाने की आवश्यकता है। कई व्यावहारिक मामलों में, लंबे प्राकृतिक रन मौजूद होते हैं, और इस कारण से [[टिमसोर्ट]] के प्रमुख घटक के रूप में प्राकृतिक मर्ज सॉर्ट का उपयोग किया जाता है। उदाहरण: | ||
Start : 3 4 2 1 7 5 8 9 0 6 | Start : 3 4 2 1 7 5 8 9 0 6 | ||
Select runs : (3 4)(2)(1 7)(5 8 9)(0 6) | Select runs : (3 4)(2)(1 7)(5 8 9)(0 6) | ||
Line 214: | Line 214: | ||
Merge : (1 2 3 4 5 7 8 9)(0 6) | Merge : (1 2 3 4 5 7 8 9)(0 6) | ||
Merge : (0 1 2 3 4 5 6 7 8 9) | Merge : (0 1 2 3 4 5 6 7 8 9) | ||
औपचारिक रूप से, प्राकृतिक मर्ज | औपचारिक रूप से, प्राकृतिक मर्ज सॉर्ट को [[एम-इष्टतम छँटाई|रन-इष्टतम]] कहा जाता है, जहाँ <math>\mathtt{Runs}(L)</math> में रनों की संख्या <math>L</math>, से एक कम होती है। | ||
[[टूर्नामेंट छँटाई]] का उपयोग बाहरी | [[टूर्नामेंट छँटाई|टूर्नामेंट]] सॉर्ट का उपयोग बाहरी सॉर्ट एल्गोरिदम के लिए प्रारंभिक रन इकट्ठा करने के लिए किया जाता है। | ||
== पिंग-पोंग मर्ज सॉर्ट == | == पिंग-पोंग मर्ज सॉर्ट == | ||
दो ब्लॉकों को एक साथ मर्ज करने की बजाय, पिंग-पोंग मर्ज चार ब्लॉकों को एक साथ मर्ज करता है। चार सॉर्ट किए गए ब्लॉकों को साथ सहायक स्थान में दो सॉर्ट किए गए ब्लॉकों में मिला दिया जाता है, फिर दो सॉर्ट किए गए ब्लॉकों को वापस मुख्य मेमोरी में मर्ज कर दिया जाता है। इस प्रक्रिया से कॉपी ऑपरेशन को छोड़ा जाता है और कुल मूव की संख्या को आधा कर दिया जाता है। 2014 में विकीसॉर्ट ने चार-एक-साथ मर्ज का एक पब्लिक डोमेन अंतर्गत अमल में लाया गया था, यह तकनीक बाद में [[धैर्य छँटाई|धैर्य]] सॉर्टिंग के लिए अनुकूलन के रूप में वर्णित किया गया था और इसे पिंग-पोंग मर्ज का नाम दिया गया था।<ref name="wikisort">{{cite web | |||
|title = WikiSort. Fast and stable sort algorithm that uses O(1) memory. Public domain. | |title = WikiSort. Fast and stable sort algorithm that uses O(1) memory. Public domain. | ||
|url = https://github.com/BonzaiThePenguin/WikiSort | |url = https://github.com/BonzaiThePenguin/WikiSort | ||
|last = |date=14 Apr 2014 | |last = |date=14 Apr 2014 | ||
}}</ref><ref>{{Cite conference |last1=Chandramouli |first1=Badrish |last2=Goldstein |first2=Jonathan |title=Patience is a Virtue: Revisiting Merge and Sort on Modern Processors |conference=SIGMOD/PODS |year=2014 |url=http://research.microsoft.com/pubs/209622/patsort-sigmod14.pdf}}</ref> | }}</ref><ref>{{Cite conference |last1=Chandramouli |first1=Badrish |last2=Goldstein |first2=Jonathan |title=Patience is a Virtue: Revisiting Merge and Sort on Modern Processors |conference=SIGMOD/PODS |year=2014 |url=http://research.microsoft.com/pubs/209622/patsort-sigmod14.pdf}}</ref> क्वादसोर्ट ने 2020 में इस तकनीक को अमल में लाया और उसे क्वाड मर्ज के नाम से जाना जाता है।<ref name="quadsort">{{cite web | ||
|title = Quadsort is a branchless stable adaptive merge sort. | |title = Quadsort is a branchless stable adaptive merge sort. | ||
|url = https://github.com/scandum/quadsort | |url = https://github.com/scandum/quadsort | ||
Line 232: | Line 232: | ||
== इन-प्लेस मर्ज सॉर्ट == | == इन-प्लेस मर्ज सॉर्ट == | ||
मर्ज सॉर्ट का एक दोष, जब सरणियों पर लागू किया जाता है, तो इसकी {{math|''O''(''n'')}} कार्यशील मेमोरी आवश्यकता होती है। मेमोरी को कम करने या मर्ज सॉर्ट को पूरी तरह से [[इन-प्लेस एल्गोरिदम]] बनाने के लिए कई तरीके सुझाए गए हैं: | |||
* {{Harvtxt| | * {{Harvtxt|क्रोनरोड |1969}} ने मर्ज सॉर्ट का एक वैकल्पिक संस्करण सुझाया जो निरंतर अतिरिक्त स्थान का उपयोग करता है। | ||
* कटजैनेन एट | * कटजैनेन एट अल. एल्गोरिथ्म प्रस्तुत करें जिसके लिए निरंतर मात्रा में कार्यशील मेमोरी की आवश्यकता होती है: इनपुट ऐरे के तत्व को रखने के लिए पर्याप्त स्टोरेज स्पेस, और होल्ड करने के लिए अतिरिक्त स्थान {{math|''O''(1)}} इनपुट ऐरे में पॉइंटर्स। वे हासिल करते हैं। छोटे स्थिरांक के साथ समयबद्ध {{math|''O''(''n'' log ''n'')}} प्राप्त करते हैं, लेकिन उनका एल्गोरिथ्म स्थिर नहीं है।<ref>{{harvtxt|Katajainen|Pasanen|Teuhola|1996}}</ref> | ||
* इन-प्लेस मर्ज एल्गोरिथम तैयार करने के लिए कई प्रयास किए गए हैं जिन्हें इन-प्लेस मर्ज सॉर्ट तैयार करने के लिए मानक (टॉप-डाउन या बॉटम-अप) मर्ज सॉर्ट के साथ जोड़ा जा सकता है। इस मामले में, इन-प्लेस की धारणा को लॉगरिदमिक स्टैक स्पेस लेने के लिए आराम दिया जा सकता है, क्योंकि मानक मर्ज सॉर्ट को अपने स्वयं के स्टैक उपयोग के लिए उस स्थान की आवश्यकता होती है। यह गेफर्ट एट अल द्वारा दिखाया गया था। कि इन-प्लेस में स्थिर | * इन-प्लेस मर्ज एल्गोरिथम तैयार करने के लिए कई प्रयास किए गए हैं जिन्हें इन-प्लेस मर्ज सॉर्ट तैयार करने के लिए मानक (टॉप-डाउन या बॉटम-अप) मर्ज सॉर्ट के साथ जोड़ा जा सकता है। इस मामले में, इन-प्लेस की धारणा को लॉगरिदमिक स्टैक स्पेस लेने के लिए आराम दिया जा सकता है, क्योंकि मानक मर्ज सॉर्ट को अपने स्वयं के स्टैक उपयोग के लिए उस स्थान की आवश्यकता होती है। यह गेफर्ट एट अल द्वारा दिखाया गया था। कि इन-प्लेस में स्थिर मर्ज संभव है {{math|''O''(''n'' log ''n'')}} स्क्रैच स्पेस की निरंतर मात्रा का उपयोग करते हुए समय, लेकिन उनका एल्गोरिथ्म जटिल है और इसमें उच्च स्थिर कारक हैं: लंबाई की सरणियों का मर्ज {{mvar|n}} और {{mvar|m}} ले जा सकते हैं {{math|5''n'' + 12''m'' + ''o''(''m'')}} चलता है।<ref>{{Cite journal | doi = 10.1016/S0304-3975(98)00162-5| title = Asymptotically efficient in-place merging| journal = Theoretical Computer Science| volume = 237| pages = 159–181| year = 2000| last1 = Geffert | first1 = Viliam| last2 = Katajainen | first2 = Jyrki| last3 = Pasanen | first3 = Tomi| issue = 1–2| doi-access = free}}</ref> इस उच्च स्थिर कारक और जटिल इन-प्लेस एल्गोरिदम को सरल और समझने में आसान बनाया गया था। बिंग-चाओ हुआंग और माइकल ए. लैंगस्टन<ref name="Research Contributions">{{cite journal |first1=Bing-Chao |last1=Huang |first2=Michael A. |last2=Langston |title=Practical In-Place Merging |date=March 1988 |journal=Communications of the ACM |volume=31 |issue=3 |pages=348–352 |doi=10.1145/42392.42403|s2cid=4841909 |doi-access=free }}</ref> अतिरिक्त स्थान की निश्चित मात्रा का उपयोग करके सॉर्टेड सूची को मर्ज करने के लिए सीधा रैखिक समय एल्गोरिदम व्यावहारिक इन-प्लेस मर्ज प्रस्तुत किया। उन दोनों ने क्रोनरोड और अन्य के काम का इस्तेमाल किया है। यह रैखिक समय और निरंतर अतिरिक्त स्थान में विलीन हो जाता है। एल्गोरिथ्म मानक मर्ज सॉर्ट एल्गोरिदम की तुलना में थोड़ा अधिक औसत समय लेता है, O(n) अस्थायी अतिरिक्त मेमोरी कोशिकाओं का दोहन करने के लिए दो से कम कारक से मुक्त होता है। हालांकि एल्गोरिथ्म व्यावहारिक रूप से बहुत तेज है लेकिन यह कुछ सूचियों के लिए अस्थिर भी है। लेकिन इसी तरह की अवधारणाओं का उपयोग करके वे इस समस्या को हल करने में सक्षम हैं। अन्य इन-प्लेस एल्गोरिदम में सिममर्ज शामिल है, जो लेता है {{math|''O''((''n'' + ''m'') log (''n'' + ''m''))}} कुल समय और स्थिर है।<ref>{{Cite conference| doi = 10.1007/978-3-540-30140-0_63| chapter = Stable Minimum Storage Merging by Symmetric Comparisons| conference = European Symp. Algorithms| volume = 3221| pages = 714–723| series = Lecture Notes in Computer Science| year = 2004| last1 = Kim | first1 = Pok-Son| last2 = Kutzner | first2 = Arne| title = Algorithms – ESA 2004| isbn = 978-3-540-23025-0| citeseerx=10.1.1.102.4612}}</ref> इस तरह के एल्गोरिथ्म को मर्ज सॉर्ट में प्लग करने से इसकी जटिलता गैर-रैखिक रूप से बढ़ जाती है, लेकिन फिर भी [[चतुर्रेखीय समय]], {{math|''O''(''n'' (log ''n'')<sup>2</sup>)}}. | ||
* [[बाहरी छँटाई]] के कई अनुप्रयोग मर्ज | * [[बाहरी छँटाई|बाहरी]] सॉर्टिंग के कई अनुप्रयोग मर्ज सॉर्ट के रूप का उपयोग करते हैं जहाँ इनपुट अधिक संख्या में उप-सूचियों तक विभाजित हो जाता है, आदर्श रूप से संख्या जिसके लिए उन्हें मर्ज करने से अभी भी वर्तमान में संसाधित पृष्ठ (कंप्यूटर मेमोरी) का सेट मुख्य मेमोरी में फिट हो जाता है। | ||
* आधुनिक स्थिर रैखिक और इन-प्लेस मर्ज वैरिएंट [[ब्लॉक मर्ज सॉर्ट]] है जो स्वैप स्पेस के रूप में उपयोग करने के लिए अद्वितीय मानों का | * आधुनिक स्थिर रैखिक और इन-प्लेस मर्ज वैरिएंट [[ब्लॉक मर्ज सॉर्ट]] है जो स्वैप स्पेस के रूप में उपयोग करने के लिए अद्वितीय मानों का अनुभाग बनाता है। | ||
* बाइनरी | * बाइनरी सेअर्चेस और रोटेशन्स का उपयोग करके अंतरिक्ष ओवरहेड को sqrt (n) तक कम किया जा सकता है।<ref>{{cite web | ||
|title = A New Method for Efficient in-Place Merging | |title = A New Method for Efficient in-Place Merging | ||
|url = https://koreascience.kr/article/CFKO200311922203087.page | |url = https://koreascience.kr/article/CFKO200311922203087.page | ||
|last = |date=1 Sep 2003 | |last = |date=1 Sep 2003 | ||
}}</ref> यह विधि | }}</ref> यह विधि C ++ STL लाइब्रेरी और क्वाडोर्ट द्वारा नियोजित है।<ref name="quadsort">{{cite web | ||
|title = Quadsort is a branchless stable adaptive merge sort. | |title = Quadsort is a branchless stable adaptive merge sort. | ||
|url = https://github.com/scandum/quadsort | |url = https://github.com/scandum/quadsort | ||
|last = |date=8 Jun 2022 | |last = |date=8 Jun 2022 | ||
}}</ref> | }}</ref> | ||
* एकाधिक सूचियों में नकल को कम करने का विकल्प सूचना के नए क्षेत्र को प्रत्येक कुंजी के साथ जोड़ना है (एम में तत्वों को कुंजियाँ कहा जाता है)। इस फ़ील्ड का उपयोग सॉर्ट की गई सूची में कुंजियों और किसी भी संबंधित जानकारी को साथ लिंक करने के लिए किया जाएगा ( कुंजी और उससे संबंधित जानकारी को रिकॉर्ड कहा जाता है)। फिर लिंक मानों को बदलकर सॉर्ट की गई सूचियों का | * एकाधिक सूचियों में नकल को कम करने का विकल्प सूचना के नए क्षेत्र को प्रत्येक कुंजी के साथ जोड़ना है (एम में तत्वों को कुंजियाँ कहा जाता है)। इस फ़ील्ड का उपयोग सॉर्ट की गई सूची में कुंजियों और किसी भी संबंधित जानकारी को साथ लिंक करने के लिए किया जाएगा ( कुंजी और उससे संबंधित जानकारी को रिकॉर्ड कहा जाता है)। फिर लिंक मानों को बदलकर सॉर्ट की गई सूचियों का मर्ज आगे बढ़ता है; किसी भी रिकॉर्ड को स्थानांतरित करने की आवश्यकता नहीं है। फ़ील्ड जिसमें केवल लिंक होता है, आम तौर पर पूरे रिकॉर्ड से छोटा होता है इसलिए कम जगह का भी उपयोग किया जाएगा। यह मानक सॉर्टिंग तकनीक है, जो मर्ज सॉर्ट तक सीमित नहीं है। | ||
* स्पेस ओवरहेड को n/2 तक कम करने का सरल तरीका संयुक्त संरचना के रूप में बाएं और दाएं को बनाए रखना है, केवल m के बाएं हिस्से को अस्थायी स्थान में कॉपी करना है, और मर्ज किए गए आउटपुट को m में रखने के लिए मर्ज रूटीन को निर्देशित करना है। इस संस्करण के साथ मर्ज रूटीन के बाहर अस्थायी स्थान आवंटित करना बेहतर है, ताकि केवल आवंटन की आवश्यकता हो। पहले बताई गई अत्यधिक नकल को भी कम किया गया है, क्योंकि रिटर्न रिजल्ट स्टेटमेंट (उपरोक्त छद्म कोड में फ़ंक्शन मर्ज) से पहले लाइनों की अंतिम जोड़ी अतिश्योक्तिपूर्ण हो जाती है। | * स्पेस ओवरहेड को n/2 तक कम करने का सरल तरीका संयुक्त संरचना के रूप में बाएं और दाएं को बनाए रखना है, केवल m के बाएं हिस्से को अस्थायी स्थान में कॉपी करना है, और मर्ज किए गए आउटपुट को m में रखने के लिए मर्ज रूटीन को निर्देशित करना है। इस संस्करण के साथ मर्ज रूटीन के बाहर अस्थायी स्थान आवंटित करना बेहतर है, ताकि केवल आवंटन की आवश्यकता हो। पहले बताई गई अत्यधिक नकल को भी कम किया गया है, क्योंकि रिटर्न रिजल्ट स्टेटमेंट (उपरोक्त छद्म कोड में फ़ंक्शन मर्ज) से पहले लाइनों की अंतिम जोड़ी अतिश्योक्तिपूर्ण हो जाती है। | ||
== टेप ड्राइव के साथ प्रयोग करें == | == टेप ड्राइव के साथ प्रयोग करें == | ||
[[File:IBM 729 Tape Drives.nasa.jpg|thumb|मर्ज सॉर्ट प्रकार के एल्गोरिदम ने बड़े डेटा सेट को शुरुआती कंप्यूटरों पर सॉर्ट करने की अनुमति दी थी, जिनमें आधुनिक मानकों द्वारा छोटी रैंडम एक्सेस मेमोरी थी। रिकॉर्ड [[चुंबकीय टेप]] पर संग्रहीत किए गए थे और चुंबकीय टेप ड्राइव के किनारों पर संसाधित किए गए थे, जैसे कि ये [[IBM 729]]s।]] | [[File:IBM 729 Tape Drives.nasa.jpg|thumb|मर्ज सॉर्ट प्रकार के एल्गोरिदम ने बड़े डेटा सेट को शुरुआती कंप्यूटरों पर सॉर्ट करने की अनुमति दी थी, जिनमें आधुनिक मानकों द्वारा छोटी रैंडम एक्सेस मेमोरी थी। रिकॉर्ड [[चुंबकीय टेप]] पर संग्रहीत किए गए थे और चुंबकीय टेप ड्राइव के किनारों पर संसाधित किए गए थे, जैसे कि ये [[IBM 729]]s।]]जब सॉर्ट करने के लिए डेटा मेमोरी में फिट कराना संभव नहीं होता है तो [[डिस्क भंडारण|डिस्क]] या [[टेप ड्राइव]] का उपयोग करके एक्सटर्नल मर्ज सॉर्ट को चलाना संभव होता है। एक्सटर्नल सॉर्टिंग व्यक्त करती है कि मर्ज सॉर्ट को डिस्क ड्राइव के साथ कैसे लागू किया जाता है। एक प्रामाणिक टेप ड्राइव सॉर्ट चार टेप ड्राइव का उपयोग करती है। सभी I/O क्रमबद्ध होती है (पास के अंत में रिवाइंड को छोड़कर)। एक न्यूनतम कार्यान्वयन केवल दो रिकॉर्ड बफर्स और कुछ प्रोग्राम चरों के साथ हो सकता है। | ||
चार टेप ड्राइव को A, B, C, D के रूप में नामित करके, मूल डेटा को A पर रखकर, केवल दो रिकॉर्ड बफर्स का उपयोग करते हुए, एल्गोरिदम बॉटम-अप कार्यान्वयन के समान होता है, मेमोरी में एरे के स्थान पर टेप ड्राइव के जोड़ों का उपयोग करते हुए। मूल एल्गोरिदम को निम्नप्रकार से वर्णित किया जा सकता है: | |||
# | # A से रेकॉर्डों के जोड़ों को मर्ज करें; दो-रेकॉर्ड उपसूचियों को C और D में एकान्तरित रूप से लिखें। | ||
# | # C और D से दो-रेकॉर्ड उपसूचियों को चार-रेकॉर्ड उपसूचियों में मर्ज करें; इन्हें एकान्तरित रूप से A और B में लिखें। | ||
# | # A और B से चार-रेकॉर्ड उपसूचियों को आठ-रेकॉर्ड उपसूचियों में मर्ज करें; इन्हें एकान्तरित रूप से C और D में लिखें। | ||
# | # इस प्रक्रिया को एक बार-दो-बार पुनरावृत्ति करें, जब तक आपके पास सभी डेटा को एक ही सूची में, log<sub>2</sub>(''n'') पास में सॉर्ट करने वाली डेटा हो जाए। | ||
बहुत कम | बहुत कम रन्स के साथ शुरू करने की बजाय, आमतौर पर [[हाइब्रिड एल्गोरिदम]] का उपयोग किया जाता है, जहां प्रारंभिक पास में बहुत सारे रेकॉर्ड्स को मेमोरी में पढ़ाया जाता है, उन्हें आंतरिक सॉर्ट किया जाता है ताकि एक लंबा रन बनाया जा सके, और फिर वे लंबे रन्स को आउटपुट सेट पर वितरित किए जाते हैं। यह स्टेप कई पहले के पास को बचाता है। उदाहरण के लिए, 1024 रेकॉर्ड का आंतरिक सॉर्ट नौ पास बचा देगा। आंतरिक सॉर्ट अक्सर बड़ा होता है क्योंकि इसमें इतना लाभ होता है। वास्तव में, ऐसी तकनीकें हैं जो प्रारंभिक रन्स को उपलब्ध आंतरिक मेमोरी से भी लंबा बना सकती हैं। उनमें से एक, क्नूथ का 'स्नोप्लो' ([[द्विआधारी ढेर]], बाइनरी मिन-हीप पर आधारित), औसतन मेमोरी के इस्तेमाल के साइज़ के दोगुना लंबे रन्स उत्पन्न करता है।<ref>{{citation| last=Ferragina| first=Paolo| title=The magic of Algorithms!| chapter=5. Sorting Atomic Items| page=5-4| chapter-url=http://didawiki.cli.di.unipi.it/lib/exe/fetch.php/magistraleinformaticanetworking/ae/ae2018/ferragina_notes_algoeng_2019_vers_5_.pdf| date=2009–2019| archive-url=https://web.archive.org/web/20210512230253/http://didawiki.cli.di.unipi.it/lib/exe/fetch.php/magistraleinformaticanetworking/ae/ae2018/ferragina_notes_algoeng_2019_vers_5_.pdf| archive-date=2021-05-12| url-status=live}}</ref> | ||
कुछ ओवरहेड के साथ, | |||
ऊपरी एल्गोरिदम में कुछ ओवरहेड के साथ, तीन टेप्स का उपयोग किया जा सकता है। O (n log n) चलने का समय दो कतारों, या एक स्टैक और एक कतार, या तीन स्टैक्स का उपयोग करके भी प्राप्त किया जा सकता है। दूसरी दिशा में, k > दो टेप्स (और O(k) आइटम मेमोरी में) का उपयोग करके, हम k/2-वे मर्ज का उपयोग करके O(log k) बार में टेप आपरेशन की संख्या को कम कर सकते हैं। | |||
अधिक परिष्कृत मर्ज सॉर्ट जो टेप (और डिस्क) ड्राइव के उपयोग को अनुकूलित करता है, वह [[पॉलीफ़ेज़ मर्ज सॉर्ट]] है। | अधिक परिष्कृत मर्ज सॉर्ट जो टेप (और डिस्क) ड्राइव के उपयोग को अनुकूलित करता है, वह [[पॉलीफ़ेज़ मर्ज सॉर्ट]] है। | ||
== मर्ज सॉर्ट का अनुकूलन == | == मर्ज सॉर्ट का अनुकूलन == | ||
[[Image:Merge sort animation2.gif|thumb|यादृच्छिक पूर्णांकों की सरणी पर टाइल मर्ज सॉर्ट लागू किया गया। क्षैतिज अक्ष सरणी अनुक्रमणिका है और लंबवत अक्ष पूर्णांक है।]]आधुनिक कंप्यूटरों पर, संदर्भ की स्थानीयता [[सॉफ्टवेयर अनुकूलन]] में सर्वोपरि हो सकती है, क्योंकि बहुस्तरीय [[मेमोरी पदानुक्रम]] का उपयोग किया जाता है। मर्ज सॉर्ट एल्गोरिथम के कैशे (कंप्यूटिंग)-जागरूक संस्करण, जिनके संचालन को विशेष रूप से मशीन के मेमोरी कैश में और बाहर पृष्ठों के संचलन को कम करने के लिए चुना गया है, प्रस्तावित किया गया है। उदाहरण के लिए, द{{visible anchor|tiled merge sort}}एल्गोरिथम आकार S की उपसरणियों तक पहुँचने पर उप-सरणियों का विभाजन बंद कर देता है, जहाँ S CPU के कैश में फिट होने वाले डेटा आइटमों की संख्या है। इनमें से प्रत्येक उप-सरणियों को इन-प्लेस सॉर्टिंग एल्गोरिथम जैसे [[सम्मिलन सॉर्ट]] के साथ | [[Image:Merge sort animation2.gif|thumb|यादृच्छिक पूर्णांकों की सरणी पर टाइल मर्ज सॉर्ट लागू किया गया। क्षैतिज अक्ष सरणी अनुक्रमणिका है और लंबवत अक्ष पूर्णांक है।]]आधुनिक कंप्यूटरों पर, संदर्भ की स्थानीयता [[सॉफ्टवेयर अनुकूलन]] में सर्वोपरि हो सकती है, क्योंकि बहुस्तरीय [[मेमोरी पदानुक्रम]] का उपयोग किया जाता है। मर्ज सॉर्ट एल्गोरिथम के कैशे (कंप्यूटिंग)-जागरूक संस्करण, जिनके संचालन को विशेष रूप से मशीन के मेमोरी कैश में और बाहर पृष्ठों के संचलन को कम करने के लिए चुना गया है, प्रस्तावित किया गया है। उदाहरण के लिए, द{{visible anchor|tiled merge sort}}एल्गोरिथम आकार S की उपसरणियों तक पहुँचने पर उप-सरणियों का विभाजन बंद कर देता है, जहाँ S CPU के कैश में फिट होने वाले डेटा आइटमों की संख्या है। इनमें से प्रत्येक उप-सरणियों को इन-प्लेस सॉर्टिंग एल्गोरिथम जैसे [[सम्मिलन सॉर्ट]] के साथ सॉर्टेड किया जाता है, मेमोरी स्वैप को हतोत्साहित करने के लिए, और सामान्य मर्ज सॉर्ट को मानक पुनरावर्ती फैशन में पूरा किया जाता है। इस एल्गोरिथ्म ने बेहतर प्रदर्शन का प्रदर्शन किया है {{Examples|date=August 2016}} उन मशीनों पर जो कैश ऑप्टिमाइज़ेशन से लाभान्वित होती हैं। {{Harv|LaMarca|Ladner|1997}} | ||
Line 274: | Line 275: | ||
=== समानांतर पुनरावर्तन === के साथ मर्ज करें | === समानांतर पुनरावर्तन === के साथ मर्ज करें | ||
अनुक्रमिक मर्ज सॉर्ट प्रक्रिया को दो चरणों में विभाजित चरण और मर्ज चरण में वर्णित किया जा सकता है। पहले में कई पुनरावर्ती कॉल होते हैं जो बार-बार ही विभाजन प्रक्रिया को तब तक करते हैं जब तक कि अनुवर्ती | अनुक्रमिक मर्ज सॉर्ट प्रक्रिया को दो चरणों में विभाजित चरण और मर्ज चरण में वर्णित किया जा सकता है। पहले में कई पुनरावर्ती कॉल होते हैं जो बार-बार ही विभाजन प्रक्रिया को तब तक करते हैं जब तक कि अनुवर्ती सॉर्ट न हो जाए (जिसमें या कोई तत्व न हो)। सहज ज्ञान युक्त दृष्टिकोण उन पुनरावर्ती कॉलों का समानांतरकरण है।<ref name="clrs">{{Harvtxt|Cormen|Leiserson|Rivest|Stein|2009|pp=797–805}}</ref> निम्नलिखित स्यूडोकोड फोर्क-जॉइन मॉडल कीवर्ड का उपयोग करके समानांतर पुनरावर्तन के साथ मर्ज सॉर्ट का वर्णन करता है: | ||
// ''Sort elements lo through hi (exclusive) of array A.'' | // ''Sort elements lo through hi (exclusive) of array A.'' | ||
Line 284: | Line 285: | ||
'''join''' | '''join''' | ||
merge(A, lo, mid, hi) | merge(A, lo, mid, hi) | ||
यह एल्गोरिथ्म अनुक्रमिक संस्करण का तुच्छ संशोधन है और अच्छी तरह से समानांतर नहीं होता है। इसलिए, इसका speedup बहुत प्रभावशाली नहीं है। इसमें समानांतर एल्गोरिदम का विश्लेषण # का अवलोकन है <math>\Theta(n)</math>, जो केवल सुधार है <math>\Theta(\log n)</math> अनुक्रमिक संस्करण की तुलना में ([[एल्गोरिदम का परिचय]] देखें)। यह मुख्य रूप से अनुक्रमिक | यह एल्गोरिथ्म अनुक्रमिक संस्करण का तुच्छ संशोधन है और अच्छी तरह से समानांतर नहीं होता है। इसलिए, इसका speedup बहुत प्रभावशाली नहीं है। इसमें समानांतर एल्गोरिदम का विश्लेषण # का अवलोकन है <math>\Theta(n)</math>, जो केवल सुधार है <math>\Theta(\log n)</math> अनुक्रमिक संस्करण की तुलना में ([[एल्गोरिदम का परिचय]] देखें)। यह मुख्य रूप से अनुक्रमिक मर्ज विधि के कारण है, क्योंकि यह समांतर निष्पादन की बाधा है। | ||
=== समानांतर मर्जिंग === के साथ मर्ज सॉर्ट करें | === समानांतर मर्जिंग === के साथ मर्ज सॉर्ट करें | ||
{{Main|Merge algorithm#Parallel merge}} | {{Main|Merge algorithm#Parallel merge}} | ||
समांतर | समांतर मर्ज एल्गोरिदम का उपयोग करके बेहतर समांतरता प्राप्त की जा सकती है। एल्गोरिद्म का परिचय | कॉर्मेन एट अल। बाइनरी वेरिएंट प्रस्तुत करें जो दो सॉर्ट किए गए उप-अनुक्रमों को सॉर्ट किए गए आउटपुट अनुक्रम में मिला देता है।<ref name="clrs" /> | ||
अनुक्रमों में से में (असमान लंबाई होने पर लंबा), मध्य सूचकांक का तत्व चुना जाता है। अन्य अनुक्रम में इसकी स्थिति इस तरह से निर्धारित की जाती है कि यदि यह तत्व इस स्थिति में डाला जाता है तो यह क्रम | अनुक्रमों में से में (असमान लंबाई होने पर लंबा), मध्य सूचकांक का तत्व चुना जाता है। अन्य अनुक्रम में इसकी स्थिति इस तरह से निर्धारित की जाती है कि यदि यह तत्व इस स्थिति में डाला जाता है तो यह क्रम सॉर्टेड रहेगा। इस प्रकार, कोई जानता है कि दोनों अनुक्रमों से कितने अन्य तत्व छोटे हैं और आउटपुट अनुक्रम में चयनित तत्व की स्थिति की गणना की जा सकती है। इस तरह से बनाए गए छोटे और बड़े तत्वों के आंशिक अनुक्रमों के लिए, मर्ज एल्गोरिथम को फिर से समानांतर में तब तक निष्पादित किया जाता है जब तक कि पुनरावर्तन का आधार मामला नहीं हो जाता। | ||
निम्नलिखित स्यूडोकोड समानांतर मर्ज एल्गोरिथम (कॉर्मेन एट अल से अपनाया गया) का उपयोग करके संशोधित समानांतर मर्ज सॉर्ट विधि दिखाता है। | निम्नलिखित स्यूडोकोड समानांतर मर्ज एल्गोरिथम (कॉर्मेन एट अल से अपनाया गया) का उपयोग करके संशोधित समानांतर मर्ज सॉर्ट विधि दिखाता है। | ||
Line 316: | Line 317: | ||
<math display="block"> T_{\infty}^{\text{sort}}(n) = T_{\infty}^{\text{sort}}\left(\frac {n} {2}\right) + T_{\infty}^{\text{merge}}(n) | <math display="block"> T_{\infty}^{\text{sort}}(n) = T_{\infty}^{\text{sort}}\left(\frac {n} {2}\right) + T_{\infty}^{\text{merge}}(n) | ||
= T_{\infty}^{\text{sort}}\left(\frac {n} {2}\right) + \Theta \left( \log(n)^2\right).</math> | = T_{\infty}^{\text{sort}}\left(\frac {n} {2}\right) + \Theta \left( \log(n)^2\right).</math> | ||
समांतर | समांतर मर्ज प्रक्रिया की जटिलता के बारे में विस्तृत जानकारी के लिए, मर्ज एल्गोरिदम # समांतर मर्ज देखें। | ||
इस पुनरावृत्ति का हल इसके द्वारा दिया गया है | इस पुनरावृत्ति का हल इसके द्वारा दिया गया है | ||
<math display="block"> T_{\infty}^{\text{sort}} = \Theta \left ( \log(n)^3 \right).</math> | <math display="block"> T_{\infty}^{\text{sort}} = \Theta \left ( \log(n)^3 \right).</math> | ||
यह समांतर | यह समांतर मर्ज एल्गोरिदम समानता तक पहुंचता है <math display="inline">\Theta \left(\frac{n}{(\log n)^2}\right)</math>, जो पिछले एल्गोरिथम की समानता से बहुत अधिक है। इस तरह का प्रकार व्यवहार में अच्छा प्रदर्शन कर सकता है जब तेजी से स्थिर अनुक्रमिक सॉर्ट, जैसे सम्मिलन सॉर्ट, और छोटे सरणियों को मर्ज करने के लिए बेस केस के रूप में तेज अनुक्रमिक मर्ज के साथ जोड़ा जाता है।<ref>Victor J. Duvanenko "Parallel Merge Sort" Dr. Dobb's Journal & blog [https://duvanenko.tech.blog/2018/01/13/parallel-merge-sort/] and GitHub repo C++ implementation [https://github.com/DragonSpit/ParallelAlgorithms]</ref> | ||
=== समानांतर मल्टीवे मर्ज सॉर्ट === | === समानांतर मल्टीवे मर्ज सॉर्ट === | ||
यह मर्ज सॉर्ट एल्गोरिदम को बाइनरी मर्ज विधि तक सीमित करने के लिए मनमाना लगता है, क्योंकि आमतौर पर p > 2 प्रोसेसर उपलब्ध होते हैं। के-वे मर्ज एल्गोरिथम का उपयोग करने के लिए बेहतर तरीका हो सकता है | के-वे मर्ज विधि, बाइनरी मर्ज का सामान्यीकरण, जिसमें <math>k</math> | यह मर्ज सॉर्ट एल्गोरिदम को बाइनरी मर्ज विधि तक सीमित करने के लिए मनमाना लगता है, क्योंकि आमतौर पर p > 2 प्रोसेसर उपलब्ध होते हैं। के-वे मर्ज एल्गोरिथम का उपयोग करने के लिए बेहतर तरीका हो सकता है | के-वे मर्ज विधि, बाइनरी मर्ज का सामान्यीकरण, जिसमें <math>k</math> सॉर्टेड अनुक्रमों को मिला दिया जाता है। यह मर्ज वेरिएंट [[समानांतर रैंडम-एक्सेस मशीन]] पर सॉर्टिंग एल्गोरिदम का वर्णन करने के लिए उपयुक्त है।<ref>{{cite web|author1=Peter Sanders |author2=Johannes Singler |date=2008 |title=Lecture ''Parallel algorithms'' |url=http://algo2.iti.kit.edu/sanders/courses/paralg08/singler.pdf |access-date=2020-05-02}}</ref><ref name=":0">{{Cite journal|title=Practical Massively Parallel Sorting |journal=Proceedings of the 27th ACM Symposium on Parallelism in Algorithms and Architectures|year=2015|doi=10.1145/2755573.2755595|last1=Axtmann|first1=Michael|last2=Bingmann|first2=Timo|last3=Sanders|first3=Peter|last4=Schulz|first4=Christian|pages=13–23|isbn=9781450335881|s2cid=18249978|url=https://publikationen.bibliothek.kit.edu/1000050651/37296033}}</ref> | ||
==== मूल विचार ==== | ==== मूल विचार ==== | ||
[[File:Parallel_multiway_mergesort_process.svg|alt=|thumb|चार प्रोसेसरों पर समानांतर मल्टीवे | [[File:Parallel_multiway_mergesort_process.svg|alt=|thumb|चार प्रोसेसरों पर समानांतर मल्टीवे मर्ज प्रक्रिया <math>t_0</math> को <math>t_3</math>.]]के अवर्गीकृत अनुक्रम को देखते हुए <math>n</math> तत्वों, लक्ष्य अनुक्रम को सॉर्टेड करना है <math>p</math> उपलब्ध [[प्रोसेसर (कंप्यूटिंग)]]। इन तत्वों को सभी प्रोसेसरों के बीच समान रूप से वितरित किया जाता है और अनुक्रमिक सॉर्टिंग एल्गोरिदम का उपयोग करके स्थानीय रूप से सॉर्ट किया जाता है। इसलिए, अनुक्रम में सॉर्टेड अनुक्रम होते हैं <math>S_1, ..., S_p</math> लंबाई का <math display="inline">\lceil \frac{n}{p} \rceil</math>. सरलीकरण के लिए <math>n</math> का गुणक हो <math>p</math>, ताकि <math display="inline">\left\vert S_i \right\vert = \frac{n}{p}</math> के लिए <math>i = 1, ..., p</math>. | ||
इन अनुक्रमों का उपयोग बहु-अनुक्रम चयन/स्प्लिटर चयन करने के लिए किया जाएगा। के लिए <math>j = 1,..., p</math>, एल्गोरिदम स्प्लिटर तत्वों को निर्धारित करता है <math>v_j | इन अनुक्रमों का उपयोग बहु-अनुक्रम चयन/स्प्लिटर चयन करने के लिए किया जाएगा। के लिए <math>j = 1,..., p</math>, एल्गोरिदम स्प्लिटर तत्वों को निर्धारित करता है <math>v_j | ||
</math> वैश्विक रैंक के साथ <math display="inline">k = j \frac{n}{p}</math>. फिर की इसी स्थिति <math>v_1, ..., v_p</math> प्रत्येक क्रम में <math>S_i</math> [[बाइनरी सर्च एल्गोरिथम]] के साथ निर्धारित किया जाता है और इस प्रकार <math>S_i</math> आगे विभाजित हैं <math>p</math> अनुवर्ती <math>S_{i,1}, ..., S_{i,p}</math> साथ <math display="inline">S_{i,j} := \{x \in S_i | rank(v_{j-1}) < rank(x) \le rank(v_j)\}</math>. | </math> वैश्विक रैंक के साथ <math display="inline">k = j \frac{n}{p}</math>. फिर की इसी स्थिति <math>v_1, ..., v_p</math> प्रत्येक क्रम में <math>S_i</math> [[बाइनरी सर्च एल्गोरिथम]] के साथ निर्धारित किया जाता है और इस प्रकार <math>S_i</math> आगे विभाजित हैं <math>p</math> अनुवर्ती <math>S_{i,1}, ..., S_{i,p}</math> साथ <math display="inline">S_{i,j} := \{x \in S_i | rank(v_{j-1}) < rank(x) \le rank(v_j)\}</math>. | ||
इसके अलावा, के तत्व <math>S_{1,i}, ..., S_{p,i}</math> प्रोसेसर को सौंपा गया है <math>i</math>, का अर्थ रैंक के बीच के सभी तत्व हैं <math display="inline">(i-1) \frac{n}{p}</math> और रैंक <math display="inline">i \frac{n}{p}</math>, जो सभी में वितरित हैं <math>S_i</math>. इस प्रकार, प्रत्येक प्रोसेसर को | इसके अलावा, के तत्व <math>S_{1,i}, ..., S_{p,i}</math> प्रोसेसर को सौंपा गया है <math>i</math>, का अर्थ रैंक के बीच के सभी तत्व हैं <math display="inline">(i-1) \frac{n}{p}</math> और रैंक <math display="inline">i \frac{n}{p}</math>, जो सभी में वितरित हैं <math>S_i</math>. इस प्रकार, प्रत्येक प्रोसेसर को सॉर्टेड अनुक्रमों का क्रम प्राप्त होता है। तथ्य यह है कि रैंक <math>k</math> विभाजक तत्वों की <math>v_i</math> विश्व स्तर पर चुना गया था, दो महत्वपूर्ण गुण प्रदान करता है: ओर, <math>k</math> चुना गया था ताकि प्रत्येक प्रोसेसर अभी भी काम कर सके <math display="inline">n/p</math> असाइनमेंट के बाद तत्व एल्गोरिथ्म पूरी तरह से [[लोड संतुलन (कंप्यूटिंग)]] | लोड-संतुलित है। दूसरी ओर, प्रोसेसर पर सभी तत्व <math>i</math> प्रोसेसर पर सभी तत्वों से कम या बराबर हैं <math>i+1</math>. इसलिए, प्रत्येक प्रोसेसर के-वे मर्ज एल्गोरिथम | पी-वे मर्ज को स्थानीय रूप से निष्पादित करता है और इस प्रकार इसके उप-अनुक्रमों से सॉर्टेड अनुक्रम प्राप्त करता है। दूसरी संपत्ति के कारण, कोई और पी-वे-मर्ज नहीं करना पड़ता है, परिणाम केवल प्रोसेसर संख्या के क्रम में साथ रखे जाते हैं। | ||
==== बहु-अनुक्रम चयन ==== | ==== बहु-अनुक्रम चयन ==== | ||
अपने सरलतम रूप में, दिया गया <math>p</math> | अपने सरलतम रूप में, दिया गया <math>p</math> सॉर्टेड अनुक्रम <math>S_1, ..., S_p</math> पर समान रूप से वितरित <math>p</math> प्रोसेसर और रैंक <math>k</math>, कार्य तत्व खोजना है <math>x</math> वैश्विक रैंक के साथ <math>k</math> अनुक्रमों के मिलन में। इसलिए, इसका उपयोग प्रत्येक को विभाजित करने के लिए किया जा सकता है <math>S_i</math> स्प्लिटर इंडेक्स पर दो भागों में <math>l_i</math>, जहां निचले हिस्से में केवल ऐसे तत्व होते हैं जो इससे छोटे होते हैं <math>x</math>, जबकि तत्वों से बड़ा <math>x</math> ऊपरी भाग में स्थित हैं। | ||
प्रस्तुत अनुक्रमिक एल्गोरिदम प्रत्येक अनुक्रम में विभाजन के सूचकांक लौटाता है, उदा। सूचकांक <math>l_i</math> क्रम में <math>S_i</math> ऐसा है कि <math>S_i[l_i]</math> से कम वैश्विक रैंक है <math>k</math> और <math>\mathrm{rank}\left(S_i[l_i+1]\right) \ge k</math>.<ref>{{cite web |author=Peter Sanders |date=2019 |title=Lecture ''Parallel algorithms'' |url=http://algo2.iti.kit.edu/sanders/courses/paralg19/vorlesung.pdf |access-date=2020-05-02}}</ref> | प्रस्तुत अनुक्रमिक एल्गोरिदम प्रत्येक अनुक्रम में विभाजन के सूचकांक लौटाता है, उदा। सूचकांक <math>l_i</math> क्रम में <math>S_i</math> ऐसा है कि <math>S_i[l_i]</math> से कम वैश्विक रैंक है <math>k</math> और <math>\mathrm{rank}\left(S_i[l_i+1]\right) \ge k</math>.<ref>{{cite web |author=Peter Sanders |date=2019 |title=Lecture ''Parallel algorithms'' |url=http://algo2.iti.kit.edu/sanders/courses/paralg19/vorlesung.pdf |access-date=2020-05-02}}</ref> | ||
एल्गोरिद्म | एल्गोरिद्म msSelect(S : सॉर्टेड अनुक्रमों की सरणी [S_1,..,S_p], k : int) है | ||
'''algorithm''' msSelect(S : Array of sorted Sequences [S_1,..,S_p], k : int) '''is''' | '''algorithm''' msSelect(S : Array of sorted Sequences [S_1,..,S_p], k : int) '''is''' | ||
Line 384: | Line 385: | ||
==== विश्लेषण ==== | ==== विश्लेषण ==== | ||
सबसे पहले, प्रत्येक प्रोसेसर असाइन किए गए सॉर्ट करता है <math>n/p</math> जटिलता के साथ | सबसे पहले, प्रत्येक प्रोसेसर असाइन किए गए सॉर्ट करता है <math>n/p</math> जटिलता के साथ सॉर्ट एल्गोरिथ्म का स्थानीय रूप से उपयोग करने वाले तत्व <math>\mathcal{O}\left( n/p \; \log ( n/p) \right)</math>. उसके बाद, फाड़नेवाला तत्वों की समय पर गणना की जानी चाहिए <math>\mathcal{O}\left(p \,\log(n/p) \log (n) \right)</math>. अंत में, के प्रत्येक समूह <math>p</math> विभाजन को प्रत्येक प्रोसेसर द्वारा चलने वाले समय के साथ समानांतर में मर्ज करना पड़ता है <math>\mathcal{O}(\log(p)\; n/p )</math> अनुक्रमिक मर्ज एल्गोरिथम का उपयोग करना | पी-वे मर्ज एल्गोरिथम। इस प्रकार, समग्र चलने का समय इसके द्वारा दिया जाता है | ||
<math>\mathcal{O}\left( \frac n p \log\left(\frac n p\right) + p \log \left( \frac n p\right) \log (n) + \frac n p \log (p) \right)</math>. | <math>\mathcal{O}\left( \frac n p \log\left(\frac n p\right) + p \log \left( \frac n p\right) \log (n) + \frac n p \log (p) \right)</math>. | ||
Line 395: | Line 396: | ||
=== आगे के संस्करण === | === आगे के संस्करण === | ||
मर्ज सॉर्ट पहले सॉर्टिंग एल्गोरिदम में से था जहां ओ (1) मर्ज सुनिश्चित करने के लिए रिचर्ड कोल ने चतुर सबसैंपलिंग एल्गोरिदम का उपयोग करके इष्टतम गति प्राप्त की थी।<ref>{{Cite journal |last1=Cole |first1=Richard |date=August 1988 |title=Parallel merge sort |journal=SIAM J. Comput. |volume=17 |issue=4 |pages=770–785 |citeseerx=10.1.1.464.7118 |doi=10.1137/0217049|s2cid=2416667 }}</ref> अन्य परिष्कृत समानांतर | मर्ज सॉर्ट पहले सॉर्टिंग एल्गोरिदम में से था जहां ओ (1) मर्ज सुनिश्चित करने के लिए रिचर्ड कोल ने चतुर सबसैंपलिंग एल्गोरिदम का उपयोग करके इष्टतम गति प्राप्त की थी।<ref>{{Cite journal |last1=Cole |first1=Richard |date=August 1988 |title=Parallel merge sort |journal=SIAM J. Comput. |volume=17 |issue=4 |pages=770–785 |citeseerx=10.1.1.464.7118 |doi=10.1137/0217049|s2cid=2416667 }}</ref> अन्य परिष्कृत समानांतर सॉर्ट एल्गोरिदम कम स्थिरांक के साथ समान या बेहतर समय सीमा प्राप्त कर सकते हैं। उदाहरण के लिए, 1991 में डेविड पॉवर्स ने समानांतर क्विकसॉर्ट (और संबंधित [[आपको कामयाबी मिले]]) का वर्णन किया था जो ओ (लॉग एन) समय में [[सीआरसीडब्ल्यू]] समानांतर रैंडम-एक्सेस मशीन (पीआरएएम) पर एन प्रोसेसर के साथ विभाजन को स्पष्ट रूप से निष्पादित करके संचालित कर सकता है।<ref>{{cite book |last=Powers |first=David M. W. |chapter-url=http://citeseer.ist.psu.edu/327487.html |chapter=Parallelized Quicksort and Radixsort with Optimal Speedup |title=Proceedings of International Conference on Parallel Computing Technologies, Novosibirsk |date=1991 |archive-url=https://web.archive.org/web/20070525234405/http://citeseer.ist.psu.edu/327487.html |archive-date=2007-05-25}}</ref> पॉवर्स आगे दिखाता है कि O((log n) पर बैचर के [[बिटोनिक सॉर्टर]] का पाइपलाइन संस्करण<sup>2</sup>) तितली [[छँटाई नेटवर्क|सॉर्ट नेटवर्क]] पर समय वास्तव में PRAM पर उसके O(log n) प्रकार की तुलना में तेज़ है, और वह तुलना, मूलांक और समानांतर सॉर्ट में छिपे हुए ओवरहेड्स की विस्तृत चर्चा प्रदान करता है।<ref>{{cite conference |last=Powers |first=David M. W. |url= http://david.wardpowers.info/Research/AI/papers/199501-ACAW-PUPC.pdf |title=Parallel Unification: Practical Complexity |conference=Australasian Computer Architecture Workshop Flinders University |date=January 1995}}</ref> | ||
Revision as of 23:15, 10 July 2023
Class | सॉर्टिंग एल्गोरिदम |
---|---|
Data structure | ऐरे |
Worst-case performance | |
Best-case performance | typical, natural variant |
Average performance | |
Worst-case space complexity | total with auxiliary, auxiliary with linked lists[1] |
कंप्यूटर विज्ञान में, मर्ज सॉर्ट (मर्जसॉर्ट के रूप में भी लिखा जाता है) कुशल, सामान्य-उद्देश्य और तुलना-आधारित सॉर्टिंग एल्गोरिथम है। अधिकांश कार्यान्वयन सॉर्ट एल्गोरिथ्म स्थिरता उत्पन्न करते हैं, जिसका अर्थ है कि समान तत्वों का क्रम इनपुट और आउटपुट में एक ही होता है। मर्ज सॉर्ट विभाजन-और-विजय एल्गोरिथम है जिसका आविष्कार जॉन वॉन न्यूमैन ने 1945 में किया था।[2] विस्तृत विवरण और नीचे से उपर तक मर्ज सॉर्ट काविश्लेषण गोल्डस्टाइन और वन न्यूमैन की रिपोर्ट में 1948 में प्रकट हुआ था।[3]
एल्गोरिथम
संकल्पनात्मक रूप से, मर्ज सॉर्ट निम्नलिखित तरीके से काम करता है:
- अनक्रमित सूची को n उप-सूचियों में विभाजित करें, प्रत्येक में एक तत्व होना चाहिए (एक तत्व की सूची को स्थिर माना जाता है)।
- बार-बार उप-सूचियों को मर्ज करके नई सूचियाँ उत्पन्न करें जो कि सॉर्ट हो जाएं, जब तक कि केवल एक ही उप-सूची बचें। यह सॉर्टेड सूची होगी।
टॉप-डाउन कार्यान्वयन
उदाहरण सी-जैसे कोड जो टॉप-डाउन मर्ज सॉर्ट एल्गोरिथम के लिए सूचकांकों का उपयोग करता है जो सूची को पुनरावर्ती रूप से उप-सूचियों में विभाजित करता है (इस उदाहरण में रन कहा जाता है) जब तक उप-सूची का आकार 1 नहीं हो जाता है, तब तक उन उप-सूची को सॉर्ट की गई सूची बनाने के लिए मर्ज कर देता है। प्रत्यावर्तन के प्रत्येक स्तर के साथ मर्ज की दिशा को वैकल्पिक करके कॉपी बैक चरण से बचा जाता है (प्रारंभिक एक बार की प्रतिलिपि को छोड़कर, इससे भी बचा जा सकता है)। इसे समझने में सहायता के लिए, दो तत्वों वाली सरणी पर विचार करें। तत्वों को B [] में कॉपी किया जाता है, फिर वापस A [] में मर्ज कर दिया जाता है। यदि चार तत्व हैं, जब रिकर्सन स्तर के निचले भाग पर पहुंच जाता है, तो A [] से चलने वाला एकल तत्व B[] में मर्ज कर दिया जाता है, और फिर रिकर्सन के अगले उच्च स्तर पर, उन दो-तत्व रन को A[ में मर्ज कर दिया जाता है। ]. यह पैटर्न प्रत्यावर्तन के प्रत्येक स्तर के साथ जारी रहता है।
// Array A[] has the items to sort; array B[] is a work array. void TopDownMergeSort(A[], B[], n) { CopyArray(A, 0, n, B); // one time copy of A[] to B[] TopDownSplitMerge(A, 0, n, B); // sort data from B[] into A[] } // Split A[] into 2 runs, sort both runs into B[], merge both runs from B[] to A[] // iBegin is inclusive; iEnd is exclusive (A[iEnd] is not in the set). void TopDownSplitMerge(B[], iBegin, iEnd, A[]) { if (iEnd - iBegin <= 1) // if run size == 1 return; // consider it sorted // split the run longer than 1 item into halves iMiddle = (iEnd + iBegin) / 2; // iMiddle = mid point // recursively sort both runs from array A[] into B[] TopDownSplitMerge(A, iBegin, iMiddle, B); // sort the left run TopDownSplitMerge(A, iMiddle, iEnd, B); // sort the right run // merge the resulting runs from array B[] into A[] TopDownMerge(B, iBegin, iMiddle, iEnd, A); } // Left source half is A[ iBegin:iMiddle-1]. // Right source half is A[iMiddle:iEnd-1 ]. // Result is B[ iBegin:iEnd-1 ]. void TopDownMerge(B[], iBegin, iMiddle, iEnd, A[]) { i = iBegin, j = iMiddle; // While there are elements in the left or right runs... for (k = iBegin; k < iEnd; k++) { // If left run head exists and is <= existing right run head. if (i < iMiddle && (j >= iEnd || A[i] <= A[j])) { B[k] = A[i]; i = i + 1; } else { B[k] = A[j]; j = j + 1; } } } void CopyArray(A[], iBegin, iEnd, B[]) { for (k = iBegin; k < iEnd; k++) B[k] = A[k]; }
संपूर्ण सरणी को सॉर्ट करना TopDownMergeSort(A, B, length(A))द्वारा पूरा किया जाता है।
नीचे-ऊपर कार्यान्वयन
नीचे-ऊपर मर्ज सॉर्ट एल्गोरिथम के लिए सूचकांकों का उपयोग करने वाला उदाहरण सी-जैसा कोड जो सूची को आकार 1 के n उप-सूचियों (इस उदाहरण में रन कहा जाता है) की सरणी के रूप में मानता है, और पुनरावृत्त रूप से दो बफ़र्स के बीच उप-सूचियों को आगे और पीछे मर्ज करता है:
// array A[] has the items to sort; array B[] is a work array void BottomUpMergeSort(A[], B[], n) { // Each 1-element run in A is already "sorted". // Make successively longer sorted runs of length 2, 4, 8, 16... until the whole array is sorted. for (width = 1; width < n; width = 2 * width) { // Array A is full of runs of length width. for (i = 0; i < n; i = i + 2 * width) { // Merge two runs: A[i:i+width-1] and A[i+width:i+2*width-1] to B[] // or copy A[i:n-1] to B[] ( if (i+width >= n) ) BottomUpMerge(A, i, min(i+width, n), min(i+2*width, n), B); } // Now work array B is full of runs of length 2*width. // Copy array B to array A for the next iteration. // A more efficient implementation would swap the roles of A and B. CopyArray(B, A, n); // Now array A is full of runs of length 2*width. } } // Left run is A[iLeft :iRight-1]. // Right run is A[iRight:iEnd-1 ]. void BottomUpMerge(A[], iLeft, iRight, iEnd, B[]) { i = iLeft, j = iRight; // While there are elements in the left or right runs... for (k = iLeft; k < iEnd; k++) { // If left run head exists and is <= existing right run head. if (i < iRight && (j >= iEnd || A[i] <= A[j])) { B[k] = A[i]; i = i + 1; } else { B[k] = A[j]; j = j + 1; } } } void CopyArray(B[], A[], n) { for (i = 0; i < n; i++) A[i] = B[i]; }
सूचियों का उपयोग करते हुए टॉप-डाउन कार्यान्वयन
टॉप-डाउन मर्ज सॉर्ट एल्गोरिथम के लिए स्यूडोकोड जो इनपुट सूची को पुनरावर्ती रूप से छोटी उपसूचियों में विभाजित करता है जब तक कि उपसूचियां तुच्छ रूप से सॉर्टेड नहीं हो जाती हैं, और फिर कॉल श्रृंखला को वापस करते समय उपसूचियों को मर्ज कर देता है।
function merge_sort(list m) is // Base case. A list of zero or one elements is sorted, by definition. if length of m ≤ 1 then return m // Recursive case. First, divide the list into equal-sized sublists // consisting of the first half and second half of the list. // This assumes lists start at index 0. var left := empty list var right := empty list for each x with index i in m do if i < (length of m)/2 then add x to left else add x to right // Recursively sort both sublists. left := merge_sort(left) right := merge_sort(right) // Then merge the now-sorted sublists. return merge(left, right)
इस उदाहरण में, merge फ़ंक्शन बाएँ और दाएँ उप-सूची को मर्ज करता है।
function merge(left, right) is var result := empty list while left is not empty and right is not empty do if first(left) ≤ first(right) then append first(left) to result left := rest(left) else append first(right) to result right := rest(right) // Either left or right may have elements left; consume them. // (Only one of the following loops will actually be entered.) while left is not empty do append first(left) to result left := rest(left) while right is not empty do append first(right) to result right := rest(right) return result
सूचियों का उपयोग करके नीचे-ऊपर कार्यान्वयन
बॉटम-अप मर्ज सॉर्ट एल्गोरिथ्म के लिए स्यूडोकोड जो नोड्स के संदर्भों के छोटे निश्चित आकार के सरणी का उपयोग करता है, जहां सरणी [i] या तो आकार 2i या नल पॉइंटर की सूची का संदर्भ है। नोड एक नोड का संदर्भ या सूचक है। मर्ज () फ़ंक्शन टॉप-डाउन मर्ज सूचियों के उदाहरण के समान होगा, यह पहले से ही सॉर्टेड सूचियों को मर्ज करता है, और खाली सूचियों को संभालता है। इस स्थिति में, मर्ज () अपने इनपुट पैरामीटर और रिटर्न वैल्यू के लिए नोड का उपयोग करेगा।
function merge_sort(node head) is // return if empty list if head = nil then return nil var node array[32]; initially all nil var node result var node next var int i result := head // merge nodes into array while result ≠ nil do next := result.next; result.next := nil for (i = 0; (i < 32) && (array[i] ≠ nil); i += 1) do result := merge(array[i], result) array[i] := nil // do not go past end of array if i = 32 then i -= 1 array[i] := result result := next // merge array into single list result := nil for (i = 0; i < 32; i += 1) do result := merge(array[i], result) return result
विश्लेषण
एन ऑब्जेक्ट्स को सॉर्ट करने में, मर्ज सॉर्ट का औसत प्रदर्शन और बिग ओ नोटेशन (एन लॉग एन) का सबसे खराब प्रदर्शन होता है। यदि लंबाई n की सूची के लिए मर्ज सॉर्ट का रनिंग टाइम T(n) है, तो पुनरावृत्ति संबंध T(n) = 2T(n/2) + n एल्गोरिथम की परिभाषा का अनुसरण करता है (एल्गोरिथ्म को दो सूचियों पर लागू करें) मूल सूची के आधे आकार का, और परिणामी दो सूचियों को मर्ज करने के लिए उठाए गए n चरणों को जोड़ें)।[4] बंद रूप मास्टर प्रमेय (एल्गोरिदम का विश्लेषण) फूट डालो और जीत पुनरावृत्ति के लिए मास्टर प्रमेय से आता है।
सबसे खराब स्थिति में मर्ज सॉर्ट द्वारा की गई तुलनाओं की संख्या सॉर्टिंग संख्याओं द्वारा दी गई है। ये संख्याएँ (n ⌈बाइनरी लघुगणक n⌉ − 2⌈lg n⌉ + 1) के बराबर या उससे थोड़ी छोटी हैं), जो (n lg n − n + 1) और (n lg n + n + O(lg n)) के बीच है।[5] मर्ज सॉर्ट का सबसे अच्छा मामला इसके सबसे खराब मामले की तुलना में लगभग आधे पुनरावृत्तियों को लेता है।[6]
बड़े n और बेतरतीब ढंग से ऑर्डर की गई इनपुट सूची के लिए, मर्ज सॉर्ट की अपेक्षित (औसत) तुलनाओं की संख्या सबसे खराब स्थिति से α·n कम होती है, जहां
सबसे खराब स्थिति में, मर्ज सॉर्ट अपने औसत मामले में क्विकॉर्ट की तुलना में लगभग 39% कम तुलना का उपयोग करता है, और चाल के संदर्भ में, मर्ज सॉर्ट की सबसे खराब स्थिति जटिलता बड़ी ओ नोटेशन (n log n) है - वही जटिलता जो जल्दी से सुलझाएं के सबसे अच्छे मामले में होती है।[6]
कुछ प्रकार की सूचियों के लिए मर्ज सॉर्ट क्विकॉर्ट से अधिक कुशल है यदि सॉर्ट किए जाने वाले डेटा को केवल अनुक्रमिक रूप से कुशलता से एक्सेस किया जा सकता है, और इस प्रकार लिस्प प्रोग्रामिंग भाषा जैसी भाषाओं में लोकप्रिय है, जहां क्रमिक रूप से एक्सेस की गई डेटा संरचनाएं बहुत आम हैं। क्विकॉर्ट के कुछ (कुशल) कार्यान्वयन के विपरीत, मर्ज सॉर्ट स्थिर प्रकार है।
मर्ज सॉर्ट का सबसे आम कार्यान्वयन जगह में सॉर्ट नहीं होता है;[7] इसलिए, सॉर्ट किए गए आउटपुट को संग्रहीत करने के लिए इनपुट की मेमोरी आकार को आवंटित किया जाना चाहिए (उन विविधताओं के लिए नीचे देखें जिन्हें केवल n/2 अतिरिक्त रिक्त स्थान की आवश्यकता होती है)।
प्राकृतिक मर्ज सॉर्ट
प्राकृतिक मर्ज सॉर्ट बॉटम-अप मर्ज सॉर्ट के समान होता है, सिवाय इसके कि इनपुट में अनुक्रम (सॉर्ट गए सॉर्टेड अनुक्रम) के किसी भी स्वाभाविक रूप से होने वाले रन का शोषण किया जाता है। दोनों मोनोटोनिक और बिटोनिक (वैकल्पिक ऊपर/नीचे) रन का शोषण किया जा सकता है, सूचियों (या समकक्ष टेप या फाइलों) के साथ सुविधाजनक डेटा संरचनाएं (कतार (सार डेटा प्रकार) या स्टैक (सार डेटा प्रकार) के रूप में उपयोग की जाती हैं)।[8] बॉटम-अप मर्ज सॉर्ट में, शुरुआती बिंदु मानता है कि प्रत्येक रन आइटम लंबा है। व्यवहार में, यादृच्छिक इनपुट डेटा में कई छोटे रन होंगे जो अभी सॉर्ट किए जाते हैं। विशिष्ट मामले में, प्राकृतिक मर्ज सॉर्ट को उतने पास की आवश्यकता नहीं हो सकती है क्योंकि मर्ज करने के लिए कम रन होते हैं। सबसे अच्छे मामले में, इनपुट पहले से ही सॉर्टेड होता है (अर्थात यह एक रन होता है), इसलिए प्राकृतिक मर्ज सॉर्ट को डेटा के माध्यम से केवल पास बनाने की आवश्यकता है। कई व्यावहारिक मामलों में, लंबे प्राकृतिक रन मौजूद होते हैं, और इस कारण से टिमसोर्ट के प्रमुख घटक के रूप में प्राकृतिक मर्ज सॉर्ट का उपयोग किया जाता है। उदाहरण:
Start : 3 4 2 1 7 5 8 9 0 6 Select runs : (3 4)(2)(1 7)(5 8 9)(0 6) Merge : (2 3 4)(1 5 7 8 9)(0 6) Merge : (1 2 3 4 5 7 8 9)(0 6) Merge : (0 1 2 3 4 5 6 7 8 9)
औपचारिक रूप से, प्राकृतिक मर्ज सॉर्ट को रन-इष्टतम कहा जाता है, जहाँ में रनों की संख्या , से एक कम होती है।
टूर्नामेंट सॉर्ट का उपयोग बाहरी सॉर्ट एल्गोरिदम के लिए प्रारंभिक रन इकट्ठा करने के लिए किया जाता है।
पिंग-पोंग मर्ज सॉर्ट
दो ब्लॉकों को एक साथ मर्ज करने की बजाय, पिंग-पोंग मर्ज चार ब्लॉकों को एक साथ मर्ज करता है। चार सॉर्ट किए गए ब्लॉकों को साथ सहायक स्थान में दो सॉर्ट किए गए ब्लॉकों में मिला दिया जाता है, फिर दो सॉर्ट किए गए ब्लॉकों को वापस मुख्य मेमोरी में मर्ज कर दिया जाता है। इस प्रक्रिया से कॉपी ऑपरेशन को छोड़ा जाता है और कुल मूव की संख्या को आधा कर दिया जाता है। 2014 में विकीसॉर्ट ने चार-एक-साथ मर्ज का एक पब्लिक डोमेन अंतर्गत अमल में लाया गया था, यह तकनीक बाद में धैर्य सॉर्टिंग के लिए अनुकूलन के रूप में वर्णित किया गया था और इसे पिंग-पोंग मर्ज का नाम दिया गया था।[9][10] क्वादसोर्ट ने 2020 में इस तकनीक को अमल में लाया और उसे क्वाड मर्ज के नाम से जाना जाता है।[11]
इन-प्लेस मर्ज सॉर्ट
मर्ज सॉर्ट का एक दोष, जब सरणियों पर लागू किया जाता है, तो इसकी O(n) कार्यशील मेमोरी आवश्यकता होती है। मेमोरी को कम करने या मर्ज सॉर्ट को पूरी तरह से इन-प्लेस एल्गोरिदम बनाने के लिए कई तरीके सुझाए गए हैं:
- क्रोनरोड (1969) ने मर्ज सॉर्ट का एक वैकल्पिक संस्करण सुझाया जो निरंतर अतिरिक्त स्थान का उपयोग करता है।
- कटजैनेन एट अल. एल्गोरिथ्म प्रस्तुत करें जिसके लिए निरंतर मात्रा में कार्यशील मेमोरी की आवश्यकता होती है: इनपुट ऐरे के तत्व को रखने के लिए पर्याप्त स्टोरेज स्पेस, और होल्ड करने के लिए अतिरिक्त स्थान O(1) इनपुट ऐरे में पॉइंटर्स। वे हासिल करते हैं। छोटे स्थिरांक के साथ समयबद्ध O(n log n) प्राप्त करते हैं, लेकिन उनका एल्गोरिथ्म स्थिर नहीं है।[12]
- इन-प्लेस मर्ज एल्गोरिथम तैयार करने के लिए कई प्रयास किए गए हैं जिन्हें इन-प्लेस मर्ज सॉर्ट तैयार करने के लिए मानक (टॉप-डाउन या बॉटम-अप) मर्ज सॉर्ट के साथ जोड़ा जा सकता है। इस मामले में, इन-प्लेस की धारणा को लॉगरिदमिक स्टैक स्पेस लेने के लिए आराम दिया जा सकता है, क्योंकि मानक मर्ज सॉर्ट को अपने स्वयं के स्टैक उपयोग के लिए उस स्थान की आवश्यकता होती है। यह गेफर्ट एट अल द्वारा दिखाया गया था। कि इन-प्लेस में स्थिर मर्ज संभव है O(n log n) स्क्रैच स्पेस की निरंतर मात्रा का उपयोग करते हुए समय, लेकिन उनका एल्गोरिथ्म जटिल है और इसमें उच्च स्थिर कारक हैं: लंबाई की सरणियों का मर्ज n और m ले जा सकते हैं 5n + 12m + o(m) चलता है।[13] इस उच्च स्थिर कारक और जटिल इन-प्लेस एल्गोरिदम को सरल और समझने में आसान बनाया गया था। बिंग-चाओ हुआंग और माइकल ए. लैंगस्टन[14] अतिरिक्त स्थान की निश्चित मात्रा का उपयोग करके सॉर्टेड सूची को मर्ज करने के लिए सीधा रैखिक समय एल्गोरिदम व्यावहारिक इन-प्लेस मर्ज प्रस्तुत किया। उन दोनों ने क्रोनरोड और अन्य के काम का इस्तेमाल किया है। यह रैखिक समय और निरंतर अतिरिक्त स्थान में विलीन हो जाता है। एल्गोरिथ्म मानक मर्ज सॉर्ट एल्गोरिदम की तुलना में थोड़ा अधिक औसत समय लेता है, O(n) अस्थायी अतिरिक्त मेमोरी कोशिकाओं का दोहन करने के लिए दो से कम कारक से मुक्त होता है। हालांकि एल्गोरिथ्म व्यावहारिक रूप से बहुत तेज है लेकिन यह कुछ सूचियों के लिए अस्थिर भी है। लेकिन इसी तरह की अवधारणाओं का उपयोग करके वे इस समस्या को हल करने में सक्षम हैं। अन्य इन-प्लेस एल्गोरिदम में सिममर्ज शामिल है, जो लेता है O((n + m) log (n + m)) कुल समय और स्थिर है।[15] इस तरह के एल्गोरिथ्म को मर्ज सॉर्ट में प्लग करने से इसकी जटिलता गैर-रैखिक रूप से बढ़ जाती है, लेकिन फिर भी चतुर्रेखीय समय, O(n (log n)2).
- बाहरी सॉर्टिंग के कई अनुप्रयोग मर्ज सॉर्ट के रूप का उपयोग करते हैं जहाँ इनपुट अधिक संख्या में उप-सूचियों तक विभाजित हो जाता है, आदर्श रूप से संख्या जिसके लिए उन्हें मर्ज करने से अभी भी वर्तमान में संसाधित पृष्ठ (कंप्यूटर मेमोरी) का सेट मुख्य मेमोरी में फिट हो जाता है।
- आधुनिक स्थिर रैखिक और इन-प्लेस मर्ज वैरिएंट ब्लॉक मर्ज सॉर्ट है जो स्वैप स्पेस के रूप में उपयोग करने के लिए अद्वितीय मानों का अनुभाग बनाता है।
- बाइनरी सेअर्चेस और रोटेशन्स का उपयोग करके अंतरिक्ष ओवरहेड को sqrt (n) तक कम किया जा सकता है।[16] यह विधि C ++ STL लाइब्रेरी और क्वाडोर्ट द्वारा नियोजित है।[11]
- एकाधिक सूचियों में नकल को कम करने का विकल्प सूचना के नए क्षेत्र को प्रत्येक कुंजी के साथ जोड़ना है (एम में तत्वों को कुंजियाँ कहा जाता है)। इस फ़ील्ड का उपयोग सॉर्ट की गई सूची में कुंजियों और किसी भी संबंधित जानकारी को साथ लिंक करने के लिए किया जाएगा ( कुंजी और उससे संबंधित जानकारी को रिकॉर्ड कहा जाता है)। फिर लिंक मानों को बदलकर सॉर्ट की गई सूचियों का मर्ज आगे बढ़ता है; किसी भी रिकॉर्ड को स्थानांतरित करने की आवश्यकता नहीं है। फ़ील्ड जिसमें केवल लिंक होता है, आम तौर पर पूरे रिकॉर्ड से छोटा होता है इसलिए कम जगह का भी उपयोग किया जाएगा। यह मानक सॉर्टिंग तकनीक है, जो मर्ज सॉर्ट तक सीमित नहीं है।
- स्पेस ओवरहेड को n/2 तक कम करने का सरल तरीका संयुक्त संरचना के रूप में बाएं और दाएं को बनाए रखना है, केवल m के बाएं हिस्से को अस्थायी स्थान में कॉपी करना है, और मर्ज किए गए आउटपुट को m में रखने के लिए मर्ज रूटीन को निर्देशित करना है। इस संस्करण के साथ मर्ज रूटीन के बाहर अस्थायी स्थान आवंटित करना बेहतर है, ताकि केवल आवंटन की आवश्यकता हो। पहले बताई गई अत्यधिक नकल को भी कम किया गया है, क्योंकि रिटर्न रिजल्ट स्टेटमेंट (उपरोक्त छद्म कोड में फ़ंक्शन मर्ज) से पहले लाइनों की अंतिम जोड़ी अतिश्योक्तिपूर्ण हो जाती है।
टेप ड्राइव के साथ प्रयोग करें
जब सॉर्ट करने के लिए डेटा मेमोरी में फिट कराना संभव नहीं होता है तो डिस्क या टेप ड्राइव का उपयोग करके एक्सटर्नल मर्ज सॉर्ट को चलाना संभव होता है। एक्सटर्नल सॉर्टिंग व्यक्त करती है कि मर्ज सॉर्ट को डिस्क ड्राइव के साथ कैसे लागू किया जाता है। एक प्रामाणिक टेप ड्राइव सॉर्ट चार टेप ड्राइव का उपयोग करती है। सभी I/O क्रमबद्ध होती है (पास के अंत में रिवाइंड को छोड़कर)। एक न्यूनतम कार्यान्वयन केवल दो रिकॉर्ड बफर्स और कुछ प्रोग्राम चरों के साथ हो सकता है।
चार टेप ड्राइव को A, B, C, D के रूप में नामित करके, मूल डेटा को A पर रखकर, केवल दो रिकॉर्ड बफर्स का उपयोग करते हुए, एल्गोरिदम बॉटम-अप कार्यान्वयन के समान होता है, मेमोरी में एरे के स्थान पर टेप ड्राइव के जोड़ों का उपयोग करते हुए। मूल एल्गोरिदम को निम्नप्रकार से वर्णित किया जा सकता है:
- A से रेकॉर्डों के जोड़ों को मर्ज करें; दो-रेकॉर्ड उपसूचियों को C और D में एकान्तरित रूप से लिखें।
- C और D से दो-रेकॉर्ड उपसूचियों को चार-रेकॉर्ड उपसूचियों में मर्ज करें; इन्हें एकान्तरित रूप से A और B में लिखें।
- A और B से चार-रेकॉर्ड उपसूचियों को आठ-रेकॉर्ड उपसूचियों में मर्ज करें; इन्हें एकान्तरित रूप से C और D में लिखें।
- इस प्रक्रिया को एक बार-दो-बार पुनरावृत्ति करें, जब तक आपके पास सभी डेटा को एक ही सूची में, log2(n) पास में सॉर्ट करने वाली डेटा हो जाए।
बहुत कम रन्स के साथ शुरू करने की बजाय, आमतौर पर हाइब्रिड एल्गोरिदम का उपयोग किया जाता है, जहां प्रारंभिक पास में बहुत सारे रेकॉर्ड्स को मेमोरी में पढ़ाया जाता है, उन्हें आंतरिक सॉर्ट किया जाता है ताकि एक लंबा रन बनाया जा सके, और फिर वे लंबे रन्स को आउटपुट सेट पर वितरित किए जाते हैं। यह स्टेप कई पहले के पास को बचाता है। उदाहरण के लिए, 1024 रेकॉर्ड का आंतरिक सॉर्ट नौ पास बचा देगा। आंतरिक सॉर्ट अक्सर बड़ा होता है क्योंकि इसमें इतना लाभ होता है। वास्तव में, ऐसी तकनीकें हैं जो प्रारंभिक रन्स को उपलब्ध आंतरिक मेमोरी से भी लंबा बना सकती हैं। उनमें से एक, क्नूथ का 'स्नोप्लो' (द्विआधारी ढेर, बाइनरी मिन-हीप पर आधारित), औसतन मेमोरी के इस्तेमाल के साइज़ के दोगुना लंबे रन्स उत्पन्न करता है।[17]
ऊपरी एल्गोरिदम में कुछ ओवरहेड के साथ, तीन टेप्स का उपयोग किया जा सकता है। O (n log n) चलने का समय दो कतारों, या एक स्टैक और एक कतार, या तीन स्टैक्स का उपयोग करके भी प्राप्त किया जा सकता है। दूसरी दिशा में, k > दो टेप्स (और O(k) आइटम मेमोरी में) का उपयोग करके, हम k/2-वे मर्ज का उपयोग करके O(log k) बार में टेप आपरेशन की संख्या को कम कर सकते हैं।
अधिक परिष्कृत मर्ज सॉर्ट जो टेप (और डिस्क) ड्राइव के उपयोग को अनुकूलित करता है, वह पॉलीफ़ेज़ मर्ज सॉर्ट है।
मर्ज सॉर्ट का अनुकूलन
आधुनिक कंप्यूटरों पर, संदर्भ की स्थानीयता सॉफ्टवेयर अनुकूलन में सर्वोपरि हो सकती है, क्योंकि बहुस्तरीय मेमोरी पदानुक्रम का उपयोग किया जाता है। मर्ज सॉर्ट एल्गोरिथम के कैशे (कंप्यूटिंग)-जागरूक संस्करण, जिनके संचालन को विशेष रूप से मशीन के मेमोरी कैश में और बाहर पृष्ठों के संचलन को कम करने के लिए चुना गया है, प्रस्तावित किया गया है। उदाहरण के लिए, दtiled merge sortएल्गोरिथम आकार S की उपसरणियों तक पहुँचने पर उप-सरणियों का विभाजन बंद कर देता है, जहाँ S CPU के कैश में फिट होने वाले डेटा आइटमों की संख्या है। इनमें से प्रत्येक उप-सरणियों को इन-प्लेस सॉर्टिंग एल्गोरिथम जैसे सम्मिलन सॉर्ट के साथ सॉर्टेड किया जाता है, मेमोरी स्वैप को हतोत्साहित करने के लिए, और सामान्य मर्ज सॉर्ट को मानक पुनरावर्ती फैशन में पूरा किया जाता है। इस एल्गोरिथ्म ने बेहतर प्रदर्शन का प्रदर्शन किया है[example needed] उन मशीनों पर जो कैश ऑप्टिमाइज़ेशन से लाभान्वित होती हैं। (LaMarca & Ladner 1997)
समानांतर मर्ज सॉर्ट
डिवाइड-एंड-कॉनकेयर एल्गोरिथम | डिवाइड-एंड-कॉनकेयर पद्धति के उपयोग के कारण मर्ज सॉर्ट अच्छी तरह से समानांतर हो जाता है। वर्षों में एल्गोरिथम के कई अलग-अलग समानांतर संस्करण विकसित किए गए हैं। कुछ समानांतर मर्ज सॉर्ट एल्गोरिदम अनुक्रमिक टॉप-डाउन मर्ज एल्गोरिदम से दृढ़ता से संबंधित हैं, जबकि अन्य के पास अलग सामान्य संरचना है और के-वे मर्ज एल्गोरिथम | के-वे मर्ज विधि का उपयोग करते हैं।
=== समानांतर पुनरावर्तन === के साथ मर्ज करें अनुक्रमिक मर्ज सॉर्ट प्रक्रिया को दो चरणों में विभाजित चरण और मर्ज चरण में वर्णित किया जा सकता है। पहले में कई पुनरावर्ती कॉल होते हैं जो बार-बार ही विभाजन प्रक्रिया को तब तक करते हैं जब तक कि अनुवर्ती सॉर्ट न हो जाए (जिसमें या कोई तत्व न हो)। सहज ज्ञान युक्त दृष्टिकोण उन पुनरावर्ती कॉलों का समानांतरकरण है।[18] निम्नलिखित स्यूडोकोड फोर्क-जॉइन मॉडल कीवर्ड का उपयोग करके समानांतर पुनरावर्तन के साथ मर्ज सॉर्ट का वर्णन करता है:
// Sort elements lo through hi (exclusive) of array A. algorithm mergesort(A, lo, hi) is if lo+1 < hi then // Two or more elements. mid := ⌊(lo + hi) / 2⌋ fork mergesort(A, lo, mid) mergesort(A, mid, hi) join merge(A, lo, mid, hi)
यह एल्गोरिथ्म अनुक्रमिक संस्करण का तुच्छ संशोधन है और अच्छी तरह से समानांतर नहीं होता है। इसलिए, इसका speedup बहुत प्रभावशाली नहीं है। इसमें समानांतर एल्गोरिदम का विश्लेषण # का अवलोकन है , जो केवल सुधार है अनुक्रमिक संस्करण की तुलना में (एल्गोरिदम का परिचय देखें)। यह मुख्य रूप से अनुक्रमिक मर्ज विधि के कारण है, क्योंकि यह समांतर निष्पादन की बाधा है।
=== समानांतर मर्जिंग === के साथ मर्ज सॉर्ट करें
समांतर मर्ज एल्गोरिदम का उपयोग करके बेहतर समांतरता प्राप्त की जा सकती है। एल्गोरिद्म का परिचय | कॉर्मेन एट अल। बाइनरी वेरिएंट प्रस्तुत करें जो दो सॉर्ट किए गए उप-अनुक्रमों को सॉर्ट किए गए आउटपुट अनुक्रम में मिला देता है।[18]
अनुक्रमों में से में (असमान लंबाई होने पर लंबा), मध्य सूचकांक का तत्व चुना जाता है। अन्य अनुक्रम में इसकी स्थिति इस तरह से निर्धारित की जाती है कि यदि यह तत्व इस स्थिति में डाला जाता है तो यह क्रम सॉर्टेड रहेगा। इस प्रकार, कोई जानता है कि दोनों अनुक्रमों से कितने अन्य तत्व छोटे हैं और आउटपुट अनुक्रम में चयनित तत्व की स्थिति की गणना की जा सकती है। इस तरह से बनाए गए छोटे और बड़े तत्वों के आंशिक अनुक्रमों के लिए, मर्ज एल्गोरिथम को फिर से समानांतर में तब तक निष्पादित किया जाता है जब तक कि पुनरावर्तन का आधार मामला नहीं हो जाता।
निम्नलिखित स्यूडोकोड समानांतर मर्ज एल्गोरिथम (कॉर्मेन एट अल से अपनाया गया) का उपयोग करके संशोधित समानांतर मर्ज सॉर्ट विधि दिखाता है।
/** * A: Input array * B: Output array * lo: lower bound * hi: upper bound * off: offset */ algorithm parallelMergesort(A, lo, hi, B, off) is len := hi - lo + 1 if len == 1 then B[off] := A[lo] else let T[1..len] be a new array mid := ⌊(lo + hi) / 2⌋ mid' := mid - lo + 1 fork parallelMergesort(A, lo, mid, T, 1) parallelMergesort(A, mid + 1, hi, T, mid' + 1) join parallelMerge(T, 1, mid', mid' + 1, len, B, off)
सबसे खराब केस स्पैन के लिए पुनरावृत्ति संबंध का विश्लेषण करने के लिए, पैरेलल मेर्जेसॉर्ट के रिकर्सिव कॉल को उनके समानांतर निष्पादन के कारण केवल बार शामिल किया जाना चाहिए, प्राप्त करना
इस पुनरावृत्ति का हल इसके द्वारा दिया गया है
समानांतर मल्टीवे मर्ज सॉर्ट
यह मर्ज सॉर्ट एल्गोरिदम को बाइनरी मर्ज विधि तक सीमित करने के लिए मनमाना लगता है, क्योंकि आमतौर पर p > 2 प्रोसेसर उपलब्ध होते हैं। के-वे मर्ज एल्गोरिथम का उपयोग करने के लिए बेहतर तरीका हो सकता है | के-वे मर्ज विधि, बाइनरी मर्ज का सामान्यीकरण, जिसमें सॉर्टेड अनुक्रमों को मिला दिया जाता है। यह मर्ज वेरिएंट समानांतर रैंडम-एक्सेस मशीन पर सॉर्टिंग एल्गोरिदम का वर्णन करने के लिए उपयुक्त है।[20][21]
मूल विचार
के अवर्गीकृत अनुक्रम को देखते हुए तत्वों, लक्ष्य अनुक्रम को सॉर्टेड करना है उपलब्ध प्रोसेसर (कंप्यूटिंग)। इन तत्वों को सभी प्रोसेसरों के बीच समान रूप से वितरित किया जाता है और अनुक्रमिक सॉर्टिंग एल्गोरिदम का उपयोग करके स्थानीय रूप से सॉर्ट किया जाता है। इसलिए, अनुक्रम में सॉर्टेड अनुक्रम होते हैं लंबाई का . सरलीकरण के लिए का गुणक हो , ताकि के लिए .
इन अनुक्रमों का उपयोग बहु-अनुक्रम चयन/स्प्लिटर चयन करने के लिए किया जाएगा। के लिए , एल्गोरिदम स्प्लिटर तत्वों को निर्धारित करता है वैश्विक रैंक के साथ . फिर की इसी स्थिति प्रत्येक क्रम में बाइनरी सर्च एल्गोरिथम के साथ निर्धारित किया जाता है और इस प्रकार आगे विभाजित हैं अनुवर्ती साथ .
इसके अलावा, के तत्व प्रोसेसर को सौंपा गया है , का अर्थ रैंक के बीच के सभी तत्व हैं और रैंक , जो सभी में वितरित हैं . इस प्रकार, प्रत्येक प्रोसेसर को सॉर्टेड अनुक्रमों का क्रम प्राप्त होता है। तथ्य यह है कि रैंक विभाजक तत्वों की विश्व स्तर पर चुना गया था, दो महत्वपूर्ण गुण प्रदान करता है: ओर, चुना गया था ताकि प्रत्येक प्रोसेसर अभी भी काम कर सके असाइनमेंट के बाद तत्व एल्गोरिथ्म पूरी तरह से लोड संतुलन (कंप्यूटिंग) | लोड-संतुलित है। दूसरी ओर, प्रोसेसर पर सभी तत्व प्रोसेसर पर सभी तत्वों से कम या बराबर हैं . इसलिए, प्रत्येक प्रोसेसर के-वे मर्ज एल्गोरिथम | पी-वे मर्ज को स्थानीय रूप से निष्पादित करता है और इस प्रकार इसके उप-अनुक्रमों से सॉर्टेड अनुक्रम प्राप्त करता है। दूसरी संपत्ति के कारण, कोई और पी-वे-मर्ज नहीं करना पड़ता है, परिणाम केवल प्रोसेसर संख्या के क्रम में साथ रखे जाते हैं।
बहु-अनुक्रम चयन
अपने सरलतम रूप में, दिया गया सॉर्टेड अनुक्रम पर समान रूप से वितरित प्रोसेसर और रैंक , कार्य तत्व खोजना है वैश्विक रैंक के साथ अनुक्रमों के मिलन में। इसलिए, इसका उपयोग प्रत्येक को विभाजित करने के लिए किया जा सकता है स्प्लिटर इंडेक्स पर दो भागों में , जहां निचले हिस्से में केवल ऐसे तत्व होते हैं जो इससे छोटे होते हैं , जबकि तत्वों से बड़ा ऊपरी भाग में स्थित हैं।
प्रस्तुत अनुक्रमिक एल्गोरिदम प्रत्येक अनुक्रम में विभाजन के सूचकांक लौटाता है, उदा। सूचकांक क्रम में ऐसा है कि से कम वैश्विक रैंक है और .[22] एल्गोरिद्म msSelect(S : सॉर्टेड अनुक्रमों की सरणी [S_1,..,S_p], k : int) है
algorithm msSelect(S : Array of sorted Sequences [S_1,..,S_p], k : int) is for i = 1 to p do (l_i, r_i) = (0, |S_i|-1) while there exists i: l_i < r_i do // pick Pivot Element in S_j[l_j], .., S_j[r_j], chose random j uniformly v := pickPivot(S, l, r) for i = 1 to p do m_i = binarySearch(v, S_i[l_i, r_i]) // sequentially if m_1 + ... + m_p >= k then // m_1+ ... + m_p is the global rank of v r := m // vector assignment else l := m return l
जटिलता विश्लेषण के लिए समानांतर रैंडम-एक्सेस मशीन मॉडल चुना जाता है। यदि डेटा समान रूप से सभी पर वितरित किया जाता है , बाइनरीसर्च पद्धति के पी-फोल्ड निष्पादन का चलने का समय है . अपेक्षित पुनरावर्तन गहराई है जैसा कि सामान्य तुरंत चयन में होता है। इस प्रकार समग्र अपेक्षित चलने का समय है .
समानांतर मल्टीवे मर्ज सॉर्ट पर लागू, इस एल्गोरिथम को समानांतर में लागू किया जाना है जैसे कि रैंक के सभी विभाजक तत्व के लिए साथ-साथ पाये जाते हैं। इन फाड़नेवाला तत्वों का उपयोग तब प्रत्येक अनुक्रम को विभाजित करने के लिए किया जा सकता है भागों, के समान कुल चलने के समय के साथ .
स्यूडोकोड
नीचे, समानांतर मल्टीवे मर्ज सॉर्ट एल्गोरिथम का पूरा स्यूडोकोड दिया गया है। हम मानते हैं कि बहु-अनुक्रम चयन से पहले और बाद में बाधा तुल्यकालन है जैसे कि प्रत्येक प्रोसेसर विभाजन तत्वों और अनुक्रम विभाजन को ठीक से निर्धारित कर सकता है।
/** * d: Unsorted Array of Elements * n: Number of Elements * p: Number of Processors * return Sorted Array */ algorithm parallelMultiwayMergesort(d : Array, n : int, p : int) is o := new Array[0, n] // the output array for i = 1 to p do in parallel // each processor in parallel S_i := d[(i-1) * n/p, i * n/p] // Sequence of length n/p sort(S_i) // sort locally synch v_i := msSelect([S_1,...,S_p], i * n/p) // element with global rank i * n/p synch (S_i,1, ..., S_i,p) := sequence_partitioning(si, v_1, ..., v_p) // split s_i into subsequences o[(i-1) * n/p, i * n/p] := kWayMerge(s_1,i, ..., s_p,i) // merge and assign to output array return o
विश्लेषण
सबसे पहले, प्रत्येक प्रोसेसर असाइन किए गए सॉर्ट करता है जटिलता के साथ सॉर्ट एल्गोरिथ्म का स्थानीय रूप से उपयोग करने वाले तत्व . उसके बाद, फाड़नेवाला तत्वों की समय पर गणना की जानी चाहिए . अंत में, के प्रत्येक समूह विभाजन को प्रत्येक प्रोसेसर द्वारा चलने वाले समय के साथ समानांतर में मर्ज करना पड़ता है अनुक्रमिक मर्ज एल्गोरिथम का उपयोग करना | पी-वे मर्ज एल्गोरिथम। इस प्रकार, समग्र चलने का समय इसके द्वारा दिया जाता है
.
व्यावहारिक अनुकूलन और अनुप्रयोग
मल्टीवे मर्ज सॉर्ट एल्गोरिथम अपनी उच्च समांतरता क्षमता के माध्यम से बहुत स्केलेबल है, जो कई प्रोसेसरों के उपयोग की अनुमति देता है। यह एल्गोरिथम को बड़ी मात्रा में डेटा सॉर्ट करने के लिए व्यवहार्य उम्मीदवार बनाता है, जैसे कि कंप्यूटर क्लस्टर में संसाधित। इसके अलावा, चूंकि ऐसी प्रणालियों में मेमोरी आमतौर पर सीमित संसाधन नहीं होती है, मर्ज सॉर्ट की अंतरिक्ष जटिलता का नुकसान नगण्य है। हालांकि, ऐसी प्रणालियों में अन्य कारक महत्वपूर्ण हो जाते हैं, जिन्हें समानांतर रैंडम-एक्सेस मशीन पर मॉडलिंग करते समय ध्यान में नहीं रखा जाता है। यहां, निम्नलिखित पहलुओं पर विचार करने की आवश्यकता है: मेमोरी पदानुक्रम, जब डेटा प्रोसेसर कैश में फिट नहीं होता है, या प्रोसेसर के बीच डेटा के आदान-प्रदान का संचार ओवरहेड होता है, जो अड़चन बन सकता है जब डेटा को साझा किए गए माध्यम से एक्सेस नहीं किया जा सकता है। याद।
पीटर सैंडर्स (कंप्यूटर वैज्ञानिक) एट अल। अपने पेपर में मल्टीलेवल मल्टीवे मर्जसॉर्ट के लिए थोक तुल्यकालिक समानांतर एल्गोरिथम प्रस्तुत किया है, जो विभाजित करता है प्रोसेसर में आकार के समूह . सभी प्रोसेसर पहले स्थानीय रूप से सॉर्ट करते हैं। सिंगल लेवल मल्टीवे मर्जसॉर्ट के विपरीत, इन अनुक्रमों को तब विभाजित किया जाता है भागों और उपयुक्त प्रोसेसर समूहों को सौंपा गया। इन चरणों को उन समूहों में पुनरावर्ती रूप से दोहराया जाता है। यह संचार को कम करता है और विशेष रूप से कई छोटे संदेशों के साथ होने वाली समस्याओं से बचाता है। अंतर्निहित वास्तविक नेटवर्क की पदानुक्रमित संरचना का उपयोग प्रोसेसर समूहों (जैसे 19 इंच का रैक, कंप्यूटर क्लस्टर, ...) को परिभाषित करने के लिए किया जा सकता है।[21]
आगे के संस्करण
मर्ज सॉर्ट पहले सॉर्टिंग एल्गोरिदम में से था जहां ओ (1) मर्ज सुनिश्चित करने के लिए रिचर्ड कोल ने चतुर सबसैंपलिंग एल्गोरिदम का उपयोग करके इष्टतम गति प्राप्त की थी।[23] अन्य परिष्कृत समानांतर सॉर्ट एल्गोरिदम कम स्थिरांक के साथ समान या बेहतर समय सीमा प्राप्त कर सकते हैं। उदाहरण के लिए, 1991 में डेविड पॉवर्स ने समानांतर क्विकसॉर्ट (और संबंधित आपको कामयाबी मिले) का वर्णन किया था जो ओ (लॉग एन) समय में सीआरसीडब्ल्यू समानांतर रैंडम-एक्सेस मशीन (पीआरएएम) पर एन प्रोसेसर के साथ विभाजन को स्पष्ट रूप से निष्पादित करके संचालित कर सकता है।[24] पॉवर्स आगे दिखाता है कि O((log n) पर बैचर के बिटोनिक सॉर्टर का पाइपलाइन संस्करण2) तितली सॉर्ट नेटवर्क पर समय वास्तव में PRAM पर उसके O(log n) प्रकार की तुलना में तेज़ है, और वह तुलना, मूलांक और समानांतर सॉर्ट में छिपे हुए ओवरहेड्स की विस्तृत चर्चा प्रदान करता है।[25]
अन्य प्रकार के एल्गोरिदम के साथ तुलना
हालाँकि ढेर बनाएं और छांटें में मर्ज सॉर्ट के समान समय सीमा होती है, इसके लिए मर्ज सॉर्ट के Θ(n) के बजाय केवल Θ(1) सहायक स्थान की आवश्यकता होती है। विशिष्ट आधुनिक आर्किटेक्चर पर, कुशल क्विकॉर्ट कार्यान्वयन आम तौर पर रैम-आधारित सरणियों को सॉर्ट करने के लिए मर्ज सॉर्ट से बेहतर प्रदर्शन करते हैं।[citation needed] दूसरी ओर, मर्ज सॉर्ट स्थिर प्रकार है और धीमी-से-पहुंच अनुक्रमिक मीडिया को संभालने में अधिक कुशल है। किसी लिंक की गई सूची को सॉर्ट करने के लिए मर्ज सॉर्ट अक्सर सबसे अच्छा विकल्प होता है: इस स्थिति में मर्ज सॉर्ट को इस तरह लागू करना अपेक्षाकृत आसान होता है कि इसके लिए केवल Θ(1) अतिरिक्त स्थान की आवश्यकता होती है, और लिंक की धीमी रैंडम-एक्सेस प्रदर्शन सूची कुछ अन्य एल्गोरिदम (जैसे कि क्विकसॉर्ट) खराब प्रदर्शन करती है, और अन्य (जैसे हीप्सोर्ट) पूरी तरह से असंभव है।
पर्ल 5.8 के अनुसार, मर्ज सॉर्ट इसका डिफ़ॉल्ट सॉर्टिंग एल्गोरिथम है (यह पर्ल के पिछले संस्करणों में क्विकॉर्ट था)।[26] जावा मंच में, Arrays.sort() तरीके इस्तेमाल करते हैं मर्ज सॉर्ट या ट्यून्ड क्विकॉर्ट डेटाटाइप के आधार पर और कार्यान्वयन दक्षता के लिए इंसर्शन सॉर्ट पर स्विच करें जब सात से कम सरणी तत्वों को सॉर्ट किया जा रहा हो।[27] लिनक्स कर्नेल अपनी लिंक्ड सूचियों के लिए मर्ज सॉर्ट का उपयोग करता है।[28] पायथन (प्रोग्रामिंग लैंग्वेज) टिम्सोर्ट का उपयोग करता है, मर्ज सॉर्ट और इंसर्शन सॉर्ट का और ट्यूनेड हाइब्रिड, जो जावा 7 में मानक सॉर्ट एल्गोरिथ्म बन गया है (गैर-आदिम प्रकार के सरणियों के लिए),[29] Android (ऑपरेटिंग सिस्टम) पर,[30] और जीएनयू ऑक्टेव में।[31]
टिप्पणियाँ
- ↑ Skiena (2008, p. 122)
- ↑ Knuth (1998, p. 158)
- ↑ Katajainen, Jyrki; Träff, Jesper Larsson (March 1997). "Algorithms and Complexity". Proceedings of the 3rd Italian Conference on Algorithms and Complexity. Italian Conference on Algorithms and Complexity. Lecture Notes in Computer Science. Vol. 1203. Rome. pp. 217–228. CiteSeerX 10.1.1.86.3154. doi:10.1007/3-540-62592-5_74. ISBN 978-3-540-62592-6.
- ↑ Cormen et al. (2009, p. 36)
- ↑ The worst case number given here does not agree with that given in Knuth's Art of Computer Programming, Vol 3. The discrepancy is due to Knuth analyzing a variant implementation of merge sort that is slightly sub-optimal
- ↑ 6.0 6.1 Jayalakshmi, N. (2007). Data structure using C++. ISBN 978-81-318-0020-1. OCLC 849900742.
- ↑ Cormen et al. (2009, p. 151)
- ↑ Powers, David M. W.; McMahon, Graham B. (1983). "A compendium of interesting prolog programs". DCS Technical Report 8313 (Report). Department of Computer Science, University of New South Wales.
- ↑ "WikiSort. Fast and stable sort algorithm that uses O(1) memory. Public domain". 14 Apr 2014.
- ↑ Chandramouli, Badrish; Goldstein, Jonathan (2014). Patience is a Virtue: Revisiting Merge and Sort on Modern Processors (PDF). SIGMOD/PODS.
- ↑ 11.0 11.1 "Quadsort is a branchless stable adaptive merge sort". 8 Jun 2022.
- ↑ Katajainen, Pasanen & Teuhola (1996)
- ↑ Geffert, Viliam; Katajainen, Jyrki; Pasanen, Tomi (2000). "Asymptotically efficient in-place merging". Theoretical Computer Science. 237 (1–2): 159–181. doi:10.1016/S0304-3975(98)00162-5.
- ↑ Huang, Bing-Chao; Langston, Michael A. (March 1988). "Practical In-Place Merging". Communications of the ACM. 31 (3): 348–352. doi:10.1145/42392.42403. S2CID 4841909.
- ↑ Kim, Pok-Son; Kutzner, Arne (2004). "Stable Minimum Storage Merging by Symmetric Comparisons". Algorithms – ESA 2004. European Symp. Algorithms. Lecture Notes in Computer Science. Vol. 3221. pp. 714–723. CiteSeerX 10.1.1.102.4612. doi:10.1007/978-3-540-30140-0_63. ISBN 978-3-540-23025-0.
- ↑ "A New Method for Efficient in-Place Merging". 1 Sep 2003.
- ↑ Ferragina, Paolo (2009–2019), "5. Sorting Atomic Items" (PDF), The magic of Algorithms!, p. 5-4, archived (PDF) from the original on 2021-05-12
- ↑ 18.0 18.1 Cormen et al. (2009, pp. 797–805)
- ↑ Victor J. Duvanenko "Parallel Merge Sort" Dr. Dobb's Journal & blog [1] and GitHub repo C++ implementation [2]
- ↑ Peter Sanders; Johannes Singler (2008). "Lecture Parallel algorithms" (PDF). Retrieved 2020-05-02.
- ↑ 21.0 21.1 Axtmann, Michael; Bingmann, Timo; Sanders, Peter; Schulz, Christian (2015). "Practical Massively Parallel Sorting". Proceedings of the 27th ACM Symposium on Parallelism in Algorithms and Architectures: 13–23. doi:10.1145/2755573.2755595. ISBN 9781450335881. S2CID 18249978.
- ↑ Peter Sanders (2019). "Lecture Parallel algorithms" (PDF). Retrieved 2020-05-02.
- ↑ Cole, Richard (August 1988). "Parallel merge sort". SIAM J. Comput. 17 (4): 770–785. CiteSeerX 10.1.1.464.7118. doi:10.1137/0217049. S2CID 2416667.
- ↑ Powers, David M. W. (1991). "Parallelized Quicksort and Radixsort with Optimal Speedup". Proceedings of International Conference on Parallel Computing Technologies, Novosibirsk. Archived from the original on 2007-05-25.
- ↑ Powers, David M. W. (January 1995). Parallel Unification: Practical Complexity (PDF). Australasian Computer Architecture Workshop Flinders University.
- ↑ "Sort – Perl 5 version 8.8 documentation". Retrieved 2020-08-23.
- ↑ coleenp (22 Feb 2019). "src/java.base/share/classes/java/util/Arrays.java @ 53904:9c3fe09f69bc". OpenJDK.
- ↑ linux kernel /lib/list_sort.c
- ↑ jjb (29 Jul 2009). "Commit 6804124: Replace "modified mergesort" in java.util.Arrays.sort with timsort". Java Development Kit 7 Hg repo. Archived from the original on 2018-01-26. Retrieved 24 Feb 2011.
- ↑ "Class: java.util.TimSort<T>". Android JDK Documentation. Archived from the original on January 20, 2015. Retrieved 19 Jan 2015.
- ↑ "liboctave/util/oct-sort.cc". Mercurial repository of Octave source code. Lines 23-25 of the initial comment block. Retrieved 18 Feb 2013.
Code stolen in large part from Python's, listobject.c, which itself had no license header. However, thanks to Tim Peters for the parts of the code I ripped-off.
संदर्भ
- Cormen, Thomas H.; Leiserson, Charles E.; Rivest, Ronald L.; Stein, Clifford (2009) [1990]. Introduction to Algorithms (3rd ed.). MIT Press and McGraw-Hill. ISBN 0-262-03384-4.
- Katajainen, Jyrki; Pasanen, Tomi; Teuhola, Jukka (1996). "Practical in-place mergesort". Nordic Journal of Computing. 3 (1): 27–40. CiteSeerX 10.1.1.22.8523. ISSN 1236-6064. Archived from the original on 2011-08-07. Retrieved 2009-04-04.. Also Practical In-Place Mergesort. Also [3]
- Knuth, Donald (1998). "Section 5.2.4: Sorting by Merging". Sorting and Searching. The Art of Computer Programming. Vol. 3 (2nd ed.). Addison-Wesley. pp. 158–168. ISBN 0-201-89685-0.
- Kronrod, M. A. (1969). "Optimal ordering algorithm without operational field". Soviet Mathematics - Doklady. 10: 744.
- LaMarca, A.; Ladner, R. E. (1997). "The influence of caches on the performance of sorting". Proc. 8th Ann. ACM-SIAM Symp. On Discrete Algorithms (SODA97): 370–379. CiteSeerX 10.1.1.31.1153.
- Skiena, Steven S. (2008). "4.5: Mergesort: Sorting by Divide-and-Conquer". The Algorithm Design Manual (2nd ed.). Springer. pp. 120–125. ISBN 978-1-84800-069-8.
- Sun Microsystems. "Arrays API (Java SE 6)". Retrieved 2007-11-19.
- Oracle Corp. "Arrays (Java SE 10 & JDK 10)". Retrieved 2018-07-23.
बाहरी संबंध
- Animated Sorting Algorithms: Merge Sort at the Wayback Machine (archived 6 March 2015) – graphical demonstration
- Open Data Structures - Section 11.1.1 - Merge Sort, Pat Morin