क्विकसॉर्ट एल्गोरिथ्म Javaउदाहरण सहित स्क्रिप्ट
⚡ स्मार्ट सारांश
क्विकसॉर्ट एल्गोरिथ्म Javaयह स्क्रिप्ट एक पिवट का चयन करके, छोटे मानों को बाईं ओर और बड़े मानों को दाईं ओर विभाजित करके, फिर रिकर्सन द्वारा ऐरे को उसी स्थान पर सॉर्ट करती है। इसका औसत समय O(n log n) है और यह बड़े संख्यात्मक डेटासेट पर अंतर्निर्मित sort() फ़ंक्शन से बेहतर प्रदर्शन करती है।
त्वरित सॉर्ट क्या है?
जल्दी से सुलझाएं यह एक तुलनात्मक छँटाई एल्गोरिदम है जो निम्न का अनुसरण करता है: विभाजन और जीत यह विधि एक तत्व को धुरी के रूप में चुनती है, सरणी को दो भागों में विभाजित करती है: एक भाग जिसमें धुरी से छोटे मान होते हैं और दूसरा भाग जिसमें धुरी से बड़े मान होते हैं, और फिर पूरी सरणी के क्रमबद्ध होने तक प्रत्येक भाग पर समान प्रक्रिया लागू करती है।
क्विक सॉर्ट हर प्रोग्रामिंग भाषा में सबसे व्यापक रूप से उपयोग किए जाने वाले सॉर्टिंग एल्गोरिदम में से एक है। यदि आप लिखते हैं Javaलिपिआपने शायद पहले से ही अंतर्निहित सुविधाओं का उपयोग कर लिया होगा। क्रमबद्ध करें () इस विधि को समझने के बाद, आप सोच सकते हैं कि क्विक सॉर्ट के लिए अलग से कार्यान्वयन सीखना क्यों ज़रूरी है। इसका उत्तर जानने के लिए, आपको पहले यह समझना होगा कि सॉर्टिंग का अर्थ क्या है और डिफ़ॉल्ट सॉर्टिंग क्या होती है। Javaस्क्रिप्ट वास्तव में ऐसा करती है।
क्विक सॉर्ट को तीन गुण परिभाषित करते हैं:
- जगह में: यह मूल को पुनर्व्यवस्थित करता है सरणी और समान आकार का दूसरा ऐरे आवंटित नहीं करता है।
- पुनरावर्ती: प्रत्येक विभाजन दो छोटी श्रेणियां उत्पन्न करता है जो समान फ़ंक्शन द्वारा क्रमबद्ध होती हैं।
- अस्थिर: समान कुंजी वाले दो तत्व अपने प्रारंभिक सापेक्ष क्रम से भिन्न क्रम में समाप्त हो सकते हैं।
सॉर्टिंग क्या है?
छँटाई का अर्थ है तत्वों को एक निश्चित क्रम में व्यवस्थित करना। आपने इसे स्कूल में अवश्य ही पढ़ा होगा: संख्याओं को सबसे छोटी से सबसे बड़ी के क्रम में व्यवस्थित करना। आरोही क्रम में लगाना, और उन्हें सबसे बड़े से सबसे छोटे क्रम में रखना है अवरोही क्रमबद्धता। छँटाई केवल संख्याओं तक सीमित नहीं है। स्ट्रिंग को वर्णानुक्रम में, तिथियों को कालक्रम में और वस्तुओं को आपके द्वारा चुने गए किसी भी फ़ील्ड के आधार पर क्रमबद्ध किया जा सकता है, जैसे कि मूल्य या स्कोर।
सॉर्टिंग महत्वपूर्ण है क्योंकि क्रमबद्ध डेटा से ऑपरेशन तेज़ी से होते हैं। बाइनरी सर्च O(log n) समय में चलती है, लेकिन केवल सॉर्ट किए गए इनपुट पर। डेटा के क्रम में होने पर डुप्लिकेशन हटाना, रेंज क्वेरी, रैंकिंग और मर्ज ऑपरेशन बहुत सस्ते हो जाते हैं, यही कारण है कि हर भाषा में कम से कम एक सॉर्टिंग रूटीन शामिल होता है।
डिफ़ॉल्ट सॉर्टिंग में Javaलिपि
जैसा कि पहले उल्लेख किया गया है, Javaस्क्रिप्ट प्रदान करती है क्रमबद्ध करें ()एक छोटा ऐरे लें, जैसे [5,3,7,6,2,9], जिसे आप आरोही क्रम में रखना चाहते हैं। क्रमबद्ध करें () ऐरे पर ठीक यही काम होता प्रतीत होता है।
ऊपर दिए गए स्क्रीनशॉट में ब्राउज़र कंसोल द्वारा सॉर्ट किए गए ऐरे को प्रिंट करते हुए दिखाया गया है। यहाँ वही कोड दिया गया है:
var items = [5, 3, 7, 6, 2, 9]; console.log(items.sort());
आउटपुट:
[ 2, 3, 5, 6, 7, 9 ]
वह परिणाम सही है, लेकिन महज़ संयोगवश। Array.prototype.sort() प्रत्येक तत्व को स्ट्रिंग में परिवर्तित करता है और स्ट्रिंग की तुलना करता है। जब तक आप कोई तुलनात्मक फ़ंक्शन प्रदान नहीं करते, तब तक यह स्थिति बनी रहेगी। इस ऐरे में प्रत्येक मान एक अंक का है, इसलिए स्ट्रिंग का क्रम अंकों के क्रम से मेल खाता है। डेटा बदलने पर यह भ्रम टूट जाता है।
var prices = [10, 9, 1, 100, 25]; console.log(prices.sort()); // string comparison console.log(prices.sort(function (a, b) { return a - b; })); // numeric comparison
आउटपुट:
[ 1, 10, 100, 25, 9 ] [ 1, 9, 10, 25, 100 ]
⚠️ चेतावनी: कभी कॉल न करें sort() बिना तुलनाकर्ता वाली संख्याओं पर। "100" को "25" से पहले सॉर्ट किया जाता है क्योंकि अक्षर "1" अक्षर "2" से पहले आता है। हमेशा लिखें sort((a, b) => a - b) संख्यात्मक डेटा के लिए।
sort() फ़ंक्शन किस एल्गोरिदम का उपयोग करता है?
विनिर्देश में किसी एल्गोरिदम का नाम नहीं दिया गया है, इसलिए प्रत्येक इंजन अपना एल्गोरिदम स्वयं चुनता है। आधुनिक इंजन सभी मर्ज-आधारित एल्गोरिदम का उपयोग करते हैं:
- V8 (क्रोम, एज, नोड.जेएस) ने उपयोग किया है टिमसॉर्ट V8 7.0 के बाद से, Chrome 70 में शामिल किया गया।
- मकड़ीनुमा बन्दर (Firefox) का उपयोग करता है मर्ज सॉर्ट.
- Javaस्क्रिप्टकोर (सफारी) भी उपयोग करता है मर्ज सॉर्ट.
ES2019 के बाद से भाषा यह गारंटी देती है कि sort() is स्थिरजो इंजन के अंदर एक साधारण क्विक सॉर्ट को खारिज करता है। मर्ज-आधारित सॉर्टिंग के लिए O(n) सहायक मेमोरी की आवश्यकता होती है, और इसे आपके फ़ंक्शन को कॉल करना होगा। Javaप्रत्येक तुलना के लिए स्क्रिप्ट तुलनाकर्ता। एक हस्तलिखित संख्यात्मक क्विक सॉर्ट संख्याओं की सीधे तुलना करता है और उन्हें उसी स्थान पर सॉर्ट करता है, इसलिए यह बड़े संख्यात्मक सरणियों पर बेहतर प्रदर्शन कर सकता है। Node.js 22 पर 1,000,000 यादृच्छिक पूर्णांकों को सॉर्ट करने में लगभग इतना समय लगा। 100 एमएस नीचे दिए गए क्विक सॉर्ट के साथ और लगभग 210 एमएस साथ में sort((a, b) => a - b).
इसलिए, जब आपको इन-प्लेस सॉर्टिंग, मेमोरी पर कड़ा नियंत्रण, या सॉर्टिंग की कार्यप्रणाली की ठोस समझ की आवश्यकता हो, तो क्विक सॉर्ट लिखना उपयोगी है। आइए इसकी कार्यप्रणाली को विस्तार से समझते हैं।
क्विक सॉर्ट कैसे काम करता है?
क्विक सॉर्ट एक कोर ऑपरेशन को दोहराता है, जिसे कहा जाता है विभाजनछोटे से छोटे दायरे में। यहाँ चरण क्रमानुसार दिए गए हैं:
- खोज धुरी सरणी में तत्व.
- बाएं पॉइंटर को रेंज के पहले एलिमेंट से शुरू करें।
- दाएँ पॉइंटर को रेंज के अंतिम तत्व से शुरू करें।
- बाएँ पॉइंटर पर स्थित तत्व की तुलना पिवट से करें। यदि यह पिवट से छोटा है, तो बाएँ पॉइंटर को एक कदम दाईं ओर ले जाएँ। तब तक जारी रखें जब तक बाएँ तत्व का मान पिवट से बड़ा या उसके बराबर न हो जाए।
- दाएँ पॉइंटर पर स्थित तत्व की तुलना पिवट से करें। यदि यह पिवट से बड़ा है, तो दाएँ पॉइंटर को एक कदम बाईं ओर ले जाएँ। तब तक जारी रखें जब तक दाएँ तत्व का मान पिवट से कम या उसके बराबर न हो जाए।
- यदि बायां पॉइंटर अभी भी दाएं पॉइंटर से छोटा या उसके बराबर है, तो दोनों तत्वों को आपस में बदल दें।
- बाएँ पॉइंटर को बढ़ाएँ और दाएँ पॉइंटर को घटाएँ।
- यदि बायां इंडेक्स अभी भी दाएं इंडेक्स से कम या उसके बराबर है, तो चरण 4 से दोहराएं। अन्यथा, बाएं पॉइंटर का इंडेक्स लौटाएं।
ऊपर दिया गया आरेख tracयह नमूना ऐरे पर पॉइंटर की गतिविधियों को दर्शाता है। पिवट से छोटा प्रत्येक तत्व उसके बाईं ओर और उससे बड़ा प्रत्येक तत्व उसके दाईं ओर आ जाता है, जो कि लौटाया गया इंडेक्स ही दर्शाता है। नीचे दिया गया भाग इसी ऐरे को चरण दर चरण समझाता है।
धुरी तत्व का निर्धारण कैसे करें
पिवट का चुनाव ही वह एकमात्र निर्णय है जो क्विक सॉर्ट को तेज़ और धीमे के बीच अंतर करता है। यदि आप हमेशा पिवट का चुनाव करते हैं, तो प्रथम यदि किसी तत्व को पहले से ही क्रमबद्ध सरणी में रखा जाए, तो सबसे खराब विभाजन होता है: एक तरफ खाली और दूसरी तरफ शेष सभी तत्व मौजूद होते हैं। इससे एल्गोरिदम O(n²) में परिवर्तित हो जाता है। मध्यम element (एरे की लंबाई को दो से विभाजित करने पर प्राप्त मान) सॉर्ट किए गए और उल्टे क्रम में सॉर्ट किए गए इनपुट के लिए उस समस्या से बचाता है, यही कारण है कि नीचे दिए गए कोड में इसका उपयोग किया गया है।
सामान्य परिवर्तन रणनीतियाँ:
- पहला या आखिरी तत्व: कोडिंग के लिहाज से सबसे सरल, लेकिन सॉर्ट किए गए डेटा पर O(n²) की त्रुटि।
- मध्य तत्व: एक अच्छा डिफ़ॉल्ट मान जो O(n log n) में सॉर्टेड और रिवर्स-सॉर्टेड एरे को हैंडल करता है।
- यादृच्छिक तत्व: इससे सबसे खराब स्थिति वाले इनपुट को पहले से तैयार करना असंभव हो जाता है।
- तीनों का माध्यिका: यह पहले, मध्य और अंतिम मानों का माध्यिका लेता है; उत्पादन पुस्तकालयों में यही मानक विकल्प है।
अब ऐरे पर क्विक सॉर्ट करने की प्रक्रिया को समझें। [5,3,7,6,2,9].
1 कदम: धुरी मध्य तत्व है। बाएँ = 0 और दाएँ = 5 के साथ, Math.floor((5 + 0) / 2) इससे इंडेक्स 2 मिलता है, इसलिए पिवट मान है 7.
2 कदम: एरे के सिरों पर पॉइंटर शुरू करें। बायां पॉइंटर इंडेक्स 0 (मान) पर है। 5और दायाँ पॉइंटर इंडेक्स 5 (मान) पर है 9).
3 कदम: बाईं ओर के मान की तुलना पिवट से करें। 5 < 7, इसलिए दाईं ओर इंडेक्स 1 पर जाएँ। 3 < 7, इसलिए दाईं ओर इंडेक्स 2 पर जाएँ। वहाँ का मान 7 है, जो पिवट से कम नहीं है, इसलिए बायाँ पॉइंटर इंडेक्स 2 पर रुक जाता है।
4 कदम: दाईं ओर के मान की तुलना पिवट से करें। 9 > 7, इसलिए बाईं ओर इंडेक्स 4 पर जाएँ। वहाँ का मान 2 है, जो पिवट से बड़ा नहीं है, इसलिए दायाँ पॉइंटर इंडेक्स 4 पर रुक जाता है।
5 कदम: बायां सूचकांक (2) दाएं सूचकांक (4) से छोटा या बराबर है, इसलिए दोनों मानों को आपस में बदल दें। सरणी इस प्रकार हो जाती है। [5,3,2,6,7,9].
6 कदम: दोनों पॉइंटर्स को एक-एक कदम अंदर की ओर ले जाएं। अब बायां पॉइंटर इंडेक्स 3 पर है और दायां पॉइंटर भी इंडेक्स 3 पर है।
7 कदम: स्कैन को दोहराएँ। इंडेक्स 3 पर मान 6 है, और 6 < 7 है, इसलिए बायाँ पॉइंटर इंडेक्स 4 पर चला जाता है। इंडेक्स 3 पर मान पिवट से बड़ा नहीं है, इसलिए दायाँ पॉइंटर इंडेक्स 3 पर ही रहता है।
8 कदम: अब बायां सूचकांक (4) दाएं सूचकांक (3) से बड़ा है, इसलिए लूप समाप्त हो जाता है और फ़ंक्शन रिटर्न करता है। 4इंडेक्स 4 से पहले की हर चीज़ पिवट से छोटी या उसके बराबर है, और इंडेक्स 4 के बाद की हर चीज़ पिवट से बड़ी या उसके बराबर है।
उस विस्तृत विवरण के आधार पर, आपको दो ऑपरेशनों के लिए कोड की आवश्यकता होगी: स्वैपping दो तत्वों और एक रेंज का विभाजन।
Code दो को बदलने के लिए Numbers in Javaलिपि
जैसा कि ऊपर दिए गए एडिटर स्क्रीनशॉट में दिखाया गया है, स्वैप हेल्पर दो इंडेक्स पर मानों को बदलने के लिए एक अस्थायी वेरिएबल का उपयोग करता है। यह सीधे एरे को परिवर्तित करता है और कुछ भी वापस नहीं करता है।
function swap(items, leftIndex, rightIndex) { var temp = items[leftIndex]; items[leftIndex] = items[rightIndex]; items[rightIndex] = temp; } var demo = [5, 3, 7, 6, 2, 9]; swap(demo, 0, 5); console.log(demo);
आउटपुट:
[ 9, 3, 7, 6, 2, 5 ]
💡टिप: आधुनिक Javaस्क्रिप्ट ऐरे डिस्ट्रक्चरिंग का उपयोग करके बिना किसी अस्थायी वेरिएबल के स्वैप कर सकती है: [items[i], items[j]] = [items[j], items[i]];यह अधिक स्पष्ट रूप से पढ़ा जाता है, हालांकि स्पष्ट हेल्पर हॉट लूप में थोड़ा तेज होता है क्योंकि यह एक अस्थायी सरणी आवंटित करने से बचता है।
Code विभाजन करने के लिए
ऊपर दिए गए स्क्रीनशॉट में कोड चरण 1 से 8 को एक फ़ंक्शन में बदल देता है। दो आंतरिक छोरों पॉइंटर्स को आगे बढ़ाएं, if ब्लॉक स्वैप करता है, और फ़ंक्शन स्प्लिट इंडेक्स लौटाता है।
function partition(items, left, right) { var pivot = items[Math.floor((right + left) / 2)], // middle element i = left, // left pointer j = right; // right pointer while (i <= j) { while (items[i] < pivot) { i++; } while (items[j] > pivot) { j--; } if (i <= j) { swap(items, i, j); // swap two elements i++; j--; } } return i; } var items = [5, 3, 7, 6, 2, 9]; var index = partition(items, 0, items.length - 1); console.log(items); console.log(index);
आउटपुट:
[ 5, 3, 2, 6, 7, 9 ] 4
आउटपुट मैनुअल वॉकथ्रू से बिल्कुल मेल खाता है: एक विभाजन पास के बाद सरणी [5,3,2,6,7,9] है और लौटाया गया विभाजन सूचकांक 4 है।
पुनरावर्ती क्रिया का निष्पादन करें Operaउत्पादन
विभाजन से विभाजन सूचकांक प्राप्त होने के बाद, इसका उपयोग करके रेंज को विभाजित करें और प्रत्येक भाग पर क्विक सॉर्ट चलाएँ। इसीलिए इसे डिवाइड एंड कॉंकर एल्गोरिदम कहा जाता है। यह प्रक्रिया तब तक चलती रहती है जब तक कि प्रत्येक उप-रेंज में एक ही तत्व न रह जाए, जिसके बाद पूरी सरणी सॉर्ट हो जाती है।
नोट: क्विक सॉर्ट पूरी प्रक्रिया के दौरान एक ही ऐरे पर काम करता है। इस प्रक्रिया में कोई नया ऐरे नहीं बनाया जाता है, यही कारण है कि यह एक इन-प्लेस एल्गोरिदम है।
तो आप इसे कॉल करते हैं विभाजन () ऊपर बताए गए फ़ंक्शन का उपयोग करें और इसके रिटर्न वैल्यू का उपयोग करके विभाजित करें सरणी इसे भागों में विभाजित करें। यह वह कोड है जो ऐसा करता है:
स्क्रीनशॉट में हाइलाइट की गई दो सुरक्षा स्थितियों पर ध्यान दें। left < index - 1 यह पुष्टि करता है कि बाईं ओर कम से कम दो तत्व शेष हैं, और index < right यह बात दाईं ओर के लिए भी सही साबित होती है। उन सुरक्षा उपायों के बिना, यह फ़ंक्शन एकल-तत्व श्रेणियों पर हमेशा के लिए खुद को कॉल करता रहेगा।
function quickSort(items, left, right) { var index; if (items.length > 1) { index = partition(items, left, right); // index returned from partition if (left < index - 1) { // more elements on the left side of the pivot quickSort(items, left, index - 1); } if (index < right) { // more elements on the right side of the pivot quickSort(items, index, right); } } return items; } // first call to quick sort var items = [5, 3, 7, 6, 2, 9]; var result = quickSort(items, 0, items.length - 1); console.log(result);
आउटपुट:
[ 2, 3, 5, 6, 7, 9 ]
त्वरित छँटाई पूरी करें Code
स्वैप, विभाजन और पुनरावर्तन के घटकों को एक साथ रखने से पूर्ण कार्यान्वयन प्राप्त होता है:
var items = [5, 3, 7, 6, 2, 9]; function swap(items, leftIndex, rightIndex) { var temp = items[leftIndex]; items[leftIndex] = items[rightIndex]; items[rightIndex] = temp; } function partition(items, left, right) { var pivot = items[Math.floor((right + left) / 2)], // middle element i = left, // left pointer j = right; // right pointer while (i <= j) { while (items[i] < pivot) { i++; } while (items[j] > pivot) { j--; } if (i <= j) { swap(items, i, j); // swapping two elements i++; j--; } } return i; } function quickSort(items, left, right) { var index; if (items.length > 1) { index = partition(items, left, right); // index returned from partition if (left < index - 1) { // more elements on the left side of the pivot quickSort(items, left, index - 1); } if (index < right) { // more elements on the right side of the pivot quickSort(items, index, right); } } return items; } // first call to quick sort var sortedArray = quickSort(items, 0, items.length - 1); console.log(sortedArray);
आउटपुट:
[ 2, 3, 5, 6, 7, 9 ]
ऊपर दिए गए स्क्रीनशॉट में एडिटर में पूरा प्रोग्राम और कंसोल में सॉर्ट किया हुआ ऐरे दिखाया गया है। इस इम्प्लीमेंटेशन को पहले से सॉर्ट किए हुए ऐरे, रिवर्स सॉर्ट किए हुए ऐरे, डुप्लिकेट और समान मानों वाले ऐरे, ऋणात्मक संख्याओं वाले ऐरे, एक तत्व वाले ऐरे और एक खाली ऐरे के विरुद्ध सत्यापित किया गया है, और यह हर मामले में सही परिणाम देता है।
💡टिप: गार्ड if (items.length > 1) यह वर्तमान रेंज के बजाय पूरे ऐरे की लंबाई की जाँच करता है। यह यहाँ काम करता है क्योंकि दो रिकर्सिव कॉल पहले से ही सुरक्षित हैं। left < index - 1 और index < right, परंतु if (left >= right) { return items; } यह नए कोड में लिखने के लिए अधिक स्पष्ट और सुरक्षित स्थिति है।
क्विक सॉर्ट की समय और स्थान जटिलता
प्रत्येक विभाजन प्रक्रिया में रेंज के प्रत्येक तत्व को एक बार संसाधित किया जाता है, इसलिए एक प्रक्रिया की लागत O(n) होती है। अतः कुल लागत इस बात पर निर्भर करती है कि रेंज के सरल होने से पहले सरणी को कितनी बार विभाजित किया जा सकता है।
| मामला | समय की जटिलता | जब यह होता है |
|---|---|---|
| श्रेष्ठ | ओ(एन लॉग एन) | प्रत्येक धुरी अपनी सीमा को समान आकार के दो हिस्सों में विभाजित करती है। |
| औसत | ओ(एन लॉग एन) | उचित पिवट नियम के साथ यादृच्छिक रूप से व्यवस्थित इनपुट। |
| वर्स्ट | ओ (एन²) | प्रत्येक पिवट सबसे छोटा या सबसे बड़ा मान होता है, जिससे पुनरावृति के n स्तर प्राप्त होते हैं। |
स्पेस कॉम्प्लेक्सिटी O(log n) है। इस इन-प्लेस संस्करण के लिए। कोई दूसरा ऐरे आवंटित नहीं किया जाता है, इसलिए अतिरिक्त मेमोरी केवल रिकर्सन स्टैक है, और संतुलित विभाजन उस स्टैक को लगभग log₂(n) फ्रेम की गहराई तक रखता है। सबसे खराब स्थिति में स्टैक O(n) फ्रेम तक बढ़ जाता है, यही कारण है कि बहुत बड़े ऐरे कॉल स्टैक को ओवरफ्लो कर सकते हैं।
दो आंकड़े इस बात को पुष्ट करते हैं। उपरोक्त कोड का उपयोग करके 4,096 यादृच्छिक मानों को सॉर्ट करने में सैद्धांतिक n·log₂(n) के 49,152 मानों की तुलना में लगभग 65,000 तुलनाएँ हुईं, और सबसे गहरी पुनरावृति 24 फ्रेम तक पहुँची जबकि log₂(4096) 12 है। ये दोनों आंकड़े O(n log n) एल्गोरिथम के लिए अपेक्षित छोटे स्थिर कारक के भीतर आते हैं।
⚠️ चेतावनी: क्विक सॉर्ट को केवल "एक O(n log n) एल्गोरिदम" कहना अधूरा है। इसका सबसे खराब मामला O(n²) है, और एक सरल प्रथम-तत्व पिवट ठीक उसी सबसे खराब मामले को दर्शाता है जो आपको उत्पादन में मिलने की सबसे अधिक संभावना है: पहले से ही सॉर्ट किया हुआ डेटा।
त्वरित छँटाई बनाम अन्य छँटाई Algorithms
क्विक सॉर्ट अक्सर एकमात्र विकल्प नहीं होता है। नीचे दी गई तालिका में इसकी तुलना अन्य एल्गोरिदम से की गई है जिनसे आपका सामना होने की सबसे अधिक संभावना है, ताकि आप अपने डेटा के लिए सही विकल्प चुन सकें।
| कलन विधि | श्रेष्ठ | औसत | वर्स्ट | अंतरिक्ष | स्थिर |
|---|---|---|---|---|---|
| जल्दी से सुलझाएं | ओ(एन लॉग एन) | ओ(एन लॉग एन) | ओ (एन²) | O (लॉग एन) | नहीं |
| मर्ज़ सॉर्ट | ओ(एन लॉग एन) | ओ(एन लॉग एन) | ओ(एन लॉग एन) | पर) | हाँ |
| ढेर बनाएं और छांटें | ओ(एन लॉग एन) | ओ(एन लॉग एन) | ओ(एन लॉग एन) | ओ (1) | नहीं |
| सम्मिलन सॉर्ट | पर) | ओ (एन²) | ओ (एन²) | ओ (1) | हाँ |
| Bubblई क्रमबद्ध करें | पर) | ओ (एन²) | ओ (एन²) | ओ (1) | हाँ |
| चयन छांटना | ओ (एन²) | ओ (एन²) | ओ (एन²) | ओ (1) | नहीं |
व्यवहार में क्विक सॉर्ट आमतौर पर बेहतर साबित होता है क्योंकि इसका आंतरिक लूप सीमित होता है और यह कैश-अनुकूल सन्निहित श्रेणियों में काम करता है। जब आपको O(n log n) की गारंटीकृत सीमा या स्थिर क्रम की आवश्यकता हो तो मर्ज सॉर्ट चुनें, जब मेमोरी बहुत सीमित हो तो हीप सॉर्ट चुनें, और बहुत छोटे या लगभग क्रमबद्ध सरणियों के लिए इंसर्शन सॉर्ट चुनें। प्रोडक्शन लाइब्रेरी अक्सर इन्हें संयोजित करती हैं: इंट्रोसॉर्ट क्विक सॉर्ट से शुरू होता है, यदि रिकर्सन बहुत गहरा हो जाता है तो हीप सॉर्ट पर स्विच करता है, और छोटी श्रेणियों पर इंसर्शन सॉर्ट के साथ समाप्त होता है।
ऑब्जेक्ट और स्ट्रिंग को जल्दी से सॉर्ट कैसे करें
अब तक प्रदर्शित कार्यान्वयन मूल्यों की तुलना करता है < और >जो इसे संख्याओं तक सीमित कर देता है। वास्तविक अनुप्रयोगों को सॉर्ट करने की आवश्यकता होती है। वस्तुओं किसी प्रॉपर्टी, वर्णानुक्रमिक स्ट्रिंग या कालानुक्रमिक तिथियों के आधार पर तुलना करना। इसका समाधान यह है कि तुलना को एक कॉलबैक में स्थानांतरित कर दिया जाए, ठीक उसी तरह जैसे बिल्ट-इन फ़ंक्शन में होता है। sort() करता है.
एक तुलनित्र (कंपैरेटर) दो मान प्राप्त करता है और पहले मान के पहले आने पर ऋणात्मक संख्या, दूसरे मान के पहले आने पर धनात्मक संख्या और दोनों मानों के समतुल्य होने पर शून्य लौटाता है। दो निश्चित कोडित तुलनाओं को तुलनित्र कॉल से बदलने पर यह एल्गोरिदम किसी भी डेटा प्रकार पर काम करने योग्य हो जाता है।
function swap(items, i, j) { var temp = items[i]; items[i] = items[j]; items[j] = temp; } function partition(items, left, right, compare) { var pivot = items[Math.floor((right + left) / 2)], i = left, j = right; while (i <= j) { while (compare(items[i], pivot) < 0) { i++; } while (compare(items[j], pivot) > 0) { j--; } if (i <= j) { swap(items, i, j); i++; j--; } } return i; } function quickSort(items, left, right, compare) { if (left >= right) { return items; } // nothing left to split var index = partition(items, left, right, compare); if (left < index - 1) { quickSort(items, left, index - 1, compare); } if (index < right) { quickSort(items, index, right, compare); } return items; } function sort(items, compare) { compare = compare || function (a, b) { return a < b ? -1 : a > b ? 1 : 0; }; return quickSort(items, 0, items.length - 1, compare); } var numbers = [10, 9, 1, 100, 25]; console.log(sort(numbers, function (a, b) { return a - b; })); var names = ["Priya", "arun", "Bala", "chetan"]; console.log(sort(names, function (a, b) { return a.toLowerCase().localeCompare(b.toLowerCase()); })); var employees = [ { name: "Arun", salary: 52000 }, { name: "Bala", salary: 41000 }, { name: "Chetan", salary: 68000 } ]; console.log(sort(employees, function (a, b) { return a.salary - b.salary; }));
आउटपुट:
[ 1, 9, 10, 25, 100 ]
[ 'arun', 'Bala', 'chetan', 'Priya' ]
[
{ name: 'Bala', salary: 41000 },
{ name: 'Arun', salary: 52000 },
{ name: 'Chetan', salary: 68000 }
]
तीन बातें ध्यान देने योग्य हैं। रिकर्सन गार्ड अब left >= rightजो किसी भी रेंज के लिए सही है और बाहरी ऐरे की लंबाई पर निर्भर नहीं करता है। स्ट्रिंग तुलना का उपयोग करता है localeCompare() ताकि उच्चारण वाले अक्षर और केस को रॉ कोड पॉइंट के बजाय सही ढंग से संभाला जा सके। और क्योंकि क्विक सॉर्ट स्थिर नहीं है, इसलिए समान वेतन वाले रिकॉर्ड अपनी जगह बदल सकते हैं; यदि मूल क्रम आपके लिए महत्वपूर्ण है, तो टाई-ब्रेकिंग दूसरी कुंजी द्वारा सॉर्ट करें।
आगे बढ़ने के लिए तैयार हैं? बुनियादी बातों को मजबूत करें Javaपटकथा का परिचयपॉइंटर की कार्यप्रणाली का अभ्यास करें Javaस्क्रिप्ट लूपऔर अधिक काम करें व्यावहारिक Javaस्क्रिप्ट कोड के उदाहरणकार्यान्वयनों की तुलना करें सम्मिलन सॉर्ट और ढेर बनाएं और छांटेंया इस एल्गोरिदम में स्टैटिक प्रकार जोड़ें TypeScript संदर्भ।







