Quicksort: धुरी का चयन

वोट
94

जब quicksort को लागू करने, चीजें आप क्या करना है में से एक एक धुरी का चयन करने के लिए है। लेकिन जब मैं नीचे एक तरह स्यूडोकोड को देखो, यह स्पष्ट नहीं है कि कैसे मैं धुरी चयन करना चाहिए। सूची के पहले तत्व? कुछ और?

 function quicksort(array)
     var list less, greater
     if length(array) ≤ 1  
         return array  
     select and remove a pivot value pivot from array
     for each x in array
         if x ≤ pivot then append x to less
         else append x to greater
     return concatenate(quicksort(less), pivot, quicksort(greater))

किसी की मदद कर सकते हैं मुझे एक धुरी के चयन की अवधारणा को समझ और चाहे या नहीं विभिन्न परिदृश्यों विभिन्न रणनीतियों के लिए कहते हैं।

02/10/2008 को 20:37
का स्रोत उपयोगकर्ता
अन्य भाषाओं में...                            


13 जवाब

वोट
72

एक यादृच्छिक धुरी का चयन मौका है कि आप बुरी से बुरी हालत O (n का सामना करेंगे को कम करता है 2 ) प्रदर्शन (हमेशा पहले या अंतिम लगभग हल या लगभग-रिवर्स अनुसार क्रमबद्ध डेटा के लिए बुरी से बुरी हालत प्रदर्शन का कारण होगा चुनने)। मध्य तत्व का चयन भी अधिकांश मामलों में स्वीकार्य होगा।

इसके अलावा, अगर आप स्वयं इस कार्यान्वित कर रहे हैं, उस में जगह काम एल्गोरिथ्म के संस्करणों (यानी दो नई सूचियों बनाने के बाद उन्हें श्रृंखलाबद्ध के बिना) कर रहे हैं।

02/10/2008 को 20:41
का स्रोत उपयोगकर्ता

वोट
47

यह अपनी आवश्यकताओं पर निर्भर करता है। यादृच्छिक पर एक धुरी का चयन यह मुश्किल एक डेटा सेट कि हे (एन ^ 2) प्रदर्शन उत्पन्न करता है बनाने के लिए बनाता है। 'माध्य के- तीन' (प्रथम, अंतिम, मध्य) भी समस्याओं से बचने का एक तरीका है। तुलना, हालांकि के सापेक्ष प्रदर्शन से सावधान रहें; अपने तुलना महंगी हैं, तो MO3 यादृच्छिक पर (एक धुरी मान) को चुनने की तुलना में अधिक की तुलना करता है। डाटाबेस रिकॉर्ड की तुलना करने के महंगा हो सकता है।


अपडेट: जवाब में टिप्पणी खींच।

mdkess माँगे:

'3 की माध्यिका' पहली बार पिछले बीच नहीं है। तीन यादृच्छिक अनुक्रमित चुनें, और इस के मध्य का मान लेते हैं। अगर ऐसा है, सबसे ज्यादा मामले डेटा काफी आसानी से उत्पन्न किया जा सकता - पूरे मुद्दे सुनिश्चित करें कि pivots के अपनी पसंद निर्धारित करने योग्य नहीं है बनाने के लिए है।

जो करने के लिए मैं ने जवाब दिया:

  • माध्य-के-तीन विभाजन के साथ होरे की खोज एल्गोरिथ्म के विश्लेषण (1997) पी Kirschenhofer, एच Prodinger द्वारा, सी मार्टिनेज अपने विवाद का समर्थन करता है (कि 'माध्यिका के- तीन' तीन यादृच्छिक आइटम है)।

  • वहाँ एक लेख में बताया गया है है portal.acm.org हन्नू Erkiö द्वारा के बारे में 'सबसे बुरे मामले क्रमपरिवर्तन के लिए माध्य के- तीन quicksort' है कि, कंप्यूटर जर्नल, वॉल्यूम 27, नहीं 3, 1984 [अपडेट में प्रकाशित 2012-02- 26: के लिए पाठ मिल गया लेख । धारा 2 'एल्गोरिथ्म' शुरू होता है: ' का एक [एल: आर], पहले मध्य और अंतिम तत्व की औसत का उपयोग करके काफी बराबर आकार के कुछ हिस्सों में, कुशल विभाजन सबसे व्यावहारिक स्थितियों में प्राप्त किया जा सकता। 'इस प्रकार, यह पहले मध्यम पिछले MO3 दृष्टिकोण पर चर्चा कर रहा है।]

  • एक और छोटा सा लेख है कि दिलचस्प है एमडी मेक्लोरी, के द्वारा होता है "quicksort के लिए एक खूनी विरोधी" , सॉफ्टवेयर अभ्यास और अनुभव, वॉल्यूम में प्रकाशित। 29 (0), 1-4 (0 1999)। यह कैसे लगभग किसी भी quicksort quadratically व्यवहार करते हैं बनाने के लिए बताते हैं।

  • एटी एंड टी बेल लेबोरेटरीज टेक जर्नल, अक्टूबर 1984 में कहा गया है "होरे सुझाव कई बेतरतीब ढंग से चुना लाइनों की औसत के आसपास विभाजन। Sedgewick" एक कार्य नियमित क्रमबद्ध का निर्माण में सिद्धांत और व्यवहार "[...] के पहले [मंझला चुनने की सिफारिश की। ..] पिछले [...] और मध्य "। यह बताता है कि 'माध्यिका के- तीन' के लिए दोनों तकनीक साहित्य में जाना जाता है। (अपडेट 2014-11-23: लेख पर उपलब्ध हो गया लगता है आईईईई एक्सप्लोर या से विले - अगर आप सदस्यता नहीं है या एक शुल्क का भुगतान करने के लिए तैयार कर रहे हैं।)

  • 'एक क्रमबद्ध समारोह इंजीनियरिंग' जीएल बेंटले और एमडी मेक्लोरी द्वारा, सॉफ्टवेयर प्रैक्टिस और अनुभव, खंड 23 (11), नवम्बर 1993 में प्रकाशित, मुद्दों की एक व्यापक चर्चा में चला जाता है, और वे इस आधार पर एक अनुकूली विभाजन एल्गोरिथ्म चुना डेटा सेट के आकार। वहाँ विभिन्न तरीकों के लिए व्यापार गत की चर्चा का एक बहुत कुछ है।

  • 'माध्यिका के- तीन' के लिए Google खोज आगे ट्रैकिंग के लिए बहुत अच्छी तरह से काम करता है।

जानकारी के लिए धन्यवाद; मैं केवल नियतात्मक 'माध्यिका के- तीन' से पहले का सामना करना पड़ा था।

02/10/2008 को 20:42
का स्रोत उपयोगकर्ता

वोट
1

आप एक यादृच्छिक सुलभ संग्रह (एक सरणी की तरह) छँटाई रहे हैं, तो यह शारीरिक बीच आइटम लेने के लिए सबसे अच्छा सामान्य है। इसके साथ ही यदि सरणी है सब तैयार हल कर (या लगभग क्रमबद्ध), दो विभाजन के पास भी हो जाएगा, और आप सबसे अच्छा गति मिल जाएगा।

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

हालांकि, एक लिंक्ड सूची के लिए, पहले के अलावा कुछ भी उठा, बस मामले को बदतर कर देगा। यह एक सूचीबद्ध-सूची में मध्यम आइटम लेने, आप प्रत्येक विभाजन कदम पर यह से निकलने के लिए होगा - एक हे जोड़ने (एन / 2) जो logn बार कुल समय हे बनाने में किया जाता है आपरेशन (1.5 एन * लोग इन एन) आम तौर पर हम तो हम के माध्यम से सभी तरह से कदम उनकी गणना, तो आधे रास्ते के माध्यम से कदम बीच खोजने के लिए है, तो एक के माध्यम से कदम होगा नहीं है - और कि अगर हम जानते हैं कि कैसे लंबी सूची है इससे पहले कि हम शुरू है तीसरी बार वास्तविक विभाजन करने के लिए: हे (2.5N * लोग इन एन)

02/10/2008 को 20:42
का स्रोत उपयोगकर्ता

वोट
1

यह पूरी तरह से कैसे अपने डेटा के साथ शुरू करने के लिए क्रमबद्ध किया जाता है पर निर्भर है। यदि आपको लगता है यह छद्म यादृच्छिक हो जाएगा तो आपका सर्वश्रेष्ठ दांव या तो एक यादृच्छिक चयन लेने या मध्यम चयन करने के लिए है।

02/10/2008 को 20:46
का स्रोत उपयोगकर्ता

वोट
16

हे, मैं सिर्फ इस वर्ग सिखाया।

वहाँ कई विकल्प हैं।
सरल: श्रृंखला के पहले या अंतिम तत्व उठाओ। (आंशिक रूप से क्रमबद्ध इनपुट पर बुरा) बेहतर: सीमा के बीच में आइटम चुनें। (आंशिक रूप से क्रमबद्ध इनपुट पर बेहतर)

हालांकि, किसी भी मनमाने ढंग से तत्व उठा खराब आकार 1 और एन -1 के दो सरणियों में आकार की सरणी n विभाजन का खतरा चलाता है। आपको लगता है कि अक्सर पर्याप्त करते हैं, आपका quicksort (एन ^ 2) हे होने के जोखिम को चलाता है।

एक सुधार मैंने देखा है मंझला (प्रथम, अंतिम, मध्य) लेने है, सबसे खराब स्थिति में, यह अभी भी O (n ^ 2) पर जा सकते हैं, लेकिन संभवतया, यह एक दुर्लभ मामला है।

सबसे डेटा के लिए, पहले उठा या पिछले पर्याप्त है। लेकिन, यदि आप पाते हैं कि आप सबसे ज्यादा मामले परिदृश्यों अक्सर (आंशिक रूप से हल कर इनपुट) में चल रहे हैं, पहला विकल्प केंद्रीय मूल्य (जो आंशिक रूप से क्रमबद्ध डेटा के लिए सांख्यिकीय रूप अच्छा धुरी है) लेने के लिए होगा।

आप अभी भी समस्या में चला रहे हैं, तो मंझला तरीका अपनाते हैं।

02/10/2008 को 20:46
का स्रोत उपयोगकर्ता

वोट
8

कभी कभी एक निश्चित धुरी चुनें - यह अपने एल्गोरिथ्म के सबसे ज्यादा मामले O (n ^ 2) क्रम, जो सिर्फ मुसीबत के लिए पूछ रहा है फायदा उठाने के लिए हमला किया जा सकता है। Quicksort के सबसे ज्यादा मामले क्रम तब होता है जब 1 तत्व के एक सरणी, और n-1 तत्वों में से एक सरणी में परिणाम विभाजन। आप अपने विभाजन के रूप में पहला तत्व चुनें मान लीजिए। किसी को अपने एल्गोरिथ्म के लिए एक सरणी घटते क्रम में है कि फ़ीड तो अपना पहला धुरी, सबसे बड़ी होगी तो सरणी में बाकी सब यह के बाईं ओर चले जाएंगे। फिर जब आप recurse, पहला तत्व फिर से सबसे बड़ी है, इसलिए एक बार फिर आप इसे के बाईं ओर सब कुछ डाल दिया, और इतने पर।

एक बेहतर तकनीक मंझला-ऑफ-द 3 विधि है, जहां आप यादृच्छिक पर तीन तत्वों चुनें, और बीच चुनना है। आप और पता है कि तत्व यह है कि आपके द्वारा चुने गए पहले या अंतिम, लेकिन यह भी, केंद्रीय सीमा प्रमेय द्वारा, मध्य तत्व का वितरण सामान्य हो जाएगा, जिसका मतलब है कि आप मध्य की ओर चला जाएगा नहीं होगा (इसलिए , एन एलजी n समय)।

यदि आप पूरी तरह एल्गोरिथ्म के लिए ओ (nlgn) क्रम की गारंटी चाहते हैं, एक सरणी की औसत पाने के लिए कॉलम के- 5 विधि हे (एन) समय में चलता है, जिसका अर्थ है कि सबसे खराब स्थिति में quicksort के लिए पुनरावृत्ति समीकरण होगा जा टी (एन) = हे (एन) (मंझला खोजने के) + O (एन) (विभाजन) + 2T (एन / 2) (बाएँ और दाएँ recurse।) मास्टर प्रमेय रूप से, यह O (n एलजी एन) है । हालांकि, लगातार कारक विशाल हो जाएगा, और अगर सबसे ज्यादा मामले प्रदर्शन अपनी प्राथमिक चिंता का विषय है, तरह के बजाय किसी मर्ज का उपयोग है, जो केवल एक छोटा सा औसतन quicksort की तुलना में धीमी है, और गारंटी देता हे (nlgn) समय (और बहुत तेजी से हो जाएगा इस लंगड़ा मंझला quicksort की तुलना में)।

Medians एल्गोरिथ्म की माध्यिका का स्पष्टीकरण

25/10/2008 को 22:50
का स्रोत उपयोगकर्ता

वोट
5

कोशिश न करें और बहुत चालाक हो और पिवट रणनीतियों गठबंधन। आप बीच में, पहली बार पिछले और एक यादृच्छिक सूचकांक की औसत उठा द्वारा यादृच्छिक धुरी के साथ 3 की औसत संयुक्त है, तो आप अभी भी वितरण जो 3 से द्विघात (इसलिए इसकी वास्तव में बदतर की औसत भेजने वाले कई की चपेट में हो जाएगा सादा यादृच्छिक धुरी)

उदाहरण के लिए एक पाइप ऑर्गन वितरण (1,2,3 ... N / 2..3,2,1) पहली और आखिरी दोनों 1 हो जाएगा और यादृच्छिक सूचकांक 1 की तुलना में कुछ संख्या अधिक हो जाएगा, मंझला लेने 1 देता है ( प्रथम या अंतिम) और आप एक extermely असंतुलित विभाजन मिलता है।

26/10/2008 को 04:54
का स्रोत उपयोगकर्ता

वोट
1

यह आसान है तीन वर्गों ऐसा करने में quicksort तोड़ने के लिए

  1. एक्सचेंज या स्वैप डेटा तत्व समारोह
  2. विभाजन समारोह
  3. विभाजन का संसाधन

यह केवल थोड़ा एक लंबे समारोह की तुलना में अधिक inefficent है, लेकिन बहुत कुछ समझने के लिए आसान है।

कोड इस प्रकार है:

/* This selects what the data type in the array to be sorted is */

#define DATATYPE long

/* This is the swap function .. your job is to swap data in x & y .. how depends on
data type .. the example works for normal numerical data types .. like long I chose
above */

void swap (DATATYPE *x, DATATYPE *y){  
  DATATYPE Temp;

  Temp = *x;        // Hold current x value
  *x = *y;          // Transfer y to x
  *y = Temp;        // Set y to the held old x value
};


/* This is the partition code */

int partition (DATATYPE list[], int l, int h){

  int i;
  int p;          // pivot element index
  int firsthigh;  // divider position for pivot element

  // Random pivot example shown for median   p = (l+h)/2 would be used
  p = l + (short)(rand() % (int)(h - l + 1)); // Random partition point

  swap(&list[p], &list[h]);                   // Swap the values
  firsthigh = l;                                  // Hold first high value
  for (i = l; i < h; i++)
    if(list[i] < list[h]) {                 // Value at i is less than h
      swap(&list[i], &list[firsthigh]);   // So swap the value
      firsthigh++;                        // Incement first high
    }
  swap(&list[h], &list[firsthigh]);           // Swap h and first high values
  return(firsthigh);                          // Return first high
};



/* Finally the body sort */

void quicksort(DATATYPE list[], int l, int h){

  int p;                                      // index of partition 
  if ((h - l) > 0) {
    p = partition(list, l, h);              // Partition list 
    quicksort(list, l, p - 1);        // Sort lower partion
    quicksort(list, p + 1, h);              // Sort upper partition
  };
};
10/03/2011 को 03:19
का स्रोत उपयोगकर्ता

वोट
0

आदर्श रूप में धुरी पूरे सरणी में मध्यम मान होना चाहिए। यह सबसे खराब स्थिति प्रदर्शन होने की संभावना कम हो जाएगा।

17/04/2013 को 15:57
का स्रोत उपयोगकर्ता

वोट
-1

वास्तव में एक अनुकूलित कार्यान्वयन में, धुरी को चुनने के लिए विधि सरणी आकार पर निर्भर होना चाहिए - एक बड़े सरणी के लिए, यह बंद का भुगतान करती है एक अच्छा धुरी चुनने अधिक समय बिताना। एक पूर्ण विश्लेषण कर के बिना, मुझे लगता है कि होगा "हे के बीच (लॉग (एन)) तत्वों" एक अच्छी शुरुआत है, और यह किसी भी अतिरिक्त स्मृति की आवश्यकता नहीं की अतिरिक्त बोनस दिया गया है: बड़ा विभाजन और in- पर पूंछ-कॉल का उपयोग करना जगह विभाजन, हम एक ही हे (लॉग (एन)) अतिरिक्त स्मृति एल्गोरिथ्म के लगभग हर मंच का उपयोग करें।

08/10/2013 को 20:50
का स्रोत उपयोगकर्ता

वोट
0

त्वरित तरह की जटिलता धुरी मूल्य का चयन के साथ बहुत भिन्न। उदाहरण के लिए आप हमेशा एक धुरी के रूप में पहला तत्व चुनते हैं, कलन विधि की जटिलता हो जाता है के रूप में सबसे खराब हे के रूप में (एन ^ 2)। यहाँ एक स्मार्ट विधि धुरी तत्व-1. पहले, मध्य, पिछले सरणी के तत्व का चयन चयन करने के लिए है। 2. इन तीन संख्याओं की तुलना और संख्या जो एक से अधिक और अन्य यानी मंझला से छोटी है पाते हैं। 3. धुरी तत्व के रूप में इस तत्व बनाते हैं।

इस विधि द्वारा धुरी चुनने लगभग दो छमाही में सरणी विभाजन और इसलिए जटिलता ओ (nlog (एन)) को कम करता है।

05/12/2013 को 06:05
का स्रोत उपयोगकर्ता

वोट
0

औसत पर, 3 की माध्यिका छोटे n के लिए अच्छा है। 5 की माध्यिका थोड़ा बड़ा n के लिए बेहतर है। ninther है, जो "तीन के तीन माध्यिकाओं की औसत" है भी बहुत बड़ी n के लिए बेहतर है।

उच्च आप बेहतर आप n बढ़ने के साथ मिल नमूने के साथ जाना है, लेकिन सुधार नाटकीय रूप से धीमा के रूप में आप नमूने वृद्धि हुई है। और तुम नमूने और नमूने छँटाई की भूमि के ऊपर उठाना।

19/10/2016 को 10:04
का स्रोत उपयोगकर्ता

वोट
0

मैं बीच सूचकांक उपयोग करने की अनुशंसा, के रूप में यह आसानी से गणना की जा सकती।

आप गोलाई (array.length / 2) द्वारा यह गणना कर सकते हैं।

09/08/2017 को 01:29
का स्रोत उपयोगकर्ता

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more