डीजकस्ट्रा के एल्गोरिथ्म में कमी-कुंजी का उपयोग क्यों किया जाता है?


93

दीजकस्ट्रा का एल्गोरिथम मुझे इस प्रकार सिखाया गया था

while pqueue is not empty:
    distance, node = pqueue.delete_min()
    if node has been visited:
        continue
    else:
        mark node as visited
    if node == target:
        break
    for each neighbor of node:
         pqueue.insert(distance + distance_to_neighbor, neighbor)

लेकिन मैं एल्गोरिथ्म के बारे में कुछ पढ़ रहा हूं, और बहुत सारे संस्करण मैं उपयोग में कमी-कुंजी को सम्मिलित करने के लिए विरोध करता हूं।

यह क्यों है, और दोनों दृष्टिकोणों के बीच अंतर क्या हैं?


14
Downvoter- क्या आप बता सकते हैं कि इस सवाल में क्या गलत है? मुझे लगता है कि यह पूरी तरह से उचित है, और कई लोगों (मेरे सहित) को पहली बार ओपी के संस्करण के डीजकस्ट्रा के बजाय कमी-कुंजी संस्करण से परिचित कराया गया था।
templatetypedef

जवाबों:


68

नोड्स को फिर से स्थापित करने के बजाय कमी-कुंजी का उपयोग करने का कारण प्राथमिकता कतार में नोड्स की संख्या को छोटा रखना है, इस प्रकार प्राथमिकता कतार की कुल संख्या को छोटा रखना और प्रत्येक प्राथमिकता कतार संतुलन की लागत कम है।

दीजकस्ट्रा के एल्गोरिथ्म के कार्यान्वयन में, जो उनकी नई प्राथमिकताओं के साथ प्राथमिकता कतार में नोड्स को पुन: बनाता है, ग्राफ में प्रत्येक किनारों के लिए प्राथमिकता नोड में एक नोड जोड़ा जाता है। इसका मतलब यह है कि प्राथमिकता कतार पर m enqueue संचालन और m dequeue संचालन हैं, जो O (m T e + m T d ) का कुल रनटाइम देता है , जहां T e को प्राथमिकता कतार और T d में संलग्न करने के लिए आवश्यक समय है। प्राथमिकता कतार से हटने के लिए आवश्यक समय।

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

तो रनटाइम पर इसका क्या प्रभाव पड़ता है? यह इस बात पर निर्भर करता है कि आप किस प्राथमिकता की कतार का उपयोग करते हैं। यहाँ एक त्वरित तालिका है जो अलग-अलग प्राथमिकता वाले कतारों को दिखाती है और अलग-अलग दीजकस्ट्रा के एल्गोरिथ्म कार्यान्वयन के समग्र रनटाइम:

Queue          |  T_e   |  T_d   |  T_k   | w/o Dec-Key |   w/Dec-Key
---------------+--------+--------+--------+-------------+---------------
Binary Heap    |O(log N)|O(log N)|O(log N)| O(M log N)  |   O(M log N)
Binomial Heap  |O(log N)|O(log N)|O(log N)| O(M log N)  |   O(M log N)
Fibonacci Heap |  O(1)  |O(log N)|  O(1)  | O(M log N)  | O(M + N log N)

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

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

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

उम्मीद है की यह मदद करेगा!


1
+1: मैं ढेर के लिए खाता भूल गया हूँ। एक वक्रोक्ति, क्योंकि इन्सर्ट वर्जन के हीप में एक नोड प्रति एज होता है, यानी O (m), इसका एक्सेस टाइम O (log m) नहीं होना चाहिए, O (m log m) का कुल रन टाइम देता है? मेरा मतलब है, एक सामान्य ग्राफ में m, n ^ 2 से अधिक नहीं है, इसलिए यह O (m log n) तक कम हो जाता है, लेकिन एक ग्राफ में जहां दो नोड्स अलग-अलग भार के कई किनारों से जुड़ सकते हैं, m अनबाउंड है (बेशक , हम दावा कर सकते हैं कि दो नोड्स के बीच का न्यूनतम पथ केवल न्यूनतम किनारों का उपयोग करता है, और इसे सामान्य ग्राफ़ में कम करता है, लेकिन गैर के लिए, यह दिलचस्प है)।
रैंप

2
@ रैंपियन- आपके पास एक बिंदु है, लेकिन जब से मुझे लगता है कि यह आमतौर पर माना जाता है कि एल्गोरिथ्म को फायर करने से पहले समानांतर किनारों को कम कर दिया गया है, मुझे नहीं लगता कि ओ (लॉग एन) बनाम ओ (लॉग एम) बहुत मायने रखेगा। आमतौर पर m को O (n ^ 2) माना जाता है।
templatetypedef

27

2007 में, एक पेपर था जिसमें कमी-कुंजी संस्करण और सम्मिलित संस्करण का उपयोग करने के बीच निष्पादन समय में अंतर का अध्ययन किया गया था। Http://www.cs.utexas.edu/users/shaikat/papers/TR-07-54.pdf देखें

उनका मूल निष्कर्ष अधिकांश रेखांकन के लिए कमी-कुंजी का उपयोग नहीं करना था। विशेष रूप से विरल रेखांकन के लिए, गैर-कमी कुंजी कमी-कुंजी संस्करण की तुलना में काफी तेज है। अधिक विवरण के लिए कागज देखें।


7
cs.sunysb.edu/~rezaul/papers/TR-07-54.pdf उस पेपर के लिए एक कार्यशील कड़ी है।
एलियनोरा

चेतावनी: लिंक किए गए पेपर में एक बग है। पृष्ठ 16, फ़ंक्शन B.2: if k < d[u]होना चाहिए if k <= d[u]
Xeverous

2

दिज्क्स्त्र को लागू करने के दो तरीके हैं: एक का उपयोग करता है जो कमी-कुंजी का समर्थन करता है और दूसरा एक ढेर का समर्थन करता है जो इसका समर्थन नहीं करता है।

वे दोनों सामान्य रूप से मान्य हैं, लेकिन बाद वाला आमतौर पर पसंद किया जाता है। निम्नलिखित में मैं 'm' का उपयोग किनारों की संख्या को दर्शाने के लिए और 'n' को हमारे ग्राफ के वर्टिकल की संख्या को दर्शाने के लिए करूँगा:

यदि आप सबसे अच्छा संभव सबसे खराब स्थिति चाहते हैं, तो आप एक फाइबोनैचि हीप के साथ जाएंगे जो कमी-कुंजी का समर्थन करता है: आपको एक अच्छा O (m + nlogn) मिलेगा।

यदि आप औसत मामले की परवाह करते हैं, तो आप बाइनरी हीप का उपयोग कर सकते हैं: आपको O (m + nlog (m / n) logn) मिलेगा। प्रमाण यहाँ है , पृष्ठ 99/100। यदि ग्राफ़ सघन है (m >> n), तो यह एक और पिछला दोनों O (m) हैं।

यदि आप जानना चाहते हैं कि क्या होता है यदि आप उन्हें वास्तविक ग्राफ़ पर चलाते हैं, तो आप इस पेपर की जांच कर सकते हैं , जैसा कि मार्क मेकेटन ने अपने उत्तर में सुझाया था।

प्रयोगों के परिणाम क्या दिखाएंगे कि एक "सरल" ढेर अधिकांश मामलों में सबसे अच्छा परिणाम देगा।

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

इसी तरह के कारणों के लिए, एक ढेर जो एक कमी-कुंजी ऑपरेशन का समर्थन नहीं करता है, यहां तक ​​कि कम निरंतर कारक हैं और वास्तव में सबसे अच्छा प्रदर्शन करते हैं। खासकर यदि ग्राफ विरल है।

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