2008-08-07 21 views
37

मैं एक निर्देशित ग्राफ 'serialize' करने के लिए एक सरल एल्गोरिदम की तलाश में हूं। विशेष रूप से मुझे अपने निष्पादन आदेश पर परस्पर निर्भरता वाली फ़ाइलों का एक सेट मिला है, और मैं संकलन समय पर सही क्रम खोजना चाहता हूं। मुझे पता है कि यह करना काफी आम बात होनी चाहिए - कंपलर हर समय ऐसा करते हैं - लेकिन मेरा google-fu आज कमजोर रहा है। इसके लिए 'जाने-जाने' एल्गोरिदम क्या है?ग्राफ क्रमबद्धता

उत्तर

54

Topological Sort (विकिपीडिया से):

ग्राफ सिद्धांत रूप में, एक सांस्थितिकीय तरह या एक निर्देशित अचक्रीय ग्राफ (DAG) का संस्थानिक आदेश अपने नोड्स की एक रेखीय आदेश जिसमें प्रत्येक नोड आता है सभी नोड्स से पहले इसमें आउटबाउंड किनारों हैं। प्रत्येक डीएजी में एक या अधिक टोपोलॉजिकल प्रकार हैं।

छद्म कोड:

L ← Empty list where we put the sorted elements 
Q ← Set of all nodes with no incoming edges 
while Q is non-empty do 
    remove a node n from Q 
    insert n into L 
    for each node m with an edge e from n to m do 
     remove edge e from the graph 
     if m has no other incoming edges then 
      insert m into Q 
if graph has edges then 
    output error message (graph has a cycle) 
else 
    output message (proposed topologically sorted order: L) 
+8

एह ... विकिपीडिया से सीधे कॉपी किया गया? – Benjol

+1

हाँ, कृपया स्रोत –

+0

धन्यवाद उद्धरण। मुझे इस तथ्य का उपयोग करने में मदद मिली कि निर्भरता पेड़ को इस विधि का उपयोग करके हल किया जा सकता है। :-) –

1

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

जब तक यह एक डीएजी है, यह सरल ढेर-आधारित चलना तुच्छ होना चाहिए।

+0

हां, इस तरह आप इसे करते हैं। इसे गहराई से पहली खोज (डीएफएस) कहा जाता है। और जब तक आप निश्चित नहीं हैं कि आपके पास एक डीएजी है, तो आप पिछली किनारों के लिए जरूरी है, अन्यथा एक चक्र आपको अनंत लूप में भेज देगा। एक foreach के बजाय – sleske

0

मैं एक काफी अनुभवहीन पुनरावर्ती एल्गोरिदम (स्यूडोकोड) के साथ आ गया है:

Map<Object, List<Object>> source; // map of each object to its dependency list 
List<Object> dest; // destination list 

function resolve(a): 
    if (dest.contains(a)) return; 
    foreach (b in source[a]): 
     resolve(b); 
    dest.add(a); 

foreach (a in source): 
    resolve(a); 

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

किसी के पास कुछ बेहतर है?

+0

थोड़ी देर के लिए उपयोग करते हैं, डेटा को पार करने वाले दो पॉइंटर्स को बनाए रखते हैं, जो एक अग्रणी कदम है जो एक ही चरण और पीछे की ओर एक पीछे है। अग्रणी सूचक Acutal संकल्पों को संभालता है और यदि यह कभी पीछे पीछे सूचक को गोद लेता है तो एक चक्र होता है। – Tenderdude

1

ग्राफ चक्र होते हैं, तो आपकी फ़ाइलों के लिए कैसे वहाँ की अनुमति दी मौजूद कर सकते हैं निष्पादन के आदेश? मुझे ऐसा लगता है कि यदि ग्राफ में चक्र होते हैं, तो आपके पास कोई समाधान नहीं है, और यह उपरोक्त एल्गोरिदम द्वारा सही ढंग से रिपोर्ट किया गया है।

+0

हां, ग्राफ़ में चक्र होने पर एक स्थलीय प्रकार संभव नहीं है। यह असली दुनिया से मेल खाता है: यदि मैं आपको ए से पहले बी, * और * बी से पहले ए से पूछता हूं, तो आप मुझे संतुष्ट करने के लिए कोई रास्ता नहीं है ;-)। – sleske

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