Graph Traversal (BFS vs DFS vs Stack)

BFS template: (from wikipedia)

1  procedure BFS(G,v) is
2      create a queue Q
3      create a set V
4      add v to V
5      enqueue v onto Q
6      while Q is not empty loop
7         t ← Q.dequeue()
8         if t is what we are looking for then
9            return t
10        end if
11        for all edges e in G.adjacentEdges(t) loop
12           u ← G.adjacentVertex(t,e)
13           if u is not in V then
14               add u to V
15               enqueue u onto Q
16           end if
17        end loop
18     end loop
19     return none
20 end BFS

Recursive DFS template:

1  procedure DFS(G,v):
2      label v as discovered
3      for all edges from v to w in G.adjacentEdges(v) do
4          if vertex w is not labeled as discovered then
5              recursively call DFS(G,w)

Stack-based DFS implementation1

def dfs(G,s):
    visited = {s}
    stack = [iter(G[s])]
    while stack:
        try:
            w = stack[-1].next()
            if w not in visited:
                visited.add(w)
                stack.append(iter(G[w]))
        except StopIteration:
            stack.pop()


Stack-based DFS implementation2 (DFS in reverse order of adj list)

1  procedure DFS-iterative(G,v):
2      let S be a stack
3      S.push(v)
4      while S is not empty
5            vS.pop() 
6            if v is not labeled as discovered:
7                label v as discovered
8                for all edges from v to w in G.adjacentEdges(v) do
9                    S.push(w)
The non-recursive implementation is similar to breadth-first search but differs from it in two ways: it uses a stack instead of a queue, and it delays checking whether a vertex has been discovered until the vertex is popped from the stack rather than making this check before pushing the vertex.


Code for Stack-based DFS Implementation1

The from start to current path is maintained implicitly in the stack.

#include <iostream>
#include <vector>
#include <stack>
#include <set>
#include <unordered_set>
using namespace std;

struct GraphNode
{
	int label;
	vector<GraphNode*> adjs;
	GraphNode(int x): label(x){}
};

typedef vector<GraphNode*>::iterator adj_iter;

vector<vector<pair<GraphNode*, adj_iter> > >  allSimplePathDFSIterative(GraphNode *start)
{
	vector<vector<pair<GraphNode*, adj_iter> > > result;
	vector<pair<GraphNode*,adj_iter> > stack;
	unordered_set<GraphNode*> hash;

	stack.push_back(make_pair(start, start->adjs.begin()));

	while(!stack.empty())
	{
		GraphNode *cur = stack.back().first;
		adj_iter iter = stack.back().second;

		if(iter == cur->adjs.begin())
		{
			cout << cur->label << endl;
			hash.insert(cur);

			if(true/*current path meets requirement*/)
			{
				result.push_back(stack);
			}
		}

		if(iter != cur->adjs.end())
		{
			GraphNode *next = *iter;
			stack.back().second = ++iter;
			if(hash.count(next) == 0)
			{
				stack.push_back(make_pair(next, next->adjs.begin()));
			}
		}
		else
		{
			stack.pop_back();
		}
	}
	return result;
}

int main() {
	GraphNode *n0 = new GraphNode(0);
	GraphNode *n1 = new GraphNode(1);
	GraphNode *n2 = new GraphNode(2);
	GraphNode *n3 = new GraphNode(3);
	GraphNode *n4 = new GraphNode(4);
	GraphNode *n5 = new GraphNode(5);

	n0->adjs.push_back(n1);
	n0->adjs.push_back(n2);
	n0->adjs.push_back(n5);

	n1->adjs.push_back(n0);
	n1->adjs.push_back(n2);

	n2->adjs.push_back(n0);
	n2->adjs.push_back(n1);
	n2->adjs.push_back(n3);
	n2->adjs.push_back(n4);

	n3->adjs.push_back(n2);
	n3->adjs.push_back(n4);
	n3->adjs.push_back(n5);

	n4->adjs.push_back(n2);
	n4->adjs.push_back(n3);

	n5->adjs.push_back(n0);
	n5->adjs.push_back(n3);

	auto res = allSimplePathDFSIterative(n0);

	for(int i=0; i<res.size(); i++)
	{
		for(int j=0; j<res[i].size(); j++)
		{
			cout << res[i][j].first->label << " ";
		}
		cout << endl;
	}

	return 0;
}


參考:

http://en.wikipedia.org/wiki/Depth-first_search

http://en.wikipedia.org/wiki/Breadth-first_search

Stack-based graph traversal ≠ depth first search      http://11011110.livejournal.com/279880.html

http://algs4.cs.princeton.edu/41undirected/NonrecursiveDFS.java

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章