जावा की Arrays.sort पद्धति विभिन्न प्रकारों के लिए दो अलग-अलग सॉर्टिंग एल्गोरिदम का उपयोग क्यों करती है?


121

जावा 6 की Arrays.sortविधि आदिमों के सरणियों के लिए क्विकसॉर्ट का उपयोग करती है और वस्तुओं की सरणियों के लिए विलय प्रकार है। मेरा मानना ​​है कि ज्यादातर समय क्विकॉर्ट मर्ज सॉर्ट की तुलना में तेज है और स्मृति की लागत कम है। मेरे प्रयोगों का समर्थन है, हालांकि दोनों एल्गोरिदम ओ (एन लॉग (एन)) हैं। तो विभिन्न प्रकारों के लिए अलग-अलग एल्गोरिदम का उपयोग क्यों किया जाता है?


14
क्विकसॉर्ट सबसे खराब स्थिति N ^ 2 नहीं NlogN है।
कोडैडक्ट

रुको, अगर आपके पास Integerएस या कुछ है तो क्या होगा ?
तिखन जेल्विस

1
क्या यह आपके द्वारा पढ़े गए स्रोत में नहीं बताया गया है?
हम्फ्रे बोगार्ट

5
यह जानकारी अब चालू नहीं है। जावा SE 7 में शुरू, MergeSort साथ प्रतिस्थापित किया गया TimSort और quicksort साथ प्रतिस्थापित किया गया दोहरे धुरी quicksort । जावा एपीआई डॉक्स के लिंक के लिए नीचे मेरा जवाब देखें।
बायरन होगा

यह भी देखें stackoverflow.com/questions/15154158/… और JDK 7+ के लिए देखें stackoverflow.com/questions/32334319/…
rogerdpack

जवाबों:


200

सबसे संभावित कारण: एस्कॉर्ट स्थिर नहीं है , अर्थात समान प्रविष्टियों को सॉर्ट के दौरान उनकी सापेक्ष स्थिति बदल सकती है; अन्य बातों के अलावा, इसका मतलब है कि यदि आप पहले से छांटे गए सरणी को क्रमबद्ध करते हैं, तो यह अपरिवर्तित नहीं रह सकता है।

चूंकि आदिम प्रकारों की कोई पहचान नहीं है (एक ही मूल्य के साथ दो ints को भेद करने का कोई तरीका नहीं है), यह उनके लिए कोई मायने नहीं रखता है। लेकिन संदर्भ प्रकारों के लिए, यह कुछ अनुप्रयोगों के लिए समस्याएं पैदा कर सकता है। इसलिए, उन लोगों के लिए एक स्थिर मर्ज प्रकार का उपयोग किया जाता है।

OTOH, आदिम प्रकारों के लिए (गारंटी एन * लॉग (n)) स्थिर मर्ज सॉर्ट का उपयोग नहीं करने का एक कारण यह हो सकता है कि इसके लिए सरणी का क्लोन बनाने की आवश्यकता हो। संदर्भ प्रकारों के लिए, जहां संदर्भित ऑब्जेक्ट आमतौर पर संदर्भों की सरणी से कहीं अधिक मेमोरी लेते हैं, यह आमतौर पर कोई फर्क नहीं पड़ता। लेकिन आदिम प्रकारों के लिए, सरणी को एकमुश्त क्लोन करने से मेमोरी का उपयोग दोगुना हो जाता है।


1
क्विकॉर्ट का उपयोग करने का एक और कारण यह है कि औसत मामले पर, क्वर्ट्स मर्जर्ट की तुलना में तेज है। हालांकि क्विकसर्ट मर्जेसर्ट की तुलना में अधिक करता है, यह बहुत कम सरणी एक्सेस करता है। 3-तरफ़ा एस्कॉर्ट भी रैखिक समय प्राप्त कर सकता है यदि इनपुट में बहुत अधिक डुप्लिकेट की गई प्रविष्टियाँ हैं जो व्यावहारिक अनुप्रयोगों में असामान्य नहीं है (मेरा अनुमान है कि दोहरी धुरी त्वरित-प्रकार में भी यह गुण है)।
जिंगगू याओ

आदिम प्रकारों के लिए यह सरणी को क्लोन नहीं करता है, यह उन्हें जगह में सॉर्ट कर सकता है, इसलिए मुझे लगता है कि एकमात्र कारण स्थिरता अनुबंध है, मूल रूप से ...
rogerdpack

27

इस जवाब में उद्धृत जावा 7 एपीआई डॉक्स के अनुसार , Arrays#Sort()ऑब्जेक्ट सरणियों के लिए अब टिमसॉर्ट का उपयोग किया जाता है , जो मर्जसॉर्ट और इंसर्शनसॉर्ट का एक संकर है। दूसरी ओर, Arrays#sort()आदिम सरणियों के लिए अब दोहरे-धुरी क्विकॉर्ट का उपयोग किया जाता है । ये बदलाव जावा एसई 7 में शुरू किए गए थे।


2
यह एक उत्तर नहीं है, 2 अलग-अलग एल्गोरिदम क्यों चुने गए हैं।
एलेक्जेंड्रा

12

एक कारण जो मैं सोच सकता हूं वह यह है कि क्विकॉर्ट के पास ओ ( एन ^ 2 ) की सबसे खराब स्थिति समय की जटिलता है जबकि मर्जर्ट ओ के सबसे खराब मामले के समय को बनाए रखता है ( एन लॉग एन ) को । ऑब्जेक्ट सरणियों के लिए एक निष्पक्ष उम्मीद है कि कई डुप्लिकेट ऑब्जेक्ट संदर्भ होंगे जो एक मामला है जहां क्विकर सबसे खराब करता है।

विभिन्न एल्गोरिदम की एक अच्छी दृश्य तुलना है, विभिन्न एल्गोरिदम के लिए सही-सबसे ग्राफ पर विशेष ध्यान दें।


2
जावा क्विकॉर्ट एक संशोधित क्विकॉर्ट है जो O (n ^ 2) से आगे नहीं बढ़ता है, डॉक्स से "यह एल्गोरिथ्म कई डेटा सेट पर n * लॉग (n) प्रदर्शन प्रदान करता है जो अन्य
क्विकॉर्ट्स

7

मैं आल्गोरिद्म पर कौरसेरा क्लास ले रहा था और एक व्याख्यान में प्रोफेसर बॉब सेडगविक ने सिस्टम सिस्टम के मूल्यांकन के बारे में बताया:

"यदि एक प्रोग्रामर वस्तुओं का उपयोग कर रहा है, तो शायद अंतरिक्ष एक महत्वपूर्ण रूप से महत्वपूर्ण विचार नहीं है और एक मर्ज प्रकार द्वारा उपयोग किया जाने वाला अतिरिक्त स्थान शायद एक समस्या नहीं है। और यदि एक प्रोग्रामर आदिम प्रकार का उपयोग कर रहा है, तो शायद प्रदर्शन सबसे महत्वपूर्ण चीज है इसलिए वे उपयोग करते हैं। जल्दी से सुलझाएं।"


4
इसका मुख्य कारण नहीं है। उस वाक्य के ठीक बाद एक सवाल था, "क्यों संदर्भ प्रकारों के लिए MergeSort का उपयोग किया जाता है?" (क्योंकि यह स्थिर है)। मुझे लगता है कि Sedgewick ने उस वीडियो का उल्लेख नहीं किया था जो इसे प्रश्न के लिए छोड़ देता है।
likern

1

java.util.Arrays का उपयोग करता है quicksort इस तरह के पूर्णांक और के रूप में आदिम प्रकार के लिए mergesort ऑब्जेक्ट को लागू करने के लिए तुलनीय या एक का उपयोग तुलनाकारी । दो अलग-अलग तरीकों का उपयोग करने का विचार यह है कि यदि प्रोग्रामर की वस्तुओं का उपयोग कर रहा है तो शायद अंतरिक्ष महत्वपूर्ण रूप से महत्वपूर्ण विचार नहीं है और इसलिए विलय द्वारा उपयोग किया जाने वाला अतिरिक्त स्थान शायद एक समस्या नहीं है और यदि प्रोग्रामर के आदिम प्रकारों का उपयोग करना संभवत: प्रदर्शन का सबसे अधिक उपयोग है। quicksort

उदाहरण के लिए: स्थिरता को हल करते समय यह उदाहरण है।

यहां छवि विवरण दर्ज करें

यही कारण है कि स्थिर प्रकार वस्तु प्रकार के लिए समझ में आता है, विशेष रूप से परिवर्तनशील वस्तु प्रकार और वस्तु प्रकार से अधिक डेटा के साथ सिर्फ सॉर्ट कुंजी, और मर्जेसर्ट एक ऐसा सॉर्ट है। लेकिन आदिम प्रकार की स्थिरता के लिए न केवल अप्रासंगिक है। यह अर्थहीन है।

स्रोत: जानकारी


0

जावा की Arrays.sortविधि क्विकसॉर्ट, इंसर्शन सॉर्ट और मर्जोर्ट का उपयोग करती है। यहां तक ​​कि OpenJDK कोड में कार्यान्वित एक एकल और दोहरी धुरी क्विकॉर्ट दोनों भी है। सबसे तेज़ सॉर्टिंग एल्गोरिथ्म परिस्थितियों और विजेताओं पर निर्भर करता है: छोटे सरणियों के लिए सम्मिलन क्रमांक (47 वर्तमान में चुना गया), ज्यादातर सॉर्ट किए गए सरणियों के लिए विलय, और शेष सरणियों के लिए क्विकसर्ट इसलिए जावा के Array.sort () सबसे अच्छा एल्गोरिथ्म चुनने की कोशिश करता है उन मानदंडों के आधार पर आवेदन करें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.