ज्यादातर सॉर्ट किए गए डेटा पर कौन सा छंटाई एल्गोरिथ्म सबसे अच्छा काम करता है?
ज्यादातर सॉर्ट किए गए डेटा पर कौन सा छंटाई एल्गोरिथ्म सबसे अच्छा काम करता है?
जवाबों:
एनिमेटेड जिफ देखने के उच्च वैज्ञानिक तरीके के आधार पर मैं कहूंगा कि प्रविष्टि और बबल प्रकार अच्छे उम्मीदवार हैं।
केवल कुछ आइटम => बीमा क्षेत्र
आइटम ज्यादातर पहले से ही सॉर्ट किए जाते हैं => इंसर्ट सोर
सबसे खराब स्थिति के बारे में चिंतित => HEAP SORT
एक अच्छे औसत-मामले के परिणाम में रुचि => QUICKSORT
आइटम घने ब्रह्माण्ड से खींचे जाते हैं => BUCKET SORT
जितना संभव हो उतना कम कोड लिखने की इच्छा => बीमा क्षेत्र
Timsort " कई प्रकार के आंशिक रूप से ऑर्डर किए गए सरणियों (lg (N! तुलनात्मक तुलना में कम) और N-1 के रूप में कम) पर " अलौकिक , स्थिर, प्राकृतिक विलय "है। अजगर का बनाया हुआsort()
कुछ समय के लिए इस एल्गोरिथ्म का उपयोग किया है, जाहिर है अच्छे परिणामों के साथ। यह विशेष रूप से इनपुट में आंशिक रूप से क्रमबद्ध क्रमों का पता लगाने और लाभ उठाने के लिए डिज़ाइन किया गया है, जो अक्सर वास्तविक डेटासेट में होते हैं। यह वास्तविक दुनिया में अक्सर ऐसा होता है कि किसी सूची में वस्तुओं की अदला-बदली की तुलना में बहुत अधिक महंगा होता है, क्योंकि आमतौर पर बस पॉइंटर्स को स्वैप किया जाता है, जो बहुत बार टाइमसॉर्ट को एक उत्कृष्ट विकल्प बनाता है। हालांकि, यदि आप जानते हैं कि आपकी तुलना हमेशा बहुत सस्ती है (उदाहरण के लिए, 32-बिट पूर्णांक को सॉर्ट करने के लिए एक खिलौना प्रोग्राम लिखना), अन्य एल्गोरिदम मौजूद हैं जो बेहतर प्रदर्शन करने की संभावना रखते हैं। टाइमसॉर्ट का लाभ उठाने का सबसे आसान तरीका निश्चित रूप से पायथन का उपयोग करना है, लेकिन चूंकि पायथन खुला स्रोत है इसलिए आप कोड उधार लेने में भी सक्षम हो सकते हैं। वैकल्पिक रूप से, ऊपर दिए गए विवरण में अपने स्वयं के कार्यान्वयन को लिखने के लिए पर्याप्त विवरण शामिल हैं।
lg(n!)
-सॉर्ट, लगभग सभी तरह की सरणी पर तुलना की तुलना में बहुत तेज है , नीचे सभी तरह से O(n)
! | @behrooz: नहीं तुलना प्रकार की तुलना में बेहतर औसत मामला हो सकता है O(n log n)
, और lg(n!)
है O(n log n)
। इसलिए टाइमसॉर्ट का सबसे खराब मामला किसी भी अन्य तुलनात्मक प्रकार की तुलना में असमान रूप से बुरा नहीं है। इसके अलावा इसका सबसे अच्छा मामला किसी भी अन्य तुलनात्मक प्रकार से बेहतर या बराबर है।
निम्नलिखित व्यवहार के साथ सम्मिलन क्रमबद्ध करें:
k
स्लॉट्स में प्रत्येक तत्व के लिए 1..n
, पहले जांचें कि क्या el[k] >= el[k-1]
। यदि ऐसा है, तो अगले तत्व पर जाएं। (स्पष्ट रूप से पहला तत्व छोड़ें।)1..k-1
सम्मिलन स्थान निर्धारित करने के लिए तत्वों में बाइनरी-खोज का उपयोग करें , तो तत्वों को खत्म कर दें। (आप इसे केवल तभी कर सकते हैं यदि कुछ थ्रेशोल्ड मान k>T
कहाँ T
है; छोटे के साथ k
यह ओवरकिल है।)यह विधि कम से कम तुलना की संख्या बनाती है।
आत्मनिरीक्षण का प्रयास करें। http://en.wikipedia.org/wiki/Introsort
यह क्विकसॉर्ट आधारित है, लेकिन यह सबसे खराब स्थिति वाले व्यवहार से बचता है जो क्विकॉर्ट के पास लगभग छांटे गए सूचियों के लिए है।
चाल यह है कि यह सॉर्ट-एल्गोरिथ्म उन मामलों का पता लगाता है जहां क्विकॉर्ट सबसे खराब स्थिति में जाता है और सॉर्ट करने या विलय करने के लिए स्विच करता है। लगभग गैर-विभाजन विभाजन विधि द्वारा लगभग छांटे गए विभाजन का पता लगाया जाता है और सम्मिलन प्रकार का उपयोग करके छोटे विभाजन को संभाला जाता है।
अधिक कोड और जटिलता की लागत के लिए आपको सभी प्रमुख सॉर्टिंग एल्गोरिदम मिलते हैं। और आप यह सुनिश्चित कर सकते हैं कि आप कभी भी सबसे खराब स्थिति वाले व्यवहार में नहीं चलेंगे चाहे आपका डेटा कैसा भी दिखे।
यदि आप C ++ प्रोग्रामर हैं तो अपने std :: सॉर्ट एल्गोरिथ्म की जांच करें। यह पहले से ही आंतरिक रूप से आत्मनिरीक्षण का उपयोग कर सकता है।
Splaysort एक अस्पष्ट छँटाई विधि है जो कि आवारा पेड़ों , एक प्रकार के अनुकूली बाइनरी ट्री पर आधारित है । Splaysort न केवल आंशिक रूप से सॉर्ट किए गए डेटा के लिए, बल्कि आंशिक रूप से रिवर्स-सॉर्ट किए गए डेटा, या वास्तव में किसी भी डेटा के लिए अच्छा है, जिसमें किसी भी प्रकार का पूर्व-मौजूदा क्रम है। यह सामान्य मामले में O (nlogn) है, और O (n) उस मामले में जहां डेटा को किसी तरह से सॉर्ट किया जाता है (आगे, रिवर्स, ऑर्गन-पाइप, आदि)।
प्रविष्टि सॉर्ट पर इसका बड़ा लाभ यह है कि यह डेटा में बिल्कुल भी सॉर्ट नहीं किए जाने पर O (n ^ 2) व्यवहार पर वापस नहीं आता है, इसलिए आपको यह सुनिश्चित करने की आवश्यकता नहीं है कि डेटा का उपयोग करने से पहले आंशिक रूप से सॉर्ट किया गया है ।
इसका नुकसान यह है कि यह जिस आवारा पेड़ की संरचना की जरूरत है, उसके अतिरिक्त स्थान के साथ-साथ यह भी आवश्यक है कि स्प्ले ट्री को बनाने और नष्ट करने के लिए आवश्यक समय हो। लेकिन डेटा के आकार और आपके द्वारा अपेक्षित पूर्व-मात्रा की मात्रा के आधार पर, ओवरहेड गति में वृद्धि के लिए इसके लायक हो सकता है।
Splaysort पर एक पेपर सॉफ्टवेयर - प्रैक्टिस एंड एक्सपीरियंस में प्रकाशित किया गया था।
पहले से ही सॉर्ट किए गए डेटा पर डायजेक्स्ट्रा का स्मूदसॉर्ट एक शानदार सॉर्ट है। यह एक हेस्पोर्ट वेरिएंट है जो O (n lg n) सबसे खराब स्थिति और O (n) बेस्ट-केस में चलता है। मैंने एल्गोरिथ्म का विश्लेषण लिखा है, यदि आप उत्सुक हैं कि यह कैसे काम करता है।
प्राकृतिक मर्जर्ट इसके लिए एक और बहुत अच्छा है - यह एक बॉटम-अप मर्जर्ट वैरिएंट है जो इनपुट को कई अलग-अलग सॉर्ट किए गए श्रेणियों के संयोजन के रूप में मानकर काम करता है, फिर मर्ज एल्गोरिथ्म का उपयोग करके उन्हें एक साथ जोड़ देता है। आप इस प्रक्रिया को तब तक दोहराते हैं जब तक कि सभी इनपुट रेंज सॉर्ट न हो जाएं। यह O (n) समय में चलता है यदि डेटा पहले से ही सॉर्ट किया गया है और O (n lg n) सबसे खराब स्थिति में है। यह बहुत ही सुंदर है, हालांकि व्यवहार में यह कुछ अन्य अनुकूली प्रकारों जैसे कि टिम्सॉर्ट या स्मूथोर्ट के रूप में अच्छा नहीं है।
प्रविष्टि प्रकार O (n + व्युत्क्रम की संख्या) समय लेता है।
उलटा एक जोड़ा है (i, j)
ऐसा i < j && a[i] > a[j]
। यानी एक आउट-ऑफ-ऑर्डर जोड़ी।
"लगभग छांटे जाने" का एक उपाय है, व्युत्क्रमों की संख्या --- कोई कुछ व्युत्क्रमों के साथ डेटा का अर्थ "लगभग क्रमबद्ध डेटा" ले सकता है। यदि किसी को व्युत्क्रमानुपाती होने की संख्या ज्ञात है (उदाहरण के लिए, आपने ओ (1) तत्वों को क्रमबद्ध सूची में जोड़ दिया है), प्रविष्टि सॉर्ट में O (n) समय लगता है।
जैसा कि बाकी सभी ने कहा, भोले क्विकसॉर्ट से सावधान रहें - जिसमें सॉर्ट किए गए या लगभग सॉर्ट किए गए डेटा पर O (N ^ 2) का प्रदर्शन हो सकता है। फिर भी, पिवट की पसंद के लिए एक उपयुक्त एल्गोरिथ्म के साथ (या तो यादृच्छिक या मध्य-तीन - क्विकॉर्ट के लिए एक पिवेट चुनना देखें ), क्विकॉर्ट अभी भी पूरी तरह से काम करेगा।
सामान्य तौर पर, एल्गोरिदम जैसे डालने के प्रकार को चुनने में कठिनाई यह तय करने में होती है कि डेटा पर्याप्त रूप से ऑर्डर से बाहर है कि क्विकॉर्ट वास्तव में जल्दी होगा।
मैं यहाँ सभी उत्तरों के बहाने नहीं जा रहा हूँ, क्योंकि मुझे लगता है कि वास्तविक उत्तरों को प्राप्त करने के लिए एल्गोरिदम को कोड करना और उन्हें प्रतिनिधि डेटा नमूनों के विरुद्ध प्रोफाइलिंग की आवश्यकता हो सकती है। लेकिन मैं इस सवाल के बारे में पूरी शाम सोच रहा हूं, और यहां मेरे साथ अब तक क्या हुआ है, और कुछ इस बात का अनुमान लगाते हैं कि सबसे अच्छा काम कहां होता है।
बता दें कि N कुल आइटमों की संख्या है, M क्रम-आउट संख्या है।
बबल सॉर्ट को 2 * M + 1 जैसा कुछ बनाना होगा जो सभी N आइटम से होकर गुजरेगा। यदि M बहुत छोटा है (0, 1, 2?), मुझे लगता है कि यह हराना बहुत कठिन होगा।
यदि M छोटा है (लॉग एन से कम कहें), तो प्रविष्टि सॉर्ट में औसत औसत प्रदर्शन होगा। हालाँकि, जब तक कोई चाल नहीं चल रही है, तब तक यह बहुत खराब स्थिति वाला प्रदर्शन होगा। (सही! यदि ऑर्डर में अंतिम आइटम पहले आता है, तो आपको हर एक आइटम को सम्मिलित करना होगा, जहां तक मैं देख सकता हूं, जो प्रदर्शन को मार देगा।) मैं अनुमान लगा रहा हूं कि इसके लिए एक अधिक विश्वसनीय छंटनी एल्गोरिदम है। मामला, लेकिन मुझे नहीं पता कि यह क्या है।
यदि M बड़ा है (लॉग एन की तुलना में बराबर या महान है), आत्मनिरीक्षण सॉर्ट लगभग निश्चित रूप से सबसे अच्छा है।
उस सभी के लिए अपवाद: यदि आप वास्तव में समय से पहले जानते हैं कि कौन से तत्व अनसोल्ड हैं, तो आपकी सबसे अच्छी शर्त उन वस्तुओं को बाहर निकालना होगा, उन्हें आत्मनिरीक्षण प्रकार का उपयोग करके सॉर्ट करना होगा, और दो सॉर्ट की गई सूचियों को एक साथ एक क्रमबद्ध सूची में मर्ज करना होगा। यदि आप जल्दी से पता लगा सकते हैं कि कौन सी वस्तुएं ऑर्डर से बाहर हैं, तो यह एक अच्छा सामान्य समाधान होगा - लेकिन मैं ऐसा करने के लिए एक सरल तरीका नहीं समझ पाया।
आगे के विचार (रात भर): यदि M + 1 <N / M, तो आप एक पंक्ति में N / M के रन की तलाश करने वाली सूची को स्कैन कर सकते हैं, जिसे क्रमबद्ध किया गया है, और फिर उस आउट का पता लगाने के लिए दोनों दिशाओं में विस्तार करें -चिजें मँगाओ। यह सबसे अधिक 2N तुलना में ले जाएगा। फिर आप अनसोल्ड आइटम को सॉर्ट कर सकते हैं, और दो सूचियों पर एक सॉर्ट मर्ज कर सकते हैं। कुल तुलना 4N + M log2 (M) जैसी किसी चीज से कम होनी चाहिए, जो कि किसी गैर-विशिष्ट सॉर्टिंग रूटीन को मात देने वाली है, मुझे लगता है। (इससे भी आगे सोचा: यह मेरे विचार से बहुत मुश्किल है, लेकिन मुझे अभी भी लगता है कि यह यथोचित संभव है।)
प्रश्न की एक और व्याख्या यह है कि कई आउट-ऑफ-ऑर्डर आइटम हो सकते हैं, लेकिन वे सूची में कहाँ होना चाहिए, इसके बहुत करीब हैं। (कल्पना करें कि एक क्रमबद्ध सूची के साथ शुरू करें और उसके बाद आने वाले हर दूसरे आइटम को स्वैप करें।) उस स्थिति में मुझे लगता है कि बुलबुला सॉर्ट बहुत अच्छा करता है - मुझे लगता है कि पास की संख्या एक आइटम के बाहर सबसे दूर के लिए आनुपातिक होगी। है। प्रविष्टि सॉर्ट खराब रूप से काम करेगा, क्योंकि ऑर्डर आइटम में से प्रत्येक एक प्रविष्टि को ट्रिगर करेगा। मुझे लगता है कि आत्मनिरीक्षण का संदेह है या ऐसा कुछ भी अच्छा काम करेगा।
यदि आपको एल्गोरिदम, डेटा संरचनाओं या ऊपर दी गई किसी भी लिंक को छांटने के लिए विशिष्ट कार्यान्वयन की आवश्यकता है, तो क्या मैं आपको कोडप्लेक्स पर उत्कृष्ट "डेटा संरचना और एल्गोरिदम" परियोजना की सिफारिश कर सकता हूं ?
इसमें वह सब कुछ होगा जो आपको पहिया को फिर से लगाए बिना चाहिए।
बस नमक का मेरा छोटा सा दाना।
जवाबों में इस उद्देश्य के लिए छँटाई एल्गोरिदम का यह अच्छा संग्रह, गनोम सॉर्ट की कमी लगता है , जो उपयुक्त भी होगा, और शायद कम से कम कार्यान्वयन के प्रयास की आवश्यकता होती है।
बबल-सॉर्ट (या, अभी तक, द्वि-दिशात्मक बबल सॉर्ट) ज्यादातर सॉर्ट किए गए सूचियों के लिए आदर्श है, हालांकि मैंने शर्त लगाई कि एक कंघी कंघी-सॉर्ट (बहुत कम प्रारंभिक अंतराल के आकार के साथ) सूची के एनएन होने पर थोड़ा तेज होगा। टी काफी पूरी तरह से हल के रूप में। बबल-सॉर्ट करने के लिए तरह तरह के गिरावट।
अच्छी तरह से यह उपयोग के मामले पर निर्भर करता है। यदि आप जानते हैं कि कौन से तत्व बदले गए हैं, तो निकालें और सम्मिलित करना सबसे अच्छा मामला होगा जहां तक मेरा संबंध है।
बबल सॉर्ट निश्चित रूप से विजेता है राडार पर अगला प्रविष्टि सॉर्ट होगा।
QuickSort से दूर रखें - पूर्व-सॉर्ट किए गए डेटा के लिए यह बहुत अक्षम है। प्रविष्टि सॉर्ट संभव के रूप में कुछ मानों को स्थानांतरित करके लगभग सॉर्ट किए गए डेटा को संभालता है।