2009-10-23 14 views
8

एक लिंक किए गए पेड़ के सभी नोड्स (सभी नोड्स के माता-पिता के संदर्भ में हैं, रूट नोड्स के माता-पिता के रूप में शून्य है) का दौरा करने का सबसे अच्छा तरीका क्या है, ताकि किसी भी नोड का दौरा किया जा सके अपने पूर्वजों के? ब्राउनी गैर-पुनरावर्ती के लिए इंगित करता है।एक पेड़ चलना, माता-पिता पहले

+1

संबंधित: http://stackoverflow.com/questions/754439/iterative-tree-walking –

उत्तर

6

छद्म कोड:

NodesToVisit = some stack or some list 
NodesToVisit.Push(RootNode) 

While NodesToVisit.Length > 0 
{ 
    CurNode = NodesToVisit.Pop() 
    For each Child C in CurNode 
     NodesToVisit.Push(C) 
    Visit(CurNode) (i.e. do whatever needs to be done) 
} 

संपादित: रिकर्सिव है या नहीं?
तकनीकी रूप से सही होने के लिए, और के रूप में इस पोस्ट में AndreyT और अन्य लोगों द्वारा बताया, इस दृष्टिकोण पुनरावर्ती एल्गोरिदम, जिसके तहत एक स्पष्ट रूप से प्रबंधित ढेर सीपीयू ढेर के एवज और जहां में प्रयोग किया जाता है का एक रूप है प्रत्यावर्तन जबकि लूप के स्तर पर होता है। इस ने कहा, यह एक पुनरावर्ती कार्यान्वयन से अलग है से प्रति सूक्ष्म लेकिन महत्वपूर्ण तरीके के एक जोड़े में:

  • केवल "चर" ढेर पर धकेल दिया जाता है; स्टैक पर कोई "स्टैक फ्रेम" और संबंधित रिटर्न पता नहीं है, केवल "वापसी पता" थोड़ी देर के लिए निहित है, और इसका एक उदाहरण भी है।
  • "स्टैक" का उपयोग एक सूची के रूप में किया जा सकता है जिससे किसी भी तरीके से तर्क को तोड़ने के बिना, सूची में कहीं भी "फ्रेम" कहीं भी लिया जा सकता है।
+0

ठीक है। यह एक अकादमिक सवाल नहीं था। यह एक व्यावहारिक सवाल था। यह मुझे सोचने या आगे पढ़ने के बिना संतोषजनक तरीके से जवाब देता है। धन्यवाद। (जब मुझे समय मिल जाए तो यह शायद मुझे बाद में सोचने लगेगा, लेकिन यह ठीक है ... उपयोगी, यहां तक ​​कि ...) नौकरी की गई। धन्यवाद फिर से :) – George

0

रूट (स्तर 0) पर नोड्स की एक सूची बनाएं, बदले में प्रत्येक नोड पर फिर से चलें और सीधे बच्चों की तलाश करें (जिनके पैरेंट नोड वह नोड है जिसे हम वर्तमान में देख रहे हैं) (स्तर 1), जब समाप्त हो गया स्तर 0 को पुनरावृत्त स्तर 1 पर ले जाएं, और तब तक जब तक आपके पास कोई अवकाश नोड्स न हो।

1

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

+0

आप प्रीऑर्डर स्थिति की गारंटी के लिए डेटा संरचना को किसी भी पुराने कंटेनर के लिए फीफो नहीं चाहते हैं। –

+0

प्रश्न में ऐसी कोई आवश्यकता नहीं थी। –

1

स्यूडोकोड में:

currentList = list(root) 
nextList = list() 
while currentList.count > 0: 
    foreach node in currentList: 
     nextList.add(node.children) 
    currentList = nextList 
3

आप में अग्रिम आदेश ट्रावर्सल के लिए देख रहे हैं। मुझे लगता है कि आप इसे कतार के साथ गैर-पुनरावर्ती कर सकते हैं:। छद्म कोड में:

खाली कतार बनाएं, फिर रूट नोड को दबाएं।

while nonempty(q) 
    node = pop(q) 
    visit(node) 
    foreach child(node) 
    push(q,child) 
+0

यह एक * रिकर्सिव एल्गोरिदम * का एक * गैर-पुनरावर्ती कार्यान्वयन * होगा। स्पष्ट स्टैक के साथ अंतर्निहित स्टैक को प्रतिस्थापित करना एक रिकर्सिव एल्गोरिदम को गैर-रिकर्सिव में बदलना नहीं है। वास्तव में, यह एल्गोरिदम बिल्कुल नहीं बदलता है। जो ऊपर है वह स्पष्ट रूप से रिकर्सिव है (जहां तक ​​एल्गोरिदम का संबंध है)। – AnT

+5

आमतौर पर जब लोग कहते हैं कि वे रिकर्सन नहीं चाहते हैं, तो वे फ़ंक्शन-स्तरीय रिकर्सन का जिक्र कर रहे हैं। यह उस शर्त को पूरा करता है। –

+0

अच्छा, कभी-कभी हाँ। हालांकि, जिस समस्या पर हम विचार कर रहे हैं वह विशेष रूप से गैर-पुनरावर्ती समाधान (यानी गैर-पुनरावर्ती एल्गोरिदम) की अनुमति देने के लिए तैयार किया गया है। मृत देनदार माता-पिता पॉइंटर्स की उपस्थिति है। आपका "गैर-पुनरावर्ती" समाधान पेरेंट पॉइंटर्स का उपयोग नहीं करता है। क्या आपको आश्चर्य नहीं है कि वे वहां क्यों हैं? वे विशेष रूप से एक वास्तविक गैर-पुनरावर्ती समाधान की अनुमति देने के लिए हैं, ओ (1) स्मृति आवश्यकता वाले एक। – AnT

1

आप रूट नोड में शुरू, और केवल नोड्स आप पहले से ही आने वाले लोगों की माता-पिता/बच्चों पर जाते हैं, वहाँ कोई रास्ता नहीं पेड़ पार करने के लिए ऐसी है कि आप अपने पूर्वजों जाने से पहले एक नोड की यात्रा है।

किसी भी तरह का ट्रैवर्सल, गहराई पहले (रिकर्सिव/स्टैक आधारित), चौड़ाई पहले (कतार आधारित), गहराई से सीमित, या सिर्फ उन्हें एक अनियमित सेट से बाहर खींचकर काम करेगा।

"सर्वोत्तम" विधि पेड़ पर निर्भर करती है। ब्रेड पहले कुछ शाखाओं के साथ एक बहुत लंबे पेड़ के लिए अच्छी तरह से काम करेगा। गहराई पहले कई शाखाओं के साथ पेड़ों के लिए अच्छी तरह से काम करेगा।

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

+0

तेह सेशन ने कहा "* कोई * नोड अपने पूर्वजों के सामने दौरा किया जाता है"। तो यह चारों ओर एक और तरीका है। – AnT

+0

दूसरा रास्ता क्या है? क्या आपने मेरा जवाब ठीक से पढ़ा? – Artelius

+0

शायद नहीं। मैंने सोचा था कि आपके पहले वाक्य में आपने दावा किया था कि समस्या हल नहीं की जा सकती है, क्योंकि यात्रा आदेश की आवश्यकता (जिसे मैंने माना है, आपको गलत समझा जाता है) संतुष्ट करना असंभव है। – AnT

3

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

+0

यह उल्लेख किया गया निरंतर स्मृति एल्गोरिदम है। आपके विचार अंतरिक्ष जटिलता के कारण – Artelius

1

मैं चौड़ाई पहली खोज से असहमत हूं क्योंकि अंतरिक्ष जटिलता अक्सर उस विशिष्ट खोज एल्गोरिदम का झुकाव होता है। संभावित रूप से पुनरावृत्त गहन एल्गोरिदम का उपयोग इस प्रकार के उपयोग के लिए एक बेहतर विकल्प है, और इसमें समान प्रकार के ट्रैवर्सल को चौड़ाई पहली खोज के रूप में शामिल किया गया है। सीमा से पहले खोज से सीमा से निपटने में मामूली मतभेद हैं, हालांकि इसे (छद्म) कोड के लिए बहुत कठिन नहीं होना चाहिए।

संदर्भ: कोई ढेर, निरंतर अंतरिक्ष: http://en.wikipedia.org/wiki/Iterative_deepening

+0

+1 - लेकिन क्यों न केवल गहराई-पहली खोज का उपयोग करें? – Artelius

+0

अभ्यास में कई पेड़ 'व्यापक', esp से गहरे होते हैं। एआई निर्णय लेने की प्रक्रिया में। प्रश्न यह नहीं बताता कि पेड़ सीमित है, लेकिन आप एक पाश में भाग सकते हैं। पुनरावृत्त गहराई के कारणों में से एक यह है कि यह पूरा हो गया है (समाधान मिलेगा)। – mduvall

1

यहाँ एक सही मायने में गैर पुनरावर्ती तरीका है। यह अजगर कोड मानता है कि प्रत्येक नोड बच्चों की एक सूची है, और इतना है कि 'सूचकांक' समारोह पहचान तुलना कर रहा है नोड वस्तुओं समानता परिभाषित नहीं करते कि,:

def walkTree(root, visit_func): 
    cur = root 
    nextChildIndex = 0 

    while True: 
     visit_func(cur) 

     while nextChildIndex >= len(cur.children) and cur is not root: 
      nextChildIndex = cur.parent.children.index(cur) + 1 
      cur = cur.parent 

     if nextChildIndex >= len(cur.children): 
      break 

     cur = cur.children[nextChildIndex] 
     nextChildIndex = 0 

मुझे यकीन है कि यह पॉलिश किया जा सकता है कर रहा हूँ थोड़ा, पढ़ने के लिए और अधिक संक्षिप्त और आसान बना दिया, लेकिन यह बात है।

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