210

I am looking for a non-recursive depth first search algorithm for a non-binary tree. Any help is very much appreciated.

Farbod Salamat-Zadeh
  • 19,687
  • 20
  • 75
  • 125
mousey
  • 11,601
  • 16
  • 52
  • 59
  • What exactly is a "non binary tree"? A graph? – Bart Kiers Mar 11 '11 at 21:33
  • 2
    @Bart Kiers A tree in general, judging by the tag. – biziclop Mar 11 '11 at 21:34
  • @Bart a tree can have any number of children. There's B tree, "2,3,4 tree", or lots of other types too. – corsiKa Mar 11 '11 at 21:35
  • 16
    Depth first search is a recursive algorithm. The answers below are recursively exploring nodes, they are just not using the system's call stack to do their recursion, and are using an explicit stack instead. – Null Set Mar 11 '11 at 21:44
  • @biziclop, @glowcoder, yes, you're probably right. Thanks. – Bart Kiers Mar 11 '11 at 21:45
  • 16
    @Null Set No, it's just a loop. By your definition, every computer program is recursive. (Which, in a certain sense of the word they are.) – biziclop Mar 11 '11 at 21:49
  • 1
    @Null Set: A tree is also a recursive data structure. – Gumbo Mar 11 '11 at 21:51
  • @biziclop I wouldn't call it *just* a loop. It's a loop and a stack! – Null Set Mar 11 '11 at 21:55
  • 1
    @Null Set That doesn't really matter in this case. Depending on which meaning of the word "recursion" you apply, either every computer program is recursive (computable) or just the ones that have functions that call themselves directly or indirectly. – biziclop Mar 11 '11 at 22:08
  • aaz's answer below avoids using a stack, possible only when nodes have links to their parents – joeytwiddle May 20 '12 at 11:44
  • most answers here use stack, but if you're going to use memory to keep track might as well use recursive and let call stack do that. I thought advantage of loop function over recursive was that you could go over large data without having to load it up in memory twice. – Muhammad Umer Nov 26 '17 at 02:07
  • 3
    @MuhammadUmer the main benefit of iterative over recursive approaches when iterative is considered less readable is that you can avoid max stack size / recursion depth constraints that most systems / programming languages implement to protect the stack. With an in memory stack your stack is only limited by the amount of memory your program is permitted to consume, which typically allows for a stack much larger than the max call stack size. – John B Feb 19 '18 at 23:27

18 Answers18

368

DFS:

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
}

The symmetry of the two is quite cool.

Update: As pointed out, take_first() removes and returns the first element in the list.

biziclop
  • 48,926
  • 12
  • 77
  • 104
  • 16
    +1 for noting how similar the two are when done non-recursively (as if they're radically different when they're recursive, but still...) – corsiKa Mar 11 '11 at 23:49
  • 3
    And then to add to the symmetry, if you use a min priority queue as the fringe instead, you have a single-source shortest path finder. – Mark Peters Mar 12 '11 at 19:31
  • 11
    BTW, the `.first()` function also removes the element from the list. Like `shift()` in many languages. `pop()` also works, and returns the child nodes in right-to-left order instead of left-to-right. – Ariel Jun 21 '11 at 03:57
  • Does this have any disadvantage to the recursive approach? E.g., stack size here is `O(depth * degree)`, instead of just `O(depth)` with the recursion. But then each element of recursion's stack is at least `O(degree)` I think? – max Apr 16 '12 at 16:46
  • It seems it can be easily modified from a tree to a general graph easily - just need to mark which nodes have been visited. Can this also work on an [implicit graph](http://en.wikipedia.org/wiki/Implicit_graph)? Can this work if I need post-order processing, rather than pre-order that it is doing as is? – max Apr 16 '12 at 16:48
  • @max This is just a simple pseudocode example, but it's easy to change it to avoid copying all the children in the queue (for example you just copy the parent node and the index of the next child). It works on implicit graphs if you replace `.children` with a call to the edge generation function. I haven't thought about post-order processing but I don't think this approach has much practical use in general, recursive code is bound to be easier to read, it's more of a demonstration of a principle. – biziclop Apr 16 '12 at 17:54
  • A deque or linked list are good structures for this, due to the first-element removal. See [this answer](http://stackoverflow.com/questions/1436020/c-stl-containers-whats-the-difference-between-deque-and-list) on deque performance as compared with list. – Engineer Dec 30 '12 at 23:28
  • @Nick The most efficient would be a something an array-backed list that wrapped around. So removing the first element would be as simple as nulling it out and incrementing the start pointer. You would need to expand the array if it wrapped around far enough to overwrite the start node, but that's not a problem, since it's an amortized cost. – corsiKa Jan 24 '13 at 21:09
  • @corsiKa Or you could use a stack :) – biziclop Jan 24 '13 at 21:22
  • @biziclop Yes, that would be ever so slightly more efficient, but then you're not 'taking from the front'. Well, unless you redefine front :-) – corsiKa Jan 24 '13 at 21:31
  • @corsiKa What you described looks suspiciously like a stack, except with a stack you're just hoping that it won't bump into anything as it grows. – biziclop Jan 24 '13 at 22:04
  • 1
    @biziclop My described structure runs into the same problem of growing that your typical array-based stack runs into. What my point was saying was that an array based structure is superior to a node-based structure, but that in order to not make it a "stack" you would need to wrap around the front. There's no denying that an array based stack (not my concoction) is the simplest, most efficient structure. – corsiKa Jan 25 '13 at 01:38
  • 7
    IMO, the DFS algo is slightly incorrect. Imagine 3 vertices all connected to each other. The progress should be: `gray(1st)->gray(2nd)->gray(3rd)->blacken(3rd)->blacken(2nd)->blacken(1st)`. But your code produces: `gray(1st)->gray(2nd)->gray(3rd)->blacken(2nd)->blacken(3rd)->blacken(1st)`. – batman Aug 02 '13 at 18:19
  • 3
    @learner I might be misunderstanding your example but if they're all connected to each other, that's not really a tree. – biziclop Aug 05 '13 at 11:00
  • @biziclop, yes. It is not a tree. So this doesn't apply to non-tree graphs? – batman Aug 06 '13 at 08:14
  • 2
    @learner The question was about trees. And in a tree it's guaranteed that you never encounter the same node twice, which is something this algorithm exploits when it throws away every node right after processing. If you're doing BFS and DFS on non-tree graphs, you must keep track of nodes already visited somehow to avoid visiting the same node twice. (Or for all eternity, if the graph has a cycle.) – biziclop Aug 07 '13 at 10:43
  • @biziclop I have an idea. I'm wondering that if my method can work for a graph with cycyles. I can just avoid to add dulplicated nodes to the stack. What I will do is to mark all the neighbors of the node which are popped out and add a `if (nodes are not marked)` to judge whether it is approapriate to be pushed to the stack. No matter the node is going to be visited or visited already. I just mark them to avoid the dulplicated push. Can this work? – Alston Jan 25 '14 at 13:40
  • @Stallman It's easier if you simply keep a list of all the nodes visited. – biziclop Jan 27 '14 at 11:04
  • @biziclop How can I know if the node is visited? If I only record the nodes to be visited, it still can't handle graph with cycles.Btw, I have spent lots of time in searching similar approach. But their psuedo-code are so abstract or complex. – Alston Jan 28 '14 at 11:53
  • @biziclop DFS is incorrect, there is no backtracking. You are moving deeper but never climb back, it will not work with more then 1 child. – Alex Burtsev Oct 29 '14 at 14:48
  • @AlexBurtsev As already mentioned, `first()` returns and removes the first element. – biziclop Oct 29 '14 at 14:51
  • So that root gets put and then immediately taken out? – fastcodejava Feb 19 '17 at 04:36
  • 2
    @fastcodejava Yes, that's what kickstarts the whole process. – biziclop Feb 19 '17 at 11:22
  • Is there a simple way (adding one or two lines) to return the path given a specific destination node in this code? – Omnomnious Oct 25 '18 at 00:51
  • 1
    "The symmetry of the two is quite cool."... except that the "DFS" version has no backtracking stage, which means that it is not "DFS" at all (at least in Dijkstra sense of the term). DFS is a major fundamental algorithm that serves as a backbone of many other algorithms built on top of it. And large number of those algorithms rely on the backtracking properties of true DFS. This "DFS" cannot be uses for that purpose. – AnT stands with Russia Feb 13 '19 at 19:03
  • @AnT That is true but if you need backtracking (which, given that we're talking about trees only, is unlikely), it's trivial to modify it to have it. Obviously at that point the symmetry disappears but I specifically wanted to concentrate on the similarities of the traversals themselves. – biziclop Feb 14 '19 at 10:42
  • 1
    This answer applies to trees only (as was asked for). However, a graph will iterate the neighbors of a node. In this case, you need to take an additional step to avoid re-tracing your path. Before adding a neighbor to the stack, check to make sure it's not the previous currentnode. You'll need another check to avoid retracing through cycles. These two checks could be merged into a single check to make sure a neighbor has not yet been traversed. – Rich Apodaca Mar 20 '19 at 18:16
  • This is just beautiful. Of course I had to optimize it because adding and removing the first item is inefficient in most languages (ended up pushing a reversed list of children and popping from the back). In python you can use a deque. I tried a few deque packages in JavaScript and none were as fast as my solution. – Fábio Santos Feb 26 '20 at 16:24
  • 1
    This answer changed my life – sugaith Aug 20 '22 at 15:44
48

You would use a stack that holds the nodes that were not visited yet:

stack.push(root)
while !stack.isEmpty() do
    node = stack.pop()
    for each node.childNodes do
        stack.push(stack)
    endfor
    // …
endwhile
Gumbo
  • 643,351
  • 109
  • 780
  • 844
  • 3
    @Gumbo I'm wondering that if it is a graph with cycyles. Can this work? I think I can just avoid to add dulplicated node to the stack and it can work. What I will do is to mark all the neighbors of the node which are popped out and add a `if (nodes are not marked)` to judge whether it is approapriate to be pushed to the stack. Can that work? – Alston Jan 25 '14 at 13:35
  • 1
    @Stallman You could remember the nodes that you have already visited. If you then only visit nodes which you haven’t visited yet, you won’t do any cycles. – Gumbo Jan 25 '14 at 13:38
  • @Gumbo What do you mean by `doing cycles`? I think I just want the order of DFS. Is that right or not, thank you. – Alston Jan 25 '14 at 13:42
  • Just wanted to point out that using a stack (LIFO) means depth first traversal. If you want to use breadth-first, go with a queue (FIFO) instead. – Per Lundberg May 21 '18 at 07:14
  • 6
    It's worth noting that to have equivalent code as the most popular @biziclop answer, you need to push child notes in reverse order (`for each node.childNodes.reverse() do stack.push(stack) endfor`). This is also probably what you want. Nice explanation why it's like that is in this video: https://www.youtube.com/watch?v=cZPXfl_tUkA endfor – Mariusz Pawelski Jul 12 '18 at 13:38
35

If you have pointers to parent nodes, you can do it without additional memory.

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

Note that if the child nodes are stored as an array rather than through sibling pointers, the next sibling can be found as:

def next_sibling(node):
    try:
        i =    node.parent.child_nodes.index(node)
        return node.parent.child_nodes[i+1]
    except (IndexError, AttributeError):
        return None
aaz
  • 5,136
  • 22
  • 18
  • This is a good solution because it does not use additional memory or manipulation of a list or stack (some good reasons to avoid recursion). However it is only possible if the tree nodes have links to their parents. – joeytwiddle May 20 '12 at 23:42
  • Thank you. This algorithm is great. But in this version you can't delete node's memory in visit function. This algorithm can convert tree to single-linked list by using "first_child" pointer. Than you can walk through it and free node's memory without recursion. – puchu Feb 20 '14 at 16:38
  • 6
    "If you have pointers to parent nodes, you can do it without additional memory" : storing pointer to parent nodes does use some "additional memory"... – Puttaraju May 31 '14 at 08:24
  • 1
    @rptr87 if it wasn't clear, without additional memory apart from those pointers. – Abhinav Gauniyal Nov 06 '16 at 13:07
  • This would fail for partial trees where node is not the absolute root, but can be easily fixed by `while not node.next_sibling or node is root:`. – Basel Shishani May 04 '17 at 14:14
5

An ES6 implementation based on biziclops great answer:

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);
  }
}
Max Leizerovich
  • 1,536
  • 1
  • 10
  • 7
5

Use a stack to track your nodes

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)

}
corsiKa
  • 81,495
  • 25
  • 153
  • 204
  • 1
    @Dave O. No, because you push back the children of the visited node in front of everything that's already there. – biziclop Mar 11 '11 at 22:04
  • I must have misinterpreted the semantics of [push_back](http://www.cplusplus.com/reference/stl/vector/push_back/) then. – Dave O. Mar 11 '11 at 22:14
  • @Dave you have a very good point. I was thinking it should be "pushing the rest of the queue back" not "push to the back." I will edit appropriately. – corsiKa Mar 11 '11 at 22:33
  • If you're pushing to the front it should be a stack. – flight Mar 11 '11 at 23:37
  • @Timmy yeah I'm not sure what I was thinking there. @quasiverse We normally think of a queue as a FIFO queue. A stack is defined as a LIFO queue. – corsiKa Mar 12 '11 at 00:01
  • @glowcoder- Can you change from using "Queue" to using "Stack?" I almost downvoted this because using a queue gives a BFS rather than a DFS (though you're treating to queue more like a stack, so it works out correctly) – templatetypedef Mar 13 '11 at 05:31
4

While "use a stack" might work as the answer to contrived interview question, in reality, it's just doing explicitly what a recursive program does behind the scenes.

Recursion uses the programs built-in stack. When you call a function, it pushes the arguments to the function onto the stack and when the function returns it does so by popping the program stack.

Chris Bennet
  • 587
  • 5
  • 13
  • 10
    With the important difference that the thread stack is severely limited, and the non-recursive algorithm would use the much more scalable heap. – Yam Marcovic May 04 '17 at 04:57
  • 3
    This is not just a contrived situation. I've used techniques like this on a few occasions in C# and JavaScript to gain significant performance gains over existing recursive call equivelants. It is often the case that managing the recursion with a stack instead of using the call stack is much faster and less resource intensive. There is a lot of overhead involved in placing a call context onto a stack vs the programmer being able to make practical decisions about what to place on a custom stack. – Jason Jackson Feb 08 '18 at 23:20
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);

                }
            }

The general logic is, push a node(starting from root) into the Stack, Pop() it and Print() value. Then if it has children( left and right) push them into the stack - push Right first so that you will visit Left child first(after visiting node itself). When stack is empty() you will have visited all nodes in Pre-Order.

Sanj
  • 261
  • 2
  • 6
2

Non-recursive DFS using ES6 generators

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 
  }    
}

It deviates from typical non-recursive DFS to easily detect when all reachable descendants of given node were processed and to maintain the current path in the list/stack.

Jarek Przygódzki
  • 4,284
  • 2
  • 31
  • 41
1

Suppose you want to execute a notification when each node in a graph is visited. The simple recursive implementation is:

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
}

Ok, now you want a stack-based implementation because your example doesn't work. Complex graphs might for instance cause this to blow the stack of your program and you need to implement a non-recursive version. The biggest issue is to know when to issue a notification.

The following pseudo-code works (mix of Java and C++ for readability):

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);
  }
}

It looks complicated but the extra logic needed for issuing notifications exists because you need to notify in reverse order of visit - DFS starts at root but notifies it last, unlike BFS which is very simple to implement.

For kicks, try following graph: nodes are s, t, v and w. directed edges are: s->t, s->v, t->w, v->w, and v->t. Run your own implementation of DFS and the order in which nodes should be visited must be: w, t, v, s A clumsy implementation of DFS would maybe notify t first and that indicates a bug. A recursive implementation of DFS would always reach w last.

1

FULL example WORKING code, without stack:

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);
}}

output: Breadth First Traversal- starting from vertex 2: 2 0 3 1 4 Depth First Traversal- starting from vertex 2: 2 3 4 1 0

  • `nodesToVisit.contains(s)` takes linear time in the number of elements in `nodesToVisit`. Alternatives include keeping track of which nodes were already visited in a boolean array with O(1) access time and O(numOfVertices) extra space. – nspo Dec 31 '20 at 10:25
1

Just wanted to add my python implementation to the long list of solutions. This non-recursive algorithm has discovery and finished events.


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)
Windel
  • 499
  • 4
  • 11
0

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

Just watched this video and came out with implementation. It looks easy for me to understand. Please critique this.

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()
}
Hengameh
  • 892
  • 7
  • 12
prog_guy
  • 796
  • 3
  • 7
  • 24
0

You can use a stack. I implemented graphs with Adjacency Matrix:

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();
        }
    }
}
kmetin
  • 253
  • 2
  • 4
  • 14
0

DFS iterative in Java:

//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;
}
Piyush Patel
  • 139
  • 2
  • 16
0

Using Stack, here are the steps to follow: Push the first vertex on the stack then,

  1. If possible, visit an adjacent unvisited vertex, mark it, and push it on the stack.
  2. If you can’t follow step 1, then, if possible, pop a vertex off the stack.
  3. If you can’t follow step 1 or step 2, you’re done.

Here's the Java program following the above steps:

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;
}
Yogesh Umesh Vaity
  • 41,009
  • 21
  • 145
  • 105
0

Pseudo-code based on @biziclop's answer:

  • Using only basic constructs: variables, arrays, if, while and for
  • Functions getNode(id) and getChildren(id)
  • Assuming known number of nodes N

NOTE: I use array-indexing from 1, not 0.

Breadth-first

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

Depth-first

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
Jonathan H
  • 7,591
  • 5
  • 47
  • 80
0

Here is a link to a java program showing DFS following both reccursive and non-reccursive methods and also calculating discovery and finish time, but no edge laleling.

    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);
                }
            }
        }
    }
}

Full source here.

getsuha
  • 711
  • 6
  • 16
-3
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);
    }
}
TylerH
  • 20,799
  • 66
  • 75
  • 101
iMobaio
  • 266
  • 4
  • 12