गैर-पुनरावर्ती गहराई पहले खोज एल्गोरिथ्म


173

मैं गैर-बाइनरी ट्री के लिए एक गैर-पुनरावर्ती गहराई पहले खोज एल्गोरिथ्म की तलाश कर रहा हूं। किसी भी प्रकार के मदद की बहुत सराहना की जाएगी।


1
@ बर्ट कियर्स एक पेड़ सामान्य रूप से, टैग द्वारा देखते हुए।
biziclop

13
गहराई पहली खोज एक पुनरावर्ती एल्गोरिदम है। नीचे दिए गए उत्तर पुनरावर्ती रूप से नोड्स की खोज कर रहे हैं, वे केवल सिस्टम के कॉल स्टैक का उपयोग अपनी पुनरावृत्ति करने के लिए नहीं कर रहे हैं, और इसके बजाय एक स्पष्ट स्टैक का उपयोग कर रहे हैं।
नल सेट

8
@ नल सेट नं, यह सिर्फ एक लूप है। आपकी परिभाषा के अनुसार, हर कंप्यूटर प्रोग्राम पुनरावर्ती है। (जो, वे शब्द के एक निश्चित अर्थ में हैं।)
बिज़िक्लोप

1
@ नल सेट: एक पेड़ भी एक पुनरावर्ती डेटा संरचना है।
गमबो

2
@MuhammadUmer पुनरावर्ती दृष्टिकोण पर पुनरावृत्ति का मुख्य लाभ जब पुनरावृत्ति को कम पठनीय माना जाता है, तो आप अधिकतम स्टैक आकार / पुनरावृत्ति की गहन बाधाओं से बच सकते हैं जो स्टैक की सुरक्षा के लिए अधिकांश सिस्टम / प्रोग्रामिंग भाषाएं लागू करते हैं। एक मेमोरी स्टैक के साथ आपका स्टैक केवल मेमोरी की मात्रा से सीमित होता है, जो आपके प्रोग्राम को उपभोग करने की अनुमति देता है, जो आम तौर पर स्टैक के लिए अधिकतम कॉल स्टैक आकार से बहुत बड़ा होने की अनुमति देता है।
जॉन बी

जवाबों:


313

डीएफएस:

list nodes_to_visit = {root};
while( nodes_to_visit isn't empty ) {
  currentnode = nodes_to_visit.take_first();
  nodes_to_visit.prepend( currentnode.children );
  //do something
}

BFS:

list nodes_to_visit = {root};
while( nodes_to_visit isn't empty ) {
  currentnode = nodes_to_visit.take_first();
  nodes_to_visit.append( currentnode.children );
  //do something
}

दोनों की समरूपता काफी शांत है।

अद्यतन: जैसा कि बताया गया है, take_first()सूची में पहला तत्व निकालता है और वापस करता है।


11
+1 यह देखने के लिए कि दोनों समान कैसे हैं जब गैर-पुनरावृत्ति किया जाता है (जैसे कि वे पुनरावर्ती होने पर मौलिक रूप से भिन्न होते हैं, लेकिन फिर भी ...)
corsiKa

3
और फिर समरूपता में जोड़ने के लिए, यदि आप एक प्राथमिक प्राथमिकता कतार को फ्रिंज के रूप में उपयोग करते हैं, तो आपके पास एकल-स्रोत सबसे छोटा पथ खोजक है।
मार्क पीटर्स

10
BTW, .first()फ़ंक्शन सूची से तत्व को भी हटा देता है। जैसे shift()कई भाषाओं में। pop()यह भी काम करता है, और बाएं-दाएं के बजाय दाएं से बाएं क्रम में बच्चे के नोड्स लौटाता है।
एरियल

5
IMO, DFS algo थोड़ा गलत है। सभी 3 कोने एक दूसरे से जुड़े हुए हैं। प्रगति होना चाहिए: gray(1st)->gray(2nd)->gray(3rd)->blacken(3rd)->blacken(2nd)->blacken(1st)। लेकिन आपका कोड उत्पादन करता है gray(1st)->gray(2nd)->gray(3rd)->blacken(2nd)->blacken(3rd)->blacken(1st):।
बैटमैन

3
@ लर्नर मैं आपके उदाहरण को गलत समझ सकता हूं, लेकिन अगर वे सभी एक-दूसरे से जुड़े हैं, तो यह वास्तव में एक पेड़ नहीं है।
biziclop

40

आप एक स्टैक का उपयोग करेंगे जो उन नोड्स को रखता है जो अभी तक नहीं गए थे:

stack.push(root)
while !stack.isEmpty() do
    node = stack.pop()
    for each node.childNodes do
        stack.push(stack)
    endfor
    // …
endwhile

2
@Gumbo मैं सोच रहा हूँ कि अगर यह cycyles के साथ एक ग्राफ है। क्या यह काम कर सकता है? मुझे लगता है कि मैं स्टैक पर ड्यूलप्लेटेड नोड जोड़ने से बच सकता हूं और यह काम कर सकता है। मैं क्या करूँगा नोड के सभी पड़ोसियों को चिह्नित करने के लिए जो बाहर पॉप किए गए हैं और एक if (nodes are not marked)जज को जोड़ते हैं कि क्या इसे स्टैक पर धकेल दिया जाना है। क्या वह काम कर सकता है?
एल्स्टन

1
@Stallman आप उन नोड्स को याद कर सकते हैं जिन्हें आप पहले ही देख चुके हैं। यदि आप केवल नोड्स पर जाते हैं, जो आपने अभी तक नहीं देखा है, तो आप कोई चक्र नहीं करेंगे।
गंबूबो

@Gumbo तुम क्या मतलब है doing cycles? मुझे लगता है कि मैं सिर्फ डीएफएस का आदेश चाहता हूं। यह सही है या नहीं, धन्यवाद।
एल्स्टन

बस यह इंगित करना चाहता था कि स्टैक (LIFO) का उपयोग करने का अर्थ है गहराई पहले ट्रैवर्सल। यदि आप चौड़ाई-प्रथम का उपयोग करना चाहते हैं, तो इसके बजाय एक कतार (FIFO) के साथ जाएं।
प्रति लुंडबर्ग

3
यह ध्यान देने योग्य है कि सबसे लोकप्रिय @biziclop उत्तर के रूप में समान कोड होने के लिए, आपको बच्चे के नोटों को रिवर्स ऑर्डर ( for each node.childNodes.reverse() do stack.push(stack) endfor) में धकेलना होगा । यह भी शायद आप चाहते हैं। अच्छा स्पष्टीकरण कि ऐसा क्यों है इस वीडियो में है: youtube.com/watch?v=cZPXfl_tUkA endfor
Mariusz

32

यदि आपके पास मूल नोड्स के संकेत हैं, तो आप इसे अतिरिक्त मेमोरी के बिना कर सकते हैं।

def dfs(root):
    node = root
    while True:
        visit(node)
        if node.first_child:
            node = node.first_child      # walk down
        else:
            while not node.next_sibling:
                if node is root:
                    return
                node = node.parent       # walk up ...
            node = node.next_sibling     # ... and right

ध्यान दें कि यदि बच्चे के नोड्स को सिबलिंग पॉइंटर्स के बजाय एक सरणी के रूप में संग्रहीत किया जाता है, तो अगले सिबलिंग को निम्न प्रकार से पाया जा सकता है:

def next_sibling(node):
    try:
        i =    node.parent.child_nodes.index(node)
        return node.parent.child_nodes[i+1]
    except (IndexError, AttributeError):
        return None

यह एक अच्छा समाधान है क्योंकि इसमें सूची या स्टैक की अतिरिक्त मेमोरी या हेरफेर का उपयोग नहीं किया जाता है (पुनरावृत्ति से बचने के कुछ अच्छे कारण)। हालांकि यह केवल तभी संभव है जब पेड़ के नोड्स का उनके माता-पिता से संबंध हो।
joeytwiddle

धन्यवाद। यह एल्गोरिथम महान है। लेकिन इस संस्करण में आप विज़िट फ़ंक्शन में नोड की मेमोरी को हटा नहीं सकते हैं। यह एल्गोरिथ्म "फर्स्ट_चिल्ड" पॉइंटर का उपयोग करके पेड़ को एकल-लिंक्ड सूची में बदल सकता है। थान आप इसके माध्यम से चल सकते हैं और बिना किसी पुनरावृत्ति के नोड की मेमोरी मुक्त कर सकते हैं।
पुचू

6
"यदि आपके पास मूल नोड्स के लिए संकेत हैं, तो आप इसे अतिरिक्त मेमोरी के बिना भी कर सकते हैं": पेरेंट नोड्स के लिए पॉइंटर को स्टोर करने से कुछ "अतिरिक्त मेमोरी" का उपयोग होता है ...
rptr

1
@ rptr87 अगर यह स्पष्ट नहीं था, तो बिना अतिरिक्त मेमोरी के उन पॉइंटर्स के अलावा।
अभिनव गौनियाल 13

यह आंशिक पेड़ों के लिए विफल होगा जहां नोड पूर्ण जड़ नहीं है, लेकिन आसानी से तय किया जा सकता है while not node.next_sibling or node is root:
बेसल शीशानी

5

अपने नोड्स को ट्रैक करने के लिए एक स्टैक का उपयोग करें

Stack<Node> s;

s.prepend(tree.head);

while(!s.empty) {
    Node n = s.poll_front // gets first node

    // do something with q?

    for each child of n: s.prepend(child)

}

1
@ ओ। नहीं, क्योंकि आप पहले से ही वहां मौजूद हर चीज के सामने आने वाले बच्चों के पीछे धकेल देते हैं।
biziclop

मुझे पुश_बैक के शब्दार्थ की गलत व्याख्या करनी चाहिए थी ।
डेव ओ।

@ क्या आपके पास बहुत अच्छा बिंदु है। मैं सोच रहा था कि इसे "बाकी कतार को पीछे धकेलना चाहिए" नहीं "पीठ पर धक्का देना चाहिए।" मैं उचित रूप से संपादित करूंगा।
corsiKa

यदि आप सामने की ओर जोर दे रहे हैं तो यह एक स्टैक होना चाहिए।
फ्लाइट

@ टिम्मी हाँ मुझे यकीन नहीं है कि मैं वहाँ क्या सोच रहा था। @quasiverse हम आम तौर पर एक कतार को FIFO कतार के रूप में सोचते हैं। एक स्टैक को एक LIFO कतार के रूप में परिभाषित किया गया है।
corsiKa

4

हालांकि "स्टैक का उपयोग करें" वास्तव में, साक्षात्कार के प्रश्न से संबंधित प्रश्न के उत्तर के रूप में काम कर सकता है, यह सिर्फ स्पष्ट रूप से कर रहा है कि एक पुनरावर्ती कार्यक्रम पर्दे के पीछे क्या करता है।

रिकर्सन प्रोग्राम में निर्मित स्टैक का उपयोग करता है। जब आप किसी फ़ंक्शन को कॉल करते हैं, तो यह फ़ंक्शन के तर्कों को स्टैक पर धकेलता है और जब फ़ंक्शन वापस आता है तो प्रोग्राम स्टैक को पॉप अप करके ऐसा करता है।


7
महत्वपूर्ण अंतर के साथ कि थ्रेड स्टैक गंभीर रूप से सीमित है, और गैर-पुनरावर्ती एल्गोरिथ्म बहुत अधिक स्केलेबल ढेर का उपयोग करेगा।
यम मार्कोविच

1
यह केवल एक आकस्मिक स्थिति नहीं है। मैंने मौजूदा पुनरावर्ती कॉल समकक्षों पर महत्वपूर्ण प्रदर्शन लाभ प्राप्त करने के लिए C # और जावास्क्रिप्ट में कुछ अवसरों पर इस तरह की तकनीकों का उपयोग किया है। यह अक्सर ऐसा होता है कि कॉल स्टैक का उपयोग करने के बजाय एक स्टैक के साथ पुनरावृत्ति का प्रबंधन बहुत तेज और कम संसाधन गहन होता है। एक ढेर पर एक कॉल संदर्भ रखने में बहुत अधिक उपरि शामिल है। प्रोग्रामर बनाम कस्टम स्टैक पर क्या करना है, इसके बारे में व्यावहारिक निर्णय लेने में सक्षम होना।
जेसन जैक्सन

4

एक ES6 कार्यान्वयन biziclops महान जवाब पर आधारित है:

root = {
  text: "root",
  children: [{
    text: "c1",
    children: [{
      text: "c11"
    }, {
      text: "c12"
    }]
  }, {
    text: "c2",
    children: [{
      text: "c21"
    }, {
      text: "c22"
    }]
  }, ]
}

console.log("DFS:")
DFS(root, node => node.children, node => console.log(node.text));

console.log("BFS:")
BFS(root, node => node.children, node => console.log(node.text));

function BFS(root, getChildren, visit) {
  let nodesToVisit = [root];
  while (nodesToVisit.length > 0) {
    const currentNode = nodesToVisit.shift();
    nodesToVisit = [
      ...nodesToVisit,
      ...(getChildren(currentNode) || []),
    ];
    visit(currentNode);
  }
}

function DFS(root, getChildren, visit) {
  let nodesToVisit = [root];
  while (nodesToVisit.length > 0) {
    const currentNode = nodesToVisit.shift();
    nodesToVisit = [
      ...(getChildren(currentNode) || []),
      ...nodesToVisit,
    ];
    visit(currentNode);
  }
}


3
PreOrderTraversal is same as DFS in binary tree. You can do the same recursion 
taking care of Stack as below.

    public void IterativePreOrder(Tree root)
            {
                if (root == null)
                    return;
                Stack s<Tree> = new Stack<Tree>();
                s.Push(root);
                while (s.Count != 0)
                {
                    Tree b = s.Pop();
                    Console.Write(b.Data + " ");
                    if (b.Right != null)
                        s.Push(b.Right);
                    if (b.Left != null)
                        s.Push(b.Left);

                }
            }

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


2

ईएस 6 जनरेटर का उपयोग करके गैर-पुनरावर्ती डीएफएस

class Node {
  constructor(name, childNodes) {
    this.name = name;
    this.childNodes = childNodes;
    this.visited = false;
  }
}

function *dfs(s) {
  let stack = [];
  stack.push(s);
  stackLoop: while (stack.length) {
    let u = stack[stack.length - 1]; // peek
    if (!u.visited) {
      u.visited = true; // grey - visited
      yield u;
    }

    for (let v of u.childNodes) {
      if (!v.visited) {
        stack.push(v);
        continue stackLoop;
      }
    }

    stack.pop(); // black - all reachable descendants were processed 
  }    
}

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


1

मान लीजिए कि आप किसी नोटिफिकेशन को निष्पादित करना चाहते हैं जब ग्राफ़ में प्रत्येक नोड का दौरा किया जाता है। सरल पुनरावर्ती कार्यान्वयन है:

void DFSRecursive(Node n, Set<Node> visited) {
  visited.add(n);
  for (Node x : neighbors_of(n)) {  // iterate over all neighbors
    if (!visited.contains(x)) {
      DFSRecursive(x, visited);
    }
  }
  OnVisit(n);  // callback to say node is finally visited, after all its non-visited neighbors
}

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

निम्नलिखित छद्म कोड काम करता है (पठनीयता के लिए जावा और सी ++ का मिश्रण):

void DFS(Node root) {
  Set<Node> visited;
  Set<Node> toNotify;  // nodes we want to notify

  Stack<Node> stack;
  stack.add(root);
  toNotify.add(root);  // we won't pop nodes from this until DFS is done
  while (!stack.empty()) {
    Node current = stack.pop();
    visited.add(current);
    for (Node x : neighbors_of(current)) {
      if (!visited.contains(x)) {
        stack.add(x);
        toNotify.add(x);
      }
    }
  }
  // Now issue notifications. toNotifyStack might contain duplicates (will never
  // happen in a tree but easily happens in a graph)
  Set<Node> notified;
  while (!toNotify.empty()) {
  Node n = toNotify.pop();
  if (!toNotify.contains(n)) {
    OnVisit(n);  // issue callback
    toNotify.add(n);
  }
}

यह जटिल दिखता है, लेकिन अधिसूचना जारी करने के लिए आवश्यक अतिरिक्त तर्क मौजूद है क्योंकि आपको यात्रा के रिवर्स ऑर्डर में सूचित करने की आवश्यकता है - DFS रूट पर शुरू होता है, लेकिन BFS के विपरीत इसे अंतिम रूप से सूचित करता है, जिसे लागू करना बहुत सरल है।

किक्स के लिए, निम्नलिखित ग्राफ का प्रयास करें: नोड्स s, t, v और w हैं। निर्देशित किनारे हैं: s-> t, s-> v, t-> w, v-> w, और v-> t। डीएफएस के अपने स्वयं के कार्यान्वयन को चलाएं और जिस क्रम में नोड्स का दौरा किया जाना चाहिए वह होना चाहिए: डब्ल्यू, टी, वी, एस डीएफएस का अनाड़ी कार्यान्वयन शायद पहले टी को सूचित करेगा और यह एक बग को इंगित करता है। डीएफएस का पुनरावर्ती कार्यान्वयन हमेशा अंतिम तक पहुंच जाएगा।


1

स्टैक के बिना पूरा उदाहरण काम कोड,:

import java.util.*;

class Graph {
private List<List<Integer>> adj;

Graph(int numOfVertices) {
    this.adj = new ArrayList<>();
    for (int i = 0; i < numOfVertices; ++i)
        adj.add(i, new ArrayList<>());
}

void addEdge(int v, int w) {
    adj.get(v).add(w); // Add w to v's list.
}

void DFS(int v) {
    int nodesToVisitIndex = 0;
    List<Integer> nodesToVisit = new ArrayList<>();
    nodesToVisit.add(v);
    while (nodesToVisitIndex < nodesToVisit.size()) {
        Integer nextChild= nodesToVisit.get(nodesToVisitIndex++);// get the node and mark it as visited node by inc the index over the element.
        for (Integer s : adj.get(nextChild)) {
            if (!nodesToVisit.contains(s)) {
                nodesToVisit.add(nodesToVisitIndex, s);// add the node to the HEAD of the unvisited nodes list.
            }
        }
        System.out.println(nextChild);
    }
}

void BFS(int v) {
    int nodesToVisitIndex = 0;
    List<Integer> nodesToVisit = new ArrayList<>();
    nodesToVisit.add(v);
    while (nodesToVisitIndex < nodesToVisit.size()) {
        Integer nextChild= nodesToVisit.get(nodesToVisitIndex++);// get the node and mark it as visited node by inc the index over the element.
        for (Integer s : adj.get(nextChild)) {
            if (!nodesToVisit.contains(s)) {
                nodesToVisit.add(s);// add the node to the END of the unvisited node list.
            }
        }
        System.out.println(nextChild);
    }
}

public static void main(String args[]) {
    Graph g = new Graph(5);

    g.addEdge(0, 1);
    g.addEdge(0, 2);
    g.addEdge(1, 2);
    g.addEdge(2, 0);
    g.addEdge(2, 3);
    g.addEdge(3, 3);
    g.addEdge(3, 1);
    g.addEdge(3, 4);

    System.out.println("Breadth First Traversal- starting from vertex 2:");
    g.BFS(2);
    System.out.println("Depth First Traversal- starting from vertex 2:");
    g.DFS(2);
}}

आउटपुट: चौड़ाई प्रथम ट्रावर्सल- वर्टेक्स २ से शुरू: २ ० ३ ४ ४ डेप्थ फर्स्ट ट्रावर्सल- वर्टेक्स २ से शुरू: २ ३ ४ १ ०


0

आप एक स्टैक का उपयोग कर सकते हैं। मैंने आसन्न मैट्रिक्स के साथ रेखांकन लागू किया:

void DFS(int current){
    for(int i=1; i<N; i++) visit_table[i]=false;
    myStack.push(current);
    cout << current << "  ";
    while(!myStack.empty()){
        current = myStack.top();
        for(int i=0; i<N; i++){
            if(AdjMatrix[current][i] == 1){
                if(visit_table[i] == false){ 
                    myStack.push(i);
                    visit_table[i] = true;
                    cout << i << "  ";
                }
                break;
            }
            else if(!myStack.empty())
                myStack.pop();
        }
    }
}

0

जावा में DFS पुनरावृत्ति:

//DFS: Iterative
private Boolean DFSIterative(Node root, int target) {
    if (root == null)
        return false;
    Stack<Node> _stack = new Stack<Node>();
    _stack.push(root);
    while (_stack.size() > 0) {
        Node temp = _stack.peek();
        if (temp.data == target)
            return true;
        if (temp.left != null)
            _stack.push(temp.left);
        else if (temp.right != null)
            _stack.push(temp.right);
        else
            _stack.pop();
    }
    return false;
}

प्रश्न गैर बाइनरी ट्री के
user3743222

अनंत लूप से बचने के लिए आपको एक विज़िट किए गए नक्शे की आवश्यकता है
सर्पिलून

0

http://www.youtube.com/watch?v=zLZhSSXAwxI

बस इस वीडियो को देखा और कार्यान्वयन के साथ बाहर आया। मुझे समझना आसान लगता है। कृपया इसकी आलोचना करें।

visited_node={root}
stack.push(root)
while(!stack.empty){
  unvisited_node = get_unvisited_adj_nodes(stack.top());
  If (unvisited_node!=null){
     stack.push(unvisited_node);  
     visited_node+=unvisited_node;
  }
  else
     stack.pop()
}

0

उपयोग करने के लिए Stack, यहाँ निम्नलिखित चरणों का पालन किया गया है: स्टैक पर पहले शीर्ष को पुश करें, फिर

  1. यदि संभव हो, तो एक आसन्न अप्रकाशित शीर्ष पर जाएं, इसे चिह्नित करें, और इसे स्टैक पर धक्का दें।
  2. यदि आप चरण 1 का पालन नहीं कर सकते हैं, तो, यदि संभव हो, तो स्टैक से एक शीर्ष पॉप करें।
  3. यदि आप चरण 1 या चरण 2 का पालन नहीं कर सकते हैं, तो आप कर रहे हैं।

उपरोक्त चरणों का पालन जावा प्रोग्राम है:

public void searchDepthFirst() {
    // begin at vertex 0
    vertexList[0].wasVisited = true;
    displayVertex(0);
    stack.push(0);
    while (!stack.isEmpty()) {
        int adjacentVertex = getAdjacentUnvisitedVertex(stack.peek());
        // if no such vertex
        if (adjacentVertex == -1) {
            stack.pop();
        } else {
            vertexList[adjacentVertex].wasVisited = true;
            // Do something
            stack.push(adjacentVertex);
        }
    }
    // stack is empty, so we're done, reset flags
    for (int j = 0; j < nVerts; j++)
            vertexList[j].wasVisited = false;
}

0
        Stack<Node> stack = new Stack<>();
        stack.add(root);
        while (!stack.isEmpty()) {
            Node node = stack.pop();
            System.out.print(node.getData() + " ");

            Node right = node.getRight();
            if (right != null) {
                stack.push(right);
            }

            Node left = node.getLeft();
            if (left != null) {
                stack.push(left);
            }
        }

0

@ Biziclop के उत्तर के आधार पर छद्म कोड:

  • केवल मूल निर्माणों का उपयोग करना: चर, सरणियाँ, यदि, जबकि और इसके लिए
  • कार्य getNode(id)औरgetChildren(id)
  • ज्ञात संख्याओं को नोड्स मानते हैं N

नोट: मैं 1, नहीं 0 से सरणी-अनुक्रमण का उपयोग करता हूं।

चौड़ाई-पहले

S = Array(N)
S[1] = 1; // root id
cur = 1;
last = 1
while cur <= last
    id = S[cur]
    node = getNode(id)
    children = getChildren(id)

    n = length(children)
    for i = 1..n
        S[ last+i ] = children[i]
    end
    last = last+n
    cur = cur+1

    visit(node)
end

गहराई-प्रथम

S = Array(N)
S[1] = 1; // root id
cur = 1;
while cur > 0
    id = S[cur]
    node = getNode(id)
    children = getChildren(id)

    n = length(children)
    for i = 1..n
        // assuming children are given left-to-right
        S[ cur+i-1 ] = children[ n-i+1 ] 

        // otherwise
        // S[ cur+i-1 ] = children[i] 
    end
    cur = cur+n-1

    visit(node)
end

0

यहाँ एक जावा प्रोग्राम का लिंक दिया गया है, जो डीएसएफ को रीक्रसिव और नॉन-रीक्रसिव दोनों तरीकों से दिखाता है और डिस्कवरी और फिनिश टाइम की गणना भी करता है, लेकिन कोई एज लैलालिंग नहीं।

    public void DFSIterative() {
    Reset();
    Stack<Vertex> s = new Stack<>();
    for (Vertex v : vertices.values()) {
        if (!v.visited) {
            v.d = ++time;
            v.visited = true;
            s.push(v);
            while (!s.isEmpty()) {
                Vertex u = s.peek();
                s.pop();
                boolean bFinished = true;
                for (Vertex w : u.adj) {
                    if (!w.visited) {
                        w.visited = true;
                        w.d = ++time;
                        w.p = u;
                        s.push(w);
                        bFinished = false;
                        break;
                    }
                }
                if (bFinished) {
                    u.f = ++time;
                    if (u.p != null)
                        s.push(u.p);
                }
            }
        }
    }
}

पूर्ण स्रोत यहाँ


0

बस समाधानों की लंबी सूची में मेरे अजगर कार्यान्वयन को जोड़ना चाहता था। इस गैर-पुनरावर्ती एल्गोरिथ्म में खोज और समाप्त होने वाली घटनाएं हैं।


worklist = [root_node]
visited = set()
while worklist:
    node = worklist[-1]
    if node in visited:
        # Node is finished
        worklist.pop()
    else:
        # Node is discovered
        visited.add(node)
        for child in node.children:
            worklist.append(child)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.