डिवाइड और कंवर्ट एल्गोरिदम - दो से अधिक भागों में विभाजित क्यों नहीं?


33

क्विकॉर्ट्स और मर्जर्ट जैसे एल्गोरिदम को विभाजित और जीतना, इनपुट आमतौर पर (कम से कम परिचयात्मक ग्रंथों में) दो में विभाजित होता है , और दो छोटे डेटा सेट फिर से पुनरावृत्ति से निपटा जाता है। यह मेरे लिए समझ में आता है कि यह एक समस्या को हल करने के लिए तेजी से बनाता है अगर दो हिस्सों में पूरे डेटा सेट के साथ काम करने का आधे से भी कम समय लगता है। लेकिन डेटा सेट को तीन भागों में विभाजित क्यों नहीं किया जाता है? चार? n ?

मुझे लगता है कि डेटा को कई में विभाजित करने के काम में, कई उप सेट इसके लायक नहीं हैं, लेकिन मुझे यह देखने के लिए अंतर्ज्ञान की कमी है कि किसी को दो उप सेटों पर रोकना चाहिए।

मैंने 3-वे क्विकसॉर्ट के कई संदर्भ भी देखे हैं। यह तेज कब है? व्यवहार में क्या प्रयोग किया जाता है?


क्विकॉर्ट के समान एक एल्गोरिथ्म बनाने की कोशिश करें जो एक सरणी को तीन भागों में विभाजित करता है।
gnasher729

जवाबों:


49

यह मेरे लिए समझ में आता है कि यह एक समस्या को हल करने के लिए तेजी से बनाता है अगर दो हिस्सों में पूरे डेटा सेट के साथ काम करने का आधे से भी कम समय लगता है।

यह डिवाइड-एंड-कॉनकोर एल्गोरिदम का सार नहीं है। आमतौर पर मुद्दा यह है कि एल्गोरिदम "पूरे डेटा सेट के साथ सौदा नहीं कर सकता है"। इसके बजाय, इसे उन टुकड़ों में विभाजित किया जाता है जो हल करने के लिए तुच्छ होते हैं (जैसे दो संख्याओं को छांटना), फिर उन्हें तुच्छ रूप से हल किया जाता है और परिणाम एक तरह से पुनर्संयोजित होते हैं जो पूर्ण डेटा सेट के लिए एक समाधान देता है।

लेकिन डेटा सेट को तीन भागों में विभाजित क्यों नहीं किया जाता है? चार? n?

मुख्य रूप से क्योंकि यह दो से अधिक भागों में विभाजित होता है और दो से अधिक परिणाम पुनर्संयोजित करता है जिसके परिणामस्वरूप अधिक जटिल कार्यान्वयन होता है लेकिन एल्गोरिथ्म की मूलभूत (बिग ओ) विशेषता को नहीं बदलता है - अंतर एक स्थिर कारक है, और इसके परिणामस्वरूप मंदी हो सकती है यदि 2 से अधिक सबसेट का विभाजन और पुनर्संयोजन अतिरिक्त उपरि बनाता है।

उदाहरण के लिए, यदि आप 3-वे मर्ज सॉर्ट करते हैं, तो पुनर्संयोजन चरण में अब आपको हर तत्व के लिए 3 तत्वों में से सबसे बड़ा खोजना होगा, जिसके लिए 1 के बजाय 2 तुलनाओं की आवश्यकता होती है, इसलिए आप समग्र रूप से दो बार तुलना करेंगे। । बदले में, आप ln (2) / ln (3) == 0.63 के एक कारक द्वारा पुनरावृत्ति की गहराई को कम करते हैं, इसलिए आपके पास 37% कम स्वैप हैं, लेकिन 2 * 0.63 == 26% अधिक तुलना (और मेमोरी एक्सेस)। चाहे वह अच्छा हो या बुरा यह निर्भर करता है कि आपके हार्डवेयर में कौन अधिक महंगा है।

मैंने 3-वे क्विकसॉर्ट के कई संदर्भ भी देखे हैं। यह तेज कब है?

जाहिरा तौर पर क्विकॉर्ट के दोहरे पिवट वेरिएंट को समान संख्या में तुलना की आवश्यकता साबित हो सकती है, लेकिन औसतन 20% कम स्वैप, इसलिए यह शुद्ध लाभ है।

व्यवहार में क्या प्रयोग किया जाता है?

इन दिनों शायद ही कोई अपने खुद के छांटने वाले एल्गोरिदम को अब प्रोग्राम करता है; वे एक पुस्तकालय द्वारा प्रदत्त एक का उपयोग करते हैं। उदाहरण के लिए, जावा 7 एपीआई वास्तव में डुअल-पिवट क्विकर का उपयोग करता है।

जो लोग वास्तव में किसी कारण के लिए अपने स्वयं के सॉर्टिंग एल्गोरिदम को प्रोग्राम करते हैं, वे सरल 2-वे वेरिएंट से चिपके रहेंगे, क्योंकि त्रुटियों की कम संभावना ज्यादातर समय 20% बेहतर प्रदर्शन करती है। याद रखें: अब तक सबसे महत्वपूर्ण प्रदर्शन सुधार है जब कोड "काम नहीं कर रहा" से "काम करने" तक जाता है।


1
छोटा नोट: जावा 7 प्राइमेटरी को सॉर्ट करते समय केवल ड्यूल-पिवट एस्कॉर्ट का उपयोग करता है । ऑब्जेक्ट्स को सॉर्ट करने के लिए यह Timsort का उपयोग करता है।
बाकुरू

1
+1 के लिए "इन दिनों शायद ही कोई अपने स्वयं के छांटने वाले एल्गोरिदम को अब प्रोग्राम करता है" और (इससे भी महत्वपूर्ण) "याद रखें: अब तक का सबसे महत्वपूर्ण प्रदर्शन सुधार है जब कोड" काम नहीं करने "से" काम करने "तक जाता है।" हालांकि, मैं यह जानना चाहूंगा कि क्या उपरि अभी भी तुच्छ है अगर, उदाहरण के लिए, एक डेटा को कई, कई हिस्सों में विभाजित करता है। जैसा कि ऐसा होता है, वैसे ही अन्य लोग भी हैं: bealto.com/gpu-sorting_intro.html stackoverflow.com/questions/1415679/… devgurus.amd.com/thread/157159
एंड्रयूजॉनसन 25

मैं थोड़ा धीमा हूं। क्या कोई समझा सकता है कि यह 2 * 0.69 अधिक तुलना क्यों करता है? यकीन नहीं आता कि 0.69 कहां से आया।
जीबफेस

@jeebface ओह, यह एक टाइपो (अब तय किया गया) था। यह 0.63 (पुनरावृत्ति की गहराई में कमी) है, फिर 26% अधिक का परिणाम भी काम करता है।
माइकल बॉर्गवर्ड

30

अस्वाभाविक रूप से बोलते हुए, इससे कोई फर्क नहीं पड़ता। उदाहरण के लिए, द्विआधारी खोज लगभग लॉग 2  एन तुलना करता है, और टर्नरी खोज लगभग लॉग 3  एन तुलना करता है। आप अपने लघुगणक जानते हैं, तो आप उस लॉग पता एक  एक्स = लॉग  एक्स / लॉग  एक है, तो द्विआधारी खोज केवल 1 के बारे में बनाता है / log 3 टर्नरी खोज के रूप में कई तुलना के रूप में 2 as 1.5 गुना। यह भी कारण है कि कोई भी कभी भी बड़े ओह संकेतन में लघुगणक के आधार को निर्दिष्ट नहीं करता है: यह हमेशा एक निरंतर आधार है जो किसी दिए गए आधार में लघुगणक से दूर है, कोई फर्क नहीं पड़ता कि आधार वास्तविक है। इसलिए समस्या को अधिक उप-भागों में विभाजित करने से समय की जटिलता में सुधार नहीं होता है और व्यावहारिक रूप से अधिक जटिल तर्क को रेखांकित करने के लिए पर्याप्त नहीं है। वास्तव में, यह जटिलता व्यावहारिक प्रदर्शन को नकारात्मक रूप से प्रभावित कर सकती है, कैश का दबाव बढ़ा सकती है या सूक्ष्म अनुकूलन को कम कर सकती है।

दूसरी ओर, कुछ ट्री-ईश डेटा संरचना उच्च ब्रांचिंग कारक का उपयोग करती हैं (3 से बड़ा, अक्सर 32 या अधिक), हालांकि आमतौर पर अन्य कारणों से। यह मेमोरी पदानुक्रम के उपयोग में सुधार करता है: रैम में संग्रहीत डेटा संरचनाएं कैश का बेहतर उपयोग करती हैं, डिस्क पर संग्रहीत डेटा संरचनाओं को कम से कम एचडीडी-> रैम की आवश्यकता होती है।


हाँ, बाइनरी ट्री संरचना की तुलना में अधिक के एक विशिष्ट अनुप्रयोग के लिए ऑक्ट्री को देखें।
डेक्सिक्स

@daaxix btree शायद अधिक सामान्य है।
जूल्स

4

ऐसे खोज / सॉर्ट एल्गोरिदम हैं जो दो से नहीं, बल्कि एन से उप-विभाजित होते हैं।

एक साधारण उदाहरण हैश कोडिंग द्वारा खोजा जाता है, जिसमें O (1) समय लगता है।

यदि हैश फ़ंक्शन क्रम-संरक्षण है, तो इसका उपयोग O (N) सॉर्ट एल्गोरिथ्म बनाने के लिए किया जा सकता है। (आप किसी भी प्रकार के एल्गोरिथ्म के बारे में सोच सकते हैं जैसे कि एन खोज करता है कि परिणाम में कोई संख्या कहां जानी चाहिए।)

मूल मुद्दा यह है, जब कोई प्रोग्राम कुछ आंकड़ों की जांच करता है और फिर कुछ निम्नलिखित राज्यों में प्रवेश करता है, तो निम्नलिखित कितने राज्य हैं, और उनकी समीपता कितनी है?

जब कोई कंप्यूटर दो नंबरों की तुलना करता है, तो कहना, और फिर या तो कूदता है या नहीं, यदि दोनों पथ समान रूप से होने की संभावना है, तो प्रोग्राम काउंटर प्रत्येक पथ पर "एक और अधिक जानकारी" जानता है, इसलिए औसतन यह "सीखा" है बिट। यदि किसी समस्या के लिए एम बिट्स की आवश्यकता होती है, तो द्विआधारी निर्णयों का उपयोग करके इसे एम निर्णयों से कम में उत्तर नहीं मिल सकता है। इसलिए, उदाहरण के लिए, आकार 1024 की एक क्रमबद्ध तालिका में एक संख्या को देखते हुए कम से कम 10 बाइनरी निर्णय नहीं किए जा सकते हैं, यदि केवल इसलिए कि किसी भी कम के पास पर्याप्त परिणाम नहीं होंगे, लेकिन यह निश्चित रूप से अधिक में किया जा सकता है।

जब कोई कंप्यूटर एक नंबर लेता है और इसे एक इंडेक्स में बदल देता है, तो यह एरे में तत्वों की संख्या के आधार 2 को लॉग करने के लिए "सीखता है", और यह इसे निरंतर समय में करता है। उदाहरण के लिए, यदि 1024 प्रविष्टियों की जंप टेबल है, तो कमोबेश सभी की समान रूप से संभावना है, तो उस तालिका के माध्यम से "10 बिट" सीखता है। यह हैश कोडिंग के पीछे मूल चाल है। इसका एक सॉर्टिंग उदाहरण है कि आप कार्ड के डेक को कैसे सॉर्ट कर सकते हैं। 52 डिब्बे हों, प्रत्येक कार्ड के लिए एक। प्रत्येक कार्ड को उसके बिन में प्रवाहित करें, और फिर उन सभी को स्कूप करें। कोई उप-विभाजन की आवश्यकता नहीं है।


1

चूंकि यह सामान्य विभाजन और जीत के बारे में एक सवाल है, न कि केवल छंटाई के रूप में, मुझे आश्चर्य है कि कोई भी मास्टर प्रमेय नहीं लाया है

संक्षेप में, डिवाइड और विजयी एल्गोरिदम के चलने का समय दो प्रतिसाद बलों द्वारा निर्धारित किया जाता है: आपको बड़ी समस्याओं को छोटी समस्याओं में बदलने से, और अधिक समस्याओं को हल करने में आपके द्वारा भुगतान की जाने वाली कीमत। एल्गोरिथ्म के विवरण के आधार पर यह समस्या को दो टुकड़ों में विभाजित करने के लिए भुगतान कर सकता है या नहीं भी कर सकता है। यदि आप प्रत्येक चरण में समान संख्या में उप-विभाजनों में विभाजित होते हैं, और आप प्रत्येक चरण में परिणामों के संयोजन की समय जटिलता जानते हैं, तो मास्टर प्रमेय आपको समग्र एल्गोरिथ्म की समय जटिलता बताएगा।

Karatsuba गुणन के लिए एल्गोरिथ्म हे की एक चलने का समय (3 n ^ log_2 3), जिसमें साधारण गुणा एल्गोरिथ्म के लिए (एन ^ 2) हे धड़कता है (एन है अंकों की संख्या प्राप्त करने के लिए 3-ओर फूट डालो और जीत का उपयोग करता है संख्या)।


मास्टर प्रमेय में, आपके द्वारा बनाई जाने वाली उप-समस्याओं की संख्या एकमात्र कारक नहीं है। करत्सुबा और उसके चचेरे भाई स्ट्रैसन में, सुधार वास्तव में कुछ उप-समस्याओं के स्मार्ट मर्जिंग समाधान से आता है, इसलिए आप उप-समस्याओं पर पुनरावर्ती कॉल की संख्या को कम करते हैं। संक्षेप में, bमास्टर प्रमेय में ऊपर aजाने के लिए आपको आगे के विभाजन में सुधार करने की आवश्यकता होती है ।
सूचित 11

-4

अपने द्विआधारी प्रकृति के कारण एक कंप्यूटर 2 में चीजों को विभाजित करने में बहुत कुशल है और 3 में बहुत अधिक नहीं है। आपको 3 में 2 पहले में विभाजित करके एक विभाजन मिलता है और फिर 2 में से एक हिस्से को फिर से विभाजित करें। इसलिए यदि आपको विभाजित करने की आवश्यकता है 2 से अपने 3 डिवीजन को पाने के लिए, आप 2 में भी विभाजित कर सकते हैं।

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