एक ढेर का निर्माण ओ (एन) समय जटिलता कैसे हो सकता है?


494

क्या कोई यह समझाने में मदद कर सकता है कि ढेर का निर्माण ओ (एन) जटिलता कैसे हो सकता है?

किसी आइटम को एक ढेर O(log n)में सम्मिलित करना है , और डालने को बार-बार n / 2 बार दोहराया जाता है (शेष पत्ते हैं, और ढेर संपत्ति का उल्लंघन नहीं कर सकते हैं)। तो, इसका मतलब है कि जटिलता होनी चाहिए O(n log n), मुझे लगता है।

दूसरे शब्दों में, प्रत्येक आइटम के लिए हम "हीप्लीज" करते हैं, इसमें ढेर के लिए प्रत्येक स्तर के लिए एक बार नीचे फ़िल्टर करने की क्षमता है (जो कि लॉग एन स्तर है)।

मैं क्या खो रहा हूँ?


ढेर का "निर्माण" करने का क्या मतलब है?
mfrankli

जब तक आप एक ढेर में होंगे, एक अनियोजित सरणी लें और शीर्ष आधे तत्वों में से प्रत्येक को तब तक फ़िल्टर करें जब तक कि यह ढेर के नियमों के अनुरूप न हो जाए
GBa

2
केवल एक चीज जो मुझे मिल सकी वह थी इस लिंक: बिल्डप्ले की जटिलता Θ (n lg n) - n प्रति कॉल n (lg n) की कीमत पर Heapify को प्रतीत होती है, लेकिन इस परिणाम को Θ (n) में सुधारा जा सकता है। cs.txstate.edu/~ch04/webtest/teaching/courses/5329/lectures/…
GBa

2
@GB इस वीडियो को MIT से देखें: वह अच्छी तरह से समझाता है कि हमें O (n) कैसे मिलता है, गणित के एक lil बिट के साथ youtube.com/watch?v=B7hVxCmfPtM
CodeShadow

2
स्पष्टीकरण के सीधे लिंक @CodeShadow का उल्लेख किया गया: youtu.be/B7hVxCmfPtM?t=41m21s
sha1

जवाबों:


435

मुझे लगता है कि इस विषय में कई प्रश्न दफन हैं:

  • आप buildHeapइसे कैसे लागू करते हैं ताकि यह O (n) समय में चले ?
  • जब आप सही तरीके से लागू होते हैं तो ओ (एन) समय buildHeapमें कैसे चलते हैं ?
  • क्यों एक ही तर्क काम ढेर प्रकार में चलाने के लिए नहीं है कि करने के लिए हे (एन) समय के बजाय O (n n लॉग इन करें) ?

आप buildHeapइसे कैसे लागू करते हैं ताकि यह O (n) समय में चले ?

अक्सर, इन सवालों के जवाब के बीच siftUpऔर अंतर पर ध्यान केंद्रित करते हैं siftDown। के बीच सही चुनाव करना siftUpऔर ओ (एन) प्रदर्शन siftDownप्राप्त करने के लिए महत्वपूर्ण है , लेकिन किसी के बीच और सामान्य रूप से अंतर को समझने में मदद करने के लिए कुछ भी नहीं करता है । वास्तव में, दोनों का उचित कार्यान्वयन और केवल उपयोग करेगा । आपरेशन केवल एक मौजूदा ढेर में आवेषण प्रदर्शन करने की जरूरत है, तो यह एक द्विआधारी ढेर का उपयोग कर, उदाहरण के लिए एक प्राथमिकता कतार लागू करने के लिए इस्तेमाल किया जाएगा।buildHeapbuildHeapheapSortbuildHeapheapSortsiftDownsiftUp

मैंने यह वर्णन करने के लिए लिखा है कि अधिकतम ढेर कैसे काम करता है। यह आमतौर पर हीप सॉर्ट के लिए या प्राथमिकता कतार के लिए उपयोग किया जाने वाला हीप का प्रकार है जहां उच्च मान उच्च प्राथमिकता का संकेत देते हैं। एक मिनट का ढेर भी उपयोगी है; उदाहरण के लिए, आरोही क्रम में पूर्णांक कुंजियों वाली वस्तुओं को प्राप्त करते समय या वर्णमाला क्रम में तार। सिद्धांत बिल्कुल समान हैं; बस सॉर्ट क्रम को स्विच करें।

ढेर संपत्ति निर्दिष्ट करता है कि एक द्विआधारी ढेर में प्रत्येक नोड में कम से कम अपने बच्चों की दोनों के रूप में बड़े रूप में किया जाना चाहिए। विशेष रूप से, इसका तात्पर्य है कि ढेर में सबसे बड़ी वस्तु जड़ में है। शिफ्टिंग और शिफ्टिंग अनिवार्य रूप से विपरीत दिशाओं में एक ही ऑपरेशन है: एक आक्रामक नोड को स्थानांतरित करें जब तक कि यह ढेर संपत्ति को संतुष्ट न करे:

  • siftDown एक नोड स्वैप करता है जो अपने सबसे बड़े बच्चे के साथ बहुत छोटा है (इस तरह इसे नीचे ले जाता है) जब तक कि यह कम से कम दोनों नोड्स के रूप में बड़ा न हो।
  • siftUp एक नोड को स्वैप करता है जो अपने माता-पिता के साथ बहुत बड़ा होता है (इस तरह इसे ऊपर ले जाता है) जब तक कि यह ऊपर के नोड से बड़ा न हो।

के लिए आवश्यक संचालन की संख्या siftDownऔर siftUpदूरी के अनुपात में है जो नोड को स्थानांतरित करना पड़ सकता है। के लिए siftDown, यह पेड़ के नीचे की दूरी है, इसलिए पेड़ siftDownके शीर्ष पर नोड्स के लिए महंगा है। के साथ siftUp, काम पेड़ के शीर्ष पर दूरी के लिए आनुपातिक है, इसलिए पेड़ siftUpके नीचे नोड्स के लिए महंगा है। हालांकि दोनों ऑपरेशन ओ (लॉग एन) सबसे खराब स्थिति में हैं, एक ढेर में, केवल एक नोड शीर्ष पर है जबकि आधा नोड्स नीचे की परत में स्थित है। इसलिए यह बहुत आश्चर्यजनक नहीं होना चाहिए कि अगर हमें हर नोड के लिए एक ऑपरेशन लागू करना है, तो हम siftDownअधिक पसंद करेंगे siftUp

buildHeapसमारोह जब तक वे सभी, ढेर संपत्ति को संतुष्ट जिससे एक वैध ढेर उत्पादन अवर्गीकृत वस्तुओं और उन्हें चाल की एक सरणी लेता है। हमारे द्वारा बताए गए और संचालन buildHeapका उपयोग करने के लिए दो दृष्टिकोण हो सकते हैं ।siftUpsiftDown

  1. ढेर के शीर्ष पर शुरू करें (सरणी की शुरुआत) और siftUpप्रत्येक आइटम पर कॉल करें । प्रत्येक चरण में, पहले से sifted आइटम (सरणी में वर्तमान आइटम से पहले आइटम) एक मान्य हीप बनाते हैं, और अगले आइटम को ऊपर ले जाकर इसे हीप में एक मान्य स्थिति में रखता है। प्रत्येक नोड को ऊपर ले जाने के बाद, सभी आइटम ढेर संपत्ति को संतुष्ट करते हैं।

  2. या, विपरीत दिशा में जाएं: सरणी के अंत में शुरू करें और पीछे की ओर सामने की ओर बढ़ें। प्रत्येक पुनरावृत्ति पर, आप एक आइटम को तब तक निचोड़ते हैं जब तक कि वह सही स्थान पर न हो।

कौन सा कार्यान्वयन buildHeapअधिक कुशल है?

ये दोनों समाधान एक वैध ढेर का उत्पादन करेंगे। अप्रत्याशित रूप से, अधिक कुशल एक दूसरा ऑपरेशन है जो उपयोग करता है siftDown

चलो एच = लॉग n ढेर की ऊंचाई का प्रतिनिधित्व करते हैं। siftDownदृष्टिकोण के लिए आवश्यक कार्य योग द्वारा दिया जाता है

(0 * n/2) + (1 * n/4) + (2 * n/8) + ... + (h * 1).

योग में प्रत्येक पद के लिए दी गई ऊंचाई पर एक नोड की अधिकतम दूरी होती है, उस ऊंचाई पर नोड्स की संख्या से गुणा (नीचे की परत के लिए शून्य, जड़ के लिए) करना होगा। इसके विपरीत, siftUpप्रत्येक नोड पर कॉल करने का योग है

(h * n/2) + ((h-1) * n/4) + ((h-2)*n/8) + ... + (0 * 1).

यह स्पष्ट होना चाहिए कि दूसरा योग बड़ा है। अकेले पहला शब्द hn / 2 = 1/2 n लॉग एन है , इसलिए इस दृष्टिकोण में सबसे अच्छा O (n लॉग एन) में जटिलता है ।

हम siftDownवास्तव में O (n) के दृष्टिकोण के लिए योग कैसे साबित करते हैं ?

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

निर्माण की जटिलता के लिए टेलर श्रृंखला

यदि आप सुनिश्चित नहीं हैं कि उनमें से प्रत्येक चरण क्यों काम करता है, तो शब्दों में इस प्रक्रिया का औचित्य है:

  • शब्द सभी सकारात्मक हैं, इसलिए परिमित राशि अनंत राशि से छोटी होनी चाहिए।
  • श्रृंखला x = 1/2 पर मूल्यांकन की गई एक शक्ति श्रृंखला के बराबर है ।
  • वह पावर सीरीज़ (एक स्थिर समय) के बराबर है टेलर श्रृंखला के व्युत्पन्न f (x) = 1 / (1-x) के लिए
  • x = 1/2 उस टेलर श्रृंखला के अभिसरण के अंतराल के भीतर है।
  • इसलिए, हम टेलर श्रृंखला को 1 / (1-x) से बदल सकते हैं , अंतर कर सकते हैं, और अनंत श्रृंखला के मूल्य का पता लगाने के लिए मूल्यांकन कर सकते हैं।

चूंकि अनंत योग बिल्कुल n है , इसलिए हम निष्कर्ष निकालते हैं कि परिमित राशि कोई बड़ी नहीं है, और इसलिए, हे (n)

हीप सॉर्ट को ओ (एन लॉग एन) समय की आवश्यकता क्यों है ?

यदि यह buildHeapरैखिक समय में चलना संभव है , तो हेप सॉर्ट को ओ (एन लॉग एन) समय की आवश्यकता क्यों है ? ठीक है, ढेर प्रकार दो चरणों के होते हैं। सबसे पहले, हम buildHeapउस सरणी पर कॉल करते हैं, जिसके लिए ओ (एन) समय की आवश्यकता होती है, अगर इसे आशावादी रूप से लागू किया जाता है। अगला चरण ढेर में सबसे बड़ी वस्तु को बार-बार हटाना और इसे सरणी के अंत में रखना है। क्योंकि हम एक आइटम को हीप से हटाते हैं, वहाँ हमेशा ढेर के अंत के बाद एक खुला स्थान होता है जहाँ हम आइटम को स्टोर कर सकते हैं। इसलिए ढेर क्रम क्रमिक रूप से अगले सबसे बड़े आइटम को हटाने और अंतिम स्थिति में शुरू होने वाले सरणी में डालकर और सामने की ओर बढ़ते हुए एक क्रमबद्ध क्रम को प्राप्त करता है। यह इस अंतिम भाग की जटिलता है जो ढेर प्रकार में हावी है। लूप इस तरह दिखता है:

for (i = n - 1; i > 0; i--) {
    arr[i] = deleteMax();
}

स्पष्ट रूप से, लूप ओ (एन) बार ( एन - 1 सटीक होने के लिए, अंतिम आइटम पहले से ही जगह पर है) चलाता है । deleteMaxएक ढेर के लिए जटिलता हे (लॉग एन) है । यह आम तौर पर रूट (ढेर में छोड़ी गई सबसे बड़ी वस्तु) को हटाकर और ढेर में अंतिम वस्तु के साथ प्रतिस्थापित किया जाता है, जो एक पत्ती है, और इसलिए सबसे छोटी वस्तुओं में से एक है। यह नई जड़ निश्चित रूप से ढेर संपत्ति का उल्लंघन करेगी, इसलिए आपको siftDownतब तक कॉल करना होगा जब तक आप इसे स्वीकार्य स्थिति में वापस नहीं ले जाते। यह अगले सबसे बड़े आइटम को जड़ तक ले जाने का भी प्रभाव है। ध्यान दें कि, पेड़ के नीचे से buildHeapकॉल करने वाले अधिकांश नोड्स के विपरीत siftDown, हम अब कॉल कर रहे हैं,siftDown प्रत्येक पुनरावृत्ति पर पेड़ के ऊपर से !हालांकि पेड़ सिकुड़ रहा है, यह काफी तेजी से सिकुड़ता नहीं है: जब तक आप नोड्स के पहले आधे हिस्से को नहीं हटा देते (जब आप नीचे की परत को पूरी तरह से साफ नहीं करते हैं) तब तक पेड़ की ऊंचाई स्थिर रहती है। फिर अगली तिमाही के लिए, ऊंचाई h - 1 है । तो इस दूसरे चरण के लिए कुल काम है

h*n/2 + (h-1)*n/4 + ... + 0 * 1.

स्विच को नोटिस करें: अब शून्य काम का मामला एक नोड से मेल खाता है और एच काम का मामला आधे नोड से मेल खाता है। यह योग ओ (n लॉग एन) के अक्षम संस्करण की तरह हैbuildHeap siftUp का उपयोग करके लागू किया गया है। लेकिन इस मामले में, हमारे पास कोई विकल्प नहीं है क्योंकि हम छांटने की कोशिश कर रहे हैं और हमें अगले सबसे बड़े आइटम को हटाने की आवश्यकता है।

संक्षेप में, हीप सॉर्ट के लिए कार्य दो चरणों का योग है: प्रत्येक नोड को हटाने के लिए बिल्डहाइप और ओ (एन लॉग एन) के लिए ओ (एन) समय , इसलिए जटिलता ओ (एन लॉग एन) है । आप साबित कर सकते हैं (सूचना सिद्धांत से कुछ विचारों का उपयोग करते हुए) कि तुलना-आधारित सॉर्ट के लिए, O (n log n) सबसे अच्छा है जिसे आप किसी भी तरह से आशा कर सकते हैं, इसलिए इससे निराश होने की कोई वजह नहीं है या इस प्रकार की उम्मीद की जा सकती है O (n) टाइम बाउंड जो buildHeapकरता है।


2
मैंने अपने उत्तर को एक अधिकतम हीप का उपयोग करने के लिए संपादित किया क्योंकि ऐसा लगता है कि अधिकांश अन्य लोग इसका उल्लेख कर रहे हैं और यह ढेर के लिए सबसे अच्छा विकल्प है।
जेरेमी वेस्ट

28
इसने इसे मेरे लिए सहज रूप से स्पष्ट कर दिया है: "केवल एक नोड शीर्ष पर है जबकि आधा नोड्स निचली परत में स्थित है। इसलिए यह बहुत आश्चर्यजनक नहीं होना चाहिए कि अगर हमें प्रत्येक नोड पर एक ऑपरेशन लागू करना है, तो हम करेंगे।" siftUp के ऊपर siftDown पसंद करें। "
विक्की चिजवानी

3
@ जेरेमीवेस्ट "एक ढेर के ऊपर शुरू करना है (सरणी की शुरुआत) और प्रत्येक आइटम पर siftUp को कॉल करें।" - क्या आप ढेर के नीचे शुरू करने का मतलब है?
aste123

4
@ aste123 नहीं, यह लिखित रूप में सही है। विचार सरणी के उस हिस्से के बीच एक बाधा बनाए रखने के लिए है जो ढेर संपत्ति और सरणी के अनट्रेंड हिस्से को संतुष्ट करता है। आप या तो शुरुआत में आगे बढ़ते हैं और siftUpप्रत्येक आइटम पर कॉल करते हैं या अंत में पीछे की ओर बढ़ते हैं और कॉल करते हैं siftDown। कोई फर्क नहीं पड़ता कि आप किस दृष्टिकोण को चुनते हैं, आप सरणी के अनसोल्ड हिस्से में अगले आइटम का चयन कर रहे हैं और इसे सरणी के आदेशित भाग में मान्य स्थिति में ले जाने के लिए उपयुक्त ऑपरेशन कर रहे हैं। केवल अंतर प्रदर्शन है।
जेरेमी वेस्ट

2
यह सबसे अच्छा जवाब है जो मैंने दुनिया में किसी भी प्रश्न के लिए देखा है। यह इतनी अच्छी तरह से समझाया गया था, मुझे पसंद था कि क्या यह वास्तव में संभव है ... बहुत बहुत धन्यवाद।
हरशिल जैन

314

आपका विश्लेषण सही है। हालांकि, यह तंग नहीं है।

यह स्पष्ट करना आसान नहीं है कि ढेर का निर्माण एक रैखिक ऑपरेशन क्यों है, आपको इसे बेहतर ढंग से पढ़ना चाहिए।

एल्गोरिथ्म का एक महान विश्लेषण यहां देखा जा सकता है


मुख्य विचार यह है कि build_heapएल्गोरिथ्म में वास्तविक heapifyलागत O(log n)सभी तत्वों के लिए नहीं है ।

कब heapify कहा जाता है, तो चलने का समय इस बात पर निर्भर करता है कि प्रक्रिया समाप्त होने से पहले कोई तत्व पेड़ में कितनी दूर जा सकता है। दूसरे शब्दों में, यह ढेर में तत्व की ऊंचाई पर निर्भर करता है। सबसे खराब स्थिति में, तत्व पत्ती स्तर तक सभी तरह से नीचे जा सकता है।

आइए हम स्तर से किए गए कार्य को गिनते हैं।

बॉटलमॉस्ट स्तर पर, 2^(h)नोड्स हैं, लेकिन हम heapifyइनमें से किसी पर कॉल नहीं करते हैं, इसलिए काम 0. है। अगले स्तर पर 2^(h − 1)नोड्स हैं, और प्रत्येक 1 स्तर से नीचे जा सकता है। नीचे से तीसरे स्तर पर, 2^(h − 2)नोड्स हैं, और प्रत्येक 2 स्तरों से नीचे जा सकता है।

जैसा कि आप देख सकते हैं कि सभी ढेर परिचालन नहीं हैं O(log n), यही कारण है कि आप प्राप्त कर रहे हैं O(n)


17
यह एक महान व्याख्या है ... लेकिन ऐसा क्यों है कि ढेर-प्रकार ओ (एन लॉग एन) में चलता है। उसी तर्क को ढेर-प्रकार पर लागू क्यों नहीं किया जाता है?
एचबी

49
@ मुझे लगता है कि आपके प्रश्न का उत्तर इस लेख से इस छवि को समझने में निहित है । है जब के साथ किया लेकिन जब साथ किया । वास्तविक छंटाई (एक-एक करके ढेर से आइटम खींचना) इसलिए के साथ किया जाना है । HeapifyO(n)siftDownO(n log n)siftUpsiftUpO(n log n)
०११

3
मैं वास्तव में नीचे की ओर आपके बाहरी दस्तावेज़ की सहज व्याख्या पसंद करता हूं।
लुकास ग्रीब्लिकास

1
@hba नीचे जेरेमी वेस्ट द्वारा दिया गया उत्तर आपके प्रश्न को और अधिक बारीक, आसानी से समझ में आने वाले विवरण को संबोधित करता है, आगे The111 की टिप्पणी यहाँ बता रहा है।
cellepo

एक प्रश्न। यह मुझे लगता है कि iऊंचाई h के पेड़ के नीचे से ऊंचाई पर एक नोड के लिए बनाई गई # 2* log(h-i)तुलनाओं को भी तुलना करना चाहिए और साथ ही @ The111 के लिए भी जिम्मेदार होना चाहिए। तुम क्या सोचते हो?
सिड

94

intuitively:

"जटिलता ओ होना चाहिए (n nog n) ... प्रत्येक आइटम के लिए हम" हीप्लीज़ "करते हैं, यह अब तक के लिए प्रत्येक स्तर के लिए एक बार फ़िल्टर करने की क्षमता है (जो लॉग एन स्तर है)।"

काफी नहीं। आपका तर्क एक तंग बन्धन पैदा नहीं करता है - यह प्रत्येक ढेर की जटिलता का अनुमान लगाता है। यदि नीचे से बनाया गया है, तो सम्मिलन (हीइफीफाय) की तुलना में बहुत कम हो सकता है O(log(n))। प्रक्रिया इस प्रकार है:

(चरण 1) पहले n/2तत्व ढेर की निचली पंक्ति पर चलते हैं। h=0, इसलिए ढेर की जरूरत नहीं है।

(चरण 2) अगले तत्व नीचे से पंक्ति 1 पर जाते हैं। , फ़िल्टर को 1 स्तर नीचे दबाएं।n/22h=1

(चरण i ) अगले तत्व नीचे से पंक्ति में जाते हैं । , फ़िल्टर स्तर को कम करें।n/2iih=ii

(स्टेप लॉग (n) ) अंतिम तत्व नीचे से पंक्ति में जाता है । , फ़िल्टर स्तर को कम करें।n/2log2(n) = 1log(n)h=log(n)log(n)

सूचना: कदम एक के बाद, 1/2तत्वों के (n/2)पहले से ही ढेर में हैं, और हमें एक बार भी heapify कॉल करने की आवश्यकता नहीं थी। इसके अलावा, ध्यान दें कि केवल एक तत्व, मूल, वास्तव में पूरी log(n)जटिलता को उकसाता है।


सैद्धांतिक रूप से:

Nआकार का एक ढेर बनाने के लिए कुल कदम n, गणितीय रूप से लिखे जा सकते हैं।

ऊंचाई पर i, हमने (ऊपर) दिखाया है कि वहाँ होगाn/2i+1 तत्व heapify कॉल करने की आवश्यकता है, और हम जानते हैं कि heapify ऊँचाई पर iहै O(i)। यह देता है:

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

अंतिम समन का हल अच्छी तरह से ज्ञात ज्यामितीय श्रृंखला समीकरण के दोनों पक्षों के व्युत्पन्न लेने से मिल सकता है:

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

अंत x = 1/2में, उपरोक्त समीकरण पैदावार में प्लगिंग2 । इसे पहले समीकरण में प्लग करना:

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

इस प्रकार, चरणों की कुल संख्या आकार की है O(n)


35

यदि आप बार-बार तत्वों को डालकर ढेर का निर्माण करते हैं तो यह O (n log n) होगा। हालाँकि, आप तत्वों को मनमाने तरीके से सम्मिलित करके एक नया ढेर अधिक कुशलता से बना सकते हैं और फिर उन्हें उचित क्रम में "heapify" करने के लिए एक एल्गोरिथम लागू कर सकते हैं (पाठ्यक्रम के प्रकार के आधार पर)।

उदाहरण के लिए http://en.wikipedia.org/wiki/Binary_heap , "हीप बिल्डिंग" देखें । इस मामले में आप अनिवार्य रूप से पेड़ के निचले स्तर से ऊपर काम करते हैं, माता-पिता और बच्चे के नोड्स को स्वैप करते हैं जब तक कि ढेर की स्थिति संतुष्ट नहीं होती है।


12

पहले से ही कुछ शानदार जवाब हैं, लेकिन मैं थोड़ा दृश्य स्पष्टीकरण जोड़ना चाहूंगा

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

अब, छवि पर एक नज़र डालें, देखते हैं
n/2^1 हरे नोड्स के साथ ऊंचाई 0 (यहाँ 23/2 = 12)
n/2^2 लाल नोड्स के साथ ऊंचाई 1 (यहाँ 23/4 = 6)
n/2^3 नीले नोड के साथ ऊंचाई 2 (यहाँ 23/8 = 3) ऊँचाई 3 के साथ
n/2^4 बैंगनी नोड्स (यहाँ 23/16 = 2) इसलिए ऊँचाई h के लिए नोड्स हैं समय जटिलता खोजने के लिए गणना कर सकते हैं
n/2^(h+1)
काम मात्रा की या प्रत्येक नोड द्वारा किए गए पुनरावृत्तियों की अधिकतम संख्या
अब यह देखा जा सकता है कि प्रत्येक नोड प्रदर्शन (अधिकतम) पुनरावृत्तियों == नोड की ऊंचाई

Green  = n/2^1 * 0 (no iterations since no children)  
red    = n/2^2 * 1 (heapify will perform atmost one swap for each red node)  
blue   = n/2^3 * 2 (heapify will perform atmost two swaps for each blue node)  
purple = n/2^4 * 3 (heapify will perform atmost three swaps for each purple node)   

इसलिए ऊँचाई के साथ किसी भी नोड के लिए अधिकतम काम n / 2 ^ (h + 1) * h है

अब कुल काम हो गया है

->(n/2^1 * 0) + (n/2^2 * 1)+ (n/2^3 * 2) + (n/2^4 * 3) +...+ (n/2^(h+1) * h)  
-> n * ( 0 + 1/4 + 2/8 + 3/16 +...+ h/2^(h+1) ) 

अब h के किसी भी मूल्य के लिए , अनुक्रम

-> ( 0 + 1/4 + 2/8 + 3/16 +...+ h/2^(h+1) ) 

1 से अधिक कभी नहीं होगा।
इस प्रकार समय की जटिलताढेर के निर्माण के लिए O (n) से अधिक नहीं होगी


7

जैसा कि हम जानते हैं कि एक ढेर की ऊँचाई लॉग (n) है , जहाँ n तत्वों की कुल संख्या है।    चलो इसे h के रूप में
दर्शाते हैं जब हम heapify ऑपरेशन करते हैं, तो अंतिम स्तर ( h ) पर तत्व एक भी नहीं चलेंगे कदम।
   दूसरे अंतिम स्तर ( h-1 ) पर तत्वों की संख्या 2 h-1 है और वे अधिकतम 1 स्तर (heapify के दौरान) में स्थानांतरित हो सकते हैं ।
   इसी तरह, i वें के लिए , हमारे पास 2 i तत्व हैं जो उच्च पदों को स्थानांतरित कर सकते हैं ।

इसलिए चालों की कुल संख्या = S = 2 h * 0 + 2 h-1 * 1 + 2 h-2 * 2 + ... 2 0 * h

                                               S = 2 h {1/2 + 2/2 2 h + 1 { 1/2 + 1/2 2 + 1/2 3 + 3/2 3 + ... h / 2 h } ----------------------- -------------------------- 1
यह एजीपी श्रृंखला है, इस विभाजन को दोनों पक्षों द्वारा 2
                                               एस / 2 = 2 घंटे {1/2 से हल करने के लिए 2 + 2/2 3 + ... h / 2 h + 1 } --------------------------------- ---------------- 2
घटाकर समीकरण 2 से 1 देता
                                               एस / 2 = 2 {1/2 + 1/2 2 + 1/2 3 + ... + 1 / 2 एच + एच / 2 एच + 1 }
                                               एस = 2 + ... + 1/2 + h / 2 ज + 1 } अब 1/2 + 1/2 2 + 1/2 3 + ... + 1/2 एच घट रहा है जीपी जिसका योग 1 से कम है (जब एच अनंत तक जाता है, तो राशि 1 हो जाती है)। आगे के विश्लेषण में, हम योग पर एक ऊपरी बाउंड लेते हैं जो 1. है। यह S = 2 h + 1 {1 + h / 2 h + 1 }                     = 2 h + 1 + h ~ 2 h + h को h = लॉग मानता है। (एन) , 2 एच = एन



                    


इसलिए एस = एन + लॉग (एन)
टी (सी) = ओ (एन)


6

एक ढेर का निर्माण करते हुए, आप कहते हैं कि आप नीचे तक पहुंच रहे हैं।

  1. आप प्रत्येक तत्व लेते हैं और अपने बच्चों के साथ तुलना करके यह जांचते हैं कि क्या जोड़ी ढेर नियमों के अनुरूप है। तो, इसलिए, पत्तियों को मुफ्त में ढेर में शामिल किया जाता है। ऐसा इसलिए है क्योंकि उनके कोई बच्चे नहीं हैं।
  2. ऊपर की ओर बढ़ते हुए, पत्तियों के ठीक ऊपर नोड के लिए सबसे खराब स्थिति 1 तुलना होगी (अधिकतम वे केवल एक ही जीव के साथ तुलना की जाएगी)
  3. और आगे बढ़ते हुए, उनके तत्काल माता-पिता की तुलना बच्चों की दो पीढ़ियों से की जा सकती है।
  4. उसी दिशा में आगे बढ़ते हुए, आप सबसे खराब स्थिति में रूट के लिए लॉग (n) तुलना करेंगे। और लॉग (n) -1 अपने तत्काल बच्चों के लिए, लॉग (n) -2 अपने तत्काल बच्चों के लिए और इसी तरह।
  5. तो इसे पूरा करें, आप लॉग (एन) + {लॉग (एन) -1} * 2 + {लॉग (एन) -2} * 4 + ..... + 1 * 2 ^ {(जैसे कुछ पर आते हैं। logn) -1} जो O (n) के अलावा कुछ नहीं है।

2

ढेर के निर्माण के मामले में, हम ऊंचाई से शुरू करते हैं, logn -1 (जहां logn n तत्वों के पेड़ की ऊंचाई है)। ऊँचाई 'h' पर मौजूद प्रत्येक तत्व के लिए, हम अधिकतम upto (logn -h) ऊँचाई पर जाते हैं।

    So total number of traversal would be:-
    T(n) = sigma((2^(logn-h))*h) where h varies from 1 to logn
    T(n) = n((1/2)+(2/4)+(3/8)+.....+(logn/(2^logn)))
    T(n) = n*(sigma(x/(2^x))) where x varies from 1 to logn
     and according to the [sources][1]
    function in the bracket approaches to 2 at infinity.
    Hence T(n) ~ O(n)

1

क्रमिक सम्मिलन द्वारा वर्णित किया जा सकता है:

T = O(log(1) + log(2) + .. + log(n)) = O(log(n!))

सन्निकटन अभिनीत करके, n! =~ O(n^(n + O(1))) , इसलिएT =~ O(nlog(n))

आशा है कि यह मदद करता है, इष्टतम तरीका O(n)दिए गए सेट के लिए बिल्ड हीप एल्गोरिथ्म का उपयोग कर रहा है (ऑर्डर करने से कोई फर्क नहीं पड़ता)।


1

मूल रूप से, एक हीप का निर्माण करते समय केवल गैर-पत्ती के नोड्स पर काम किया जाता है ... और किया गया कार्य ढेर की स्थिति को संतुष्ट करने के लिए नीचे स्वैपिंग की मात्रा है ... दूसरे शब्दों में (सबसे खराब स्थिति में) राशि ऊंचाई के लिए आनुपातिक है नोड के ... समस्या की सभी जटिलता में सभी गैर-पत्ती नोड्स की ऊँचाई के अनुपात के समानुपाती है..जिसमें (2 ^ h + 1 - 1) -h-1 = nh-1 = है पर)


1

@ बॉर्सो ने पहले ही जटिलता विश्लेषण के प्रमाण का प्रदर्शन किया है। लेकिन अभी भी जटिलता विश्लेषण सीखने वालों के लिए, मुझे यह जोड़ना होगा:

आपकी मूल गलती का आधार बयान के अर्थ की गलत व्याख्या के कारण है, "एक ढेर में प्रविष्टि ओ (लॉग एन) समय लेता है"। एक ढेर में प्रविष्टि वास्तव में हे (लॉग एन) है, लेकिन आपको यह पहचानना होगा कि सम्मिलन के दौरान एन ढेर का आकार है ।

N ऑब्जेक्ट्स को ढेर में डालने के संदर्भ में, ith सम्मिलन की जटिलता हे (लॉग n_i) है जहां n_i प्रविष्टि i के अनुसार हीप का आकार है। केवल अंतिम प्रविष्टि में O (log n) की जटिलता है।


1

मान लीजिए कि आपके पास ढेर में एन तत्व हैं। तब इसकी ऊंचाई लॉग (N) होगी

अब आप एक और तत्व सम्मिलित करना चाहते हैं, फिर जटिलता होगी: लॉग (एन) , हमें यूपी की सभी तरह से तुलना करनी होगी को रूट करना होगा।

अब आपके पास N + 1 तत्व और ऊंचाई = है लॉग (N + 1) है

प्रेरण तकनीक का उपयोग करके यह साबित किया जा सकता है कि सम्मिलन की जटिलता canlogi होगी

अब उपयोग कर रहे हैं

लॉग + ए लॉग बी = लॉग एब

यह सरल करता है: ilogi = log (n!)

जो वास्तव में हे (NlogN)

परंतु

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

यह अहसास मुझे विस्तार से बताने के बाद आया, हालांकि हीप्स पर प्रयोग।


0

मैं वास्तव में जेरेमी पश्चिम द्वारा स्पष्टीकरण पसंद करता हूं .... एक और दृष्टिकोण जो समझने में आसान है, यहां दिया गया है http://courses.washington.edu/css343/zander/NotesProbs/heapcomplexity

चूंकि, बिल्डहीप का उपयोग करना निर्भर करता है, यह हाइपिफाई पर निर्भर करता है और शिफ्टडाउन दृष्टिकोण का उपयोग किया जाता है जो सभी नोड्स की ऊंचाई पर निर्भर करता है। तो, नोड्स की ऊँचाई का योग ज्ञात करने के लिए जो S = योग से i = 0 से i = h का (2 ^ i * (hi)) दिया जाता है, जहाँ h = logn पेड़ की ऊँचाई को हल करने के लिए होता है, हमें मिलता है s = 2 ^ (एच + 1) - 1 - (एच + 1) के बाद से, एन = 2 ^ (एच + 1) - 1 एस = एन - एच - 1 = एन- लोगन - 1 एस = ओ (एन),> और निर्माण की जटिलता ओ (एन) है।


0

"बिल्ड हीप का रैखिक समय, हीप में सभी नोड्स की ऊंचाइयों के योग की गणना करके दिखाया जा सकता है, जो कि धराशायी लाइनों की अधिकतम संख्या है। एन = 2 ^ (एच) युक्त ऊंचाई के सही द्विआधारी पेड़ के लिए। h + 1) - 1 नोड्स, नोड्स की ऊंचाइयों का योग N - H - 1. है। इस प्रकार यह (N) है। "


0

O का प्रमाण (n)

सबूत फैंसी नहीं है, और काफी सीधा है, मैंने केवल एक पूर्ण बाइनरी ट्री के लिए मामला साबित किया है, परिणाम को एक पूर्ण बाइनरी ट्री के लिए सामान्यीकृत किया जा सकता है।


0

हम प्रत्येक नोड ले जा सकने वाले अधिकतम चाल का अनुमान लगाकर ढेर निर्माण के लिए रनटाइम प्राप्त करते हैं। इसलिए हमें यह जानने की जरूरत है कि प्रत्येक पंक्ति में कितने नोड हैं और प्रत्येक नोड से कितनी दूर जा सकते हैं।

रूट नोड से शुरू होने वाली प्रत्येक अगली पंक्ति में पिछली पंक्ति की तुलना में नोड्स की संख्या दोगुनी होती है, इसलिए यह उत्तर देकर कि हम कितनी बार नोड्स की संख्या को दोगुना कर सकते हैं जब तक कि हमारे पास कोई नोड नहीं बचा है जब तक हम पेड़ की ऊंचाई प्राप्त नहीं करते हैं। या गणितीय शब्दों में पेड़ की ऊँचाई log2 (n) है, n सरणी की लंबाई है।

नोड्स की गणना करने के लिए एक पंक्ति में हम पीछे से शुरू करते हैं, हम जानते हैं कि n / 2 नोड्स सबसे नीचे हैं, इसलिए 2 से विभाजित करके हमें पिछली पंक्ति और इसी तरह मिलती है।

इसके आधार पर हमें Siftdown दृष्टिकोण के लिए यह सूत्र मिलता है: (0 * n / 2) + (1 * n / 4) + (2 * n / 8) + ... + (log2 (n) * 1)

अंतिम परिधि में शब्द एक नोड द्वारा गुणा किए गए पेड़ की ऊंचाई है, जो जड़ में है, पहली परिधि में शब्द नीचे की पंक्ति में सभी नोड्स हैं जिनकी लंबाई वे यात्रा कर सकते हैं, 0। स्मार्ट में एक ही सूत्र: यहाँ छवि विवरण दर्ज करें

गणित

N को वापस लाने पर हमारे पास 2 * n, 2 को छोड़ दिया जा सकता है क्योंकि इसके स्थिर और टाडा में हमारे पास Siftdown दृष्टिकोण का सबसे खराब मामला है: n।


-6

लगता है कि आप एक गलती कर रहे हैं। इस पर एक नज़र डालें: http://golang.org/pkg/container/heap/ एक ढेर isn'y O (n) का निर्माण। हालाँकि, सम्मिलित करना O (lg (n) है। मेरा मानना ​​है कि इनिशियलाइज़ेशन O (n) है यदि आप एक ढेर का आकार b / c सेट करते हैं तो ढेर को स्थान आवंटित करने और डेटा संरचना सेट करने की आवश्यकता है। यदि आपके पास डालने के लिए n आइटम हैं। ढेर में तो हाँ, प्रत्येक सम्मिलित है lg (n) और n आइटम हैं, इसलिए आपको n * lg (n) मिलता है जैसा कि यू कहा गया है


2
नहीं, यह तंग नहीं है। बिल्ड हीप यील्ड्स हे (n) का
संक्षिप्त

ऐसा लगता है कि यह एक अनुमान है। Thearticle में उन्होंने कहा कि संदर्भित है "अंतर्ज्ञान है कि ढेर करने के लिए ज्यादातर कॉल बहुत कम ढेर पर हैं" हालांकि यह कुछ धारणाएं बना रहा है। संभवतः, एक बड़े ढेर के लिए, सबसे खराब स्थिति अभी भी O (n * lg (n)) होगी, भले ही आप आमतौर पर O (n) के करीब पहुंच सकें। लेकिन मैं गलत हो सकता है
माइक स्कैचर

हां, यह मेरा सहज जवाब है, लेकिन विकिपीडिया राज्य जैसे संदर्भ "एन तत्वों वाले हीप्स को ओ (एन) में नीचे-ऊपर का निर्माण किया जा सकता है।"
जीबीए

1
मैं पूरी तरह से डेटा संरचना की तरह सोच रहा था। मैं एक ढेर के विशिष्ट गुणों को भूल गया।
माइक स्कैचर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.