2009-09-23 15 views

उत्तर

29

प्रभावी रूप से "कमी-कुंजी" को लागू करने के लिए, आपको कार्यक्षमता तक पहुंचने की आवश्यकता होगी "इस तत्व को कम करें और इस तत्व को एक बच्चे के साथ स्वैप करें जब तक कि ढेर स्थिति बहाल न हो जाए"। heapq.py में, जिसे _siftdown कहा जाता है (और इसी तरह _siftup इनक्रिकमेंटिंग के लिए)। तो अच्छी खबर यह है कि कार्य वहां हैं ... बुरी खबर यह है कि उनके नाम अंडरस्कोर से शुरू होते हैं, जो दर्शाते हैं कि उन्हें "आंतरिक कार्यान्वयन विवरण" माना जाता है और उन्हें सीधे आवेदन कोड द्वारा एक्सेस नहीं किया जाना चाहिए (अगली रिलीज मानक पुस्तकालय ऐसी चीजों को बदल सकता है और इस तरह के "आंतरिक" का उपयोग कर कोड तोड़ सकता है)।

यह है कि क्या आप की अनदेखी करने की चेतावनी leading- _ चाहते हे (एन) का उपयोग हे के बजाय heapify (लॉग एन) छानना, या sifting पुरातन "बनाने के लिए कुछ या heapq की कार्यक्षमता के सभी reimplement तय करने के लिए आप पर निर्भर है इंटरफेस के सार्वजनिक भागों के रूप में उजागर "। चूंकि हेपैक की डेटा संरचना दस्तावेज और सार्वजनिक (केवल एक सूची) है, मुझे लगता है कि सबसे अच्छा विकल्प शायद आंशिक-पुनर्मूल्यांकन है - अपने आवेदन कोड में हेपक्विटी से sifting कार्यों को कॉपी करें, अनिवार्य रूप से।

+2

heapq.py का लिंक पुराना प्रतीत होता है। सुविधा के लिए यहां पाइथन कार्यान्वयन का एक और लिंक है: http://hg.python.org/cpython/file/2.7/Lib/heapq.py – Jordan

+0

क्या आपका मतलब है "इस तत्व को इसके _parent_ के साथ स्वैप करें जब तक ढेर की स्थिति बहाल न हो जाए"? (मुझे लगता है कि तत्व थे, '[2, 3, 5]', फिर '2' माता-पिता होंगे, और' 3' और '5' इसके दो बच्चे होंगे) – tscizzle

3

कल्पना कीजिए कि आप एक प्राथमिकता कतार के रूप में एक ढेर का उपयोग कर रहे हैं, जहां आपके पास स्ट्रिंग द्वारा प्रतिनिधित्व कार्यों का एक गुच्छा है और प्रत्येक कार्य में एक कुंजी है। Concreteness के लिए, देखें: task_list = [[7,"do laundry"], [3, "clean room"], [6, "call parents"]] जहां task_list में प्रत्येक कार्य प्राथमिकता और विवरण के साथ एक सूची है। यदि आप heapq.heapify(task_list) चलाते हैं, तो आप हेप इनवेरिएंट को बनाए रखने के लिए अपनी सरणी प्राप्त करते हैं। हालांकि, अगर आप "कपड़े धोने" की प्राथमिकता को 1 से बदलना चाहते हैं, तो आपके पास ढेर के माध्यम से रैखिक स्कैन किए बिना ढेर में "कपड़े धोने" कहां है, यह जानने का कोई तरीका नहीं है (इसलिए लॉगरिदमिक समय में कमी_की नहीं कर सकता) । नोट decrease_key(heap, i, new_key) आपको ढेर में बदलने के लिए मूल्य की अनुक्रमणिका जानने की आवश्यकता है।

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

task_list = [[7, "do laundry"], [3, "clean room"], [6, "call parents"]] 
task_list_heap = task_list[:] # make a non-deep copy 
heapq.heapify(task_list_heap) 
# at this point: 
# task_list = [[7, 'do laundry'], [3, 'clean room'], [6, 'call parents']] 
# task_list_heap = [3, 'clean room'], [7, 'do laundry'], [6, 'call parents']] 
# Change key of first item of task_list (which was "do laundry") from 7 to 1. 
task_list[0][0] = 1 
# Now: 
# task_list = [[1, 'do laundry'], [3, 'clean room'], [6, 'call parents']] 
# task_list_heap = [3, 'clean room'], [1, 'do laundry'], [6, 'call parents']] 
# task_list_heap violates heap invariant at the moment 

हालांकि, अब आप heapq._siftdown(task_list_heap, 1) कॉल करने के लिए लॉग समय में ढेर अपरिवर्तनीय (heapq.heapify रैखिक समय है) बनाए रखने की जरूरत है, लेकिन दुर्भाग्य से हम इस मामले में task_list_heap (heap_index में "लॉन्ड्री के" के सूचकांक है पता नहीं है 1)।

इसलिए हमें प्रत्येक ढेर के heap_index के हमारे ढेर को ट्रैक करने की आवश्यकता है; उदाहरण के लिए, list (ढेर के लिए) और dict प्रत्येक ऑब्जेक्ट को ढेर/सूची में अपनी अनुक्रमणिका में मैपिंग करें (जो अपडेट हो जाता है क्योंकि हीप स्थिति प्रत्येक स्वैप के लिए स्थिर कारक जोड़कर बदल जाती है)। आप heapq.py के माध्यम से पढ़ सकते हैं और प्रक्रिया को सरल बनाते हुए स्वयं को कार्यान्वित कर सकते हैं; हालांकि, अन्य ने इस प्रकार के HeapDict को पहले से ही कार्यान्वित किया है।

4

heapq documentation इस पर एक प्रविष्टि है कि यह कैसे करें।

हालांकि, मैंने heap पैकेज लिखा है जो वास्तव में यह करता है (यह heapq के आसपास एक रैपर है)।तो अगर आप pip या easy_install है आप की तरह

pip install heap 
फिर अपने कोड लिखने में

from heap.heap import heap 

h = heap() 

h['hello'] = 4 # Insert item with priority 4. 

h['hello'] = 2 # Update priority/decrease-key has same syntax as insert. 

यह बहुत नया है, हालांकि कुछ कर सकते हैं, तो कीड़े से भरा हो सकता है।

2

कम-कुंजी कई एल्गोरिदम (डिजस्ट्रा के एल्गोरिदम, ए *, ऑप्टिक्स) के लिए एक ऑपरेशन होना चाहिए, मुझे आश्चर्य है कि क्यों पाइथन की अंतर्निहित प्राथमिकता कतार इसका समर्थन नहीं करती है।

दुर्भाग्य से, मैं math4tots के पैकेज को डाउनलोड करने में सक्षम नहीं था।

लेकिन, मैं डैनियल स्टुटज़बैक द्वारा this कार्यान्वयन को खोजने में सक्षम था। पाइथन 3.5 के साथ मेरे लिए पूरी तरह से काम किया।

संबंधित मुद्दे

 संबंधित मुद्दे