हीप - एक सॉर्ट की गई सूची में


15

सबसे शायद, यह सवाल पहले पूछा गया है। यह CLRS (2nd Ed) समस्या 6.5-8 से है -

एक सॉर्ट की गई सूची में कश्मीर सॉर्ट किए गए सूचियों को मर्ज करने के लिए टाइम अल्गोरिदम दें , जहां n सभी इनपुट सूचियों में कुल तत्वों की संख्या है। (संकेत: k -way विलय के लिए एक मिनट-ढेर का उपयोग करें ।)O(nlgk)knk

जैसा कि क्रमबद्ध सूचियाँ और कुल n मान हैं, मान लें कि प्रत्येक सूची में n सम्‍मिलित हैkn नंबर, सूचियों में से प्रत्येक को कड़ाई से आरोही क्रम में क्रमबद्ध किया गया है, और परिणाम भी आरोही क्रम में संग्रहीत किए जाएंगे।nk

मेरा छद्म कोड इस तरह दिखता है -

    list[k]   ; k sorted lists
    heap[k]   ; an auxiliary array to hold the min-heap
    result[n] ; array to store the sorted list
    for i := 1 to k                 ; O(k)
    do
        heap[i] := GET-MIN(list[i]) ; pick the first element 
                                    ; and keeps track of the current index - O(1)
    done
    BUILD-MIN-HEAP(heap) ; build the min-heap - O(k)
    for i := 1 to n
    do
        array[i] := EXTRACT-MIN(heap)   ; store the min - O(logk)
        nextMin := GET-MIN(list[1])     ; get the next element from the list 1 - O(1)
        ; find the minimum value from the top of k lists - O(k)
        for j := 2 to k                 
        do
            if GET-MIN(list[j]) < nextMin
                nextMin := GET-MIN(list[j]) 
        done
        ; insert the next minimum into the heap - O(logk)
        MIN-HEAP-INSERT(heap, nextMin)
    done

मेरे समग्र जटिलता हो जाता । मुझे O ( n ) के अंदर O ( k ) लूप से बचने का कोई तरीका नहीं मिलाO(k)+O(k)+O(n(k+2lgk))O(nk+nlgk)O(nk)O(k)O(n)k सूचियों से अगला न्यूनतम तत्व खोजने के लिए लूप। क्या कोई और रास्ता है? एल्गोरिथ्म कैसे प्राप्त करें ?O(nlgk)

जवाबों:


13

ढेर का उद्देश्य आपको न्यूनतम देना है, इसलिए मुझे यकीन नहीं है कि लूप के लिए इसका उद्देश्य क्या है - for j := 2 to k

मेरा छद्म कोड पर ले:

lists[k][?]      // input lists
c = 0            // index in result
result[n]        // output
heap[k]          // stores index and applicable list and uses list value for comparison
                 // if i is the index and k is the list
                 //   it has functions - insert(i, k) and deleteMin() which returns i,k
                 // the reason we use the index and the list, rather than just the value
                 //   is so that we can get the successor of any value

// populate the initial heap
for i = 1:k                   // runs O(k) times
  heap.insert(0, k)           // O(log k)

// keep doing this - delete the minimum, insert the next value from that list into the heap
while !heap.empty()           // runs O(n) times
  i,k = heap.deleteMin();     // O(log k)
  result[c++] = lists[k][i]
  i++
  if (i < lists[k].length)    // insert only if not end-of-list
    heap.insert(i, k)         // O(log k)

कुल समय जटिलता इस प्रकार है O(klogk+n2logk)=O(nlogk)

आप भी कर सकते हैं deleteMinऔर के बजाय insert, getMin( ) और ( ( लॉग के ) ) है, जो निरंतर कारक को कम करेगा, लेकिन जटिलता नहीं।O(1)incrementIndexO(logk)

उदाहरण:
(इंडेक्स और लिस्ट इंडेक्स की बजाय वैल्यू का उपयोग करके और क्लियरिटी के लिए सॉर्ट किए गए एरे के रूप में लिस्ट किया गया ढेर)

Input: [1, 10, 15], [4, 5, 6], [7, 8, 9]

Initial heap: [1, 4, 7]

Delete 1, insert 10
Result: [1]
Heap: [4, 7, 10]

Delete 4, insert 5
Result: [1, 4]
Heap: [5, 7, 10]

Delete 5, insert 6
Result: [1, 4, 5]
Heap: [6, 7, 10]

Delete 6, insert nothing
Result: [1, 4, 5, 6]
Heap: [7, 10]

Delete 7, insert 8
Result: [1, 4, 5, 6, 7]
Heap: [8, 10]

Delete 8, insert 9
Result: [1, 4, 5, 6, 7, 8]
Heap: [9, 10]

Delete 9, insert nothing
Result: [1, 4, 5, 6, 7, 8, 9]
Heap: [10]

Delete 10, insert 15
Result: [1, 4, 5, 6, 7, 8, 9, 10]
Heap: [15]

Delete 15, insert nothing
Result: [1, 4, 5, 6, 7, 8, 9, 10, 15]
Heap: []

Done

मान लें कि आपके पास इन सूचियों को मर्ज करने के लिए है, सूची [1] = [1, 10, 15], सूची [2] = [4, 5, 6] और सूची [3] = [7, 8, 9]। पहले पुनरावृत्ति पर, हीप से मान 1 होगा और आगे आपका एल्गोरिदम 10 को ढेर में सम्मिलित करेगा, लेकिन 10 सभी सूचियों का सबसे बड़ा मूल्य है - आप इससे कैसे बचेंगे?
रामगुरुर

@ramgorur इससे कोई फर्क नहीं पड़ता कि 10 ढेर में है। 4,5,6,7,8 और 9 सभी इससे पहले संसाधित हो जाएंगे क्योंकि हम हमेशा ढेर से सबसे छोटा मूल्य प्राप्त करते हैं और उसी सूची से हटाए गए मूल्यों को अगले आइटम के साथ बदलते रहते हैं। उदाहरण के साथ संपादित उत्तर।
जुगल २४'१३

ठीक है, अगर यह मामला है, तो हमें वास्तव में अगले तत्व के लिए समान सूची याद नहीं है । हम हर बार एक यादृच्छिक सूची चुन सकते हैं और अगले तत्व को ढेर में धकेल सकते हैं - जो माना जाता है कि वही परिणाम देगा, क्या मैं सही हूं? या समान सूची तर्क का पालन करने के लिए कोई अन्य विशेष कारण है ?
रामगुरूर

हटाते समय 4, यदि आप एक यादृच्छिक सूची चुनते हैं, तो आप सम्मिलित करना समाप्त कर सकते हैं 8, इस प्रकार ढेर होगा [7, 8, 10], जिसमें से आप परिणाम सेट के 7बजाय सम्मिलित करेंगे 5, जो गलत होगा।
डुकलिंग

O(k)

13

n/k

आपकी समस्या के लिए, निम्नलिखित एल्गोरिथ्म को चाल करना चाहिए:

  1. HklmO(klgk)
  2. i1n
    • न्यूनतम निकालेंmHresult[i]O(lgk)
    • mlmHO(lgk) )

O(klgk+nlgk)=O(nlgk)result

iresultHiresult[1..i] is correctly sorted after the i-th iteration.

This is true before the first iteration: First, we show that the first element to insert into result is in H: Assume towards a contradiction that the first element to insert into result (that is, the overall smallest element, call it r1) were not a first element. Then, in the list l that contains r1, the first element l[1] must be distinct from r1 (as by assumption, r1 is not a first element). As our lists are all sorted, we have even l[1]<r1, but this is a contradiction, as we chose r1 to be the overall smallest element. Obviously, the minimum of all first elements is the one to insert into result.

The invariant holds after an iteration: We proceed in the same way. Assume the i-th element to insert (call it ri) were not in H. By construction, H holds at most one element from each list, and once it contains an element m from a list l, all of its predecessors in l were already extracted from H and (by hypothesis) correctly inserted into result. Therefore, ri is assumed to be a successor of some element m in the list l. But this is, as above, a contradiction, as l is sorted, and therefore, the invariant holds.

On termination, we thus have result[1..n] correctly sorted.


Actually the tighter time complexity would be O(K+2*NlogK)=O(NlogK). O(K) is tighter bound than O(KlogK), when making a Heap. Refer this for further clarifications.
Ashwani Gautam

@AshwaniGautam That's not tighter at all, since both O(k) and O(klogk) are dominated. That said, your point is correct; the first initialization of the heap can indeed be done in linear time (in k). I guess (hope!) both answerers know that, but it's not crucial here.
Raphael
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.