Graph Traversal (BFS vs DFS vs Stack)

4 篇文章 0 订阅
3 篇文章 0 订阅

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

BFSDFS是两种基本的图遍历算法,它们都可以用C语言来实现。 BFS(广度优先搜索)是一种逐层扫描图的算法,它从起点开始,遍历所有与该点相邻的点,然后再遍历与这些点相邻的点,直到遍历所有的点。BFS可以使用队列来实现,具体实现步骤如下: 1. 将起点加入队列中。 2. 每次从队列中取出一个节点,并将该节点的未遍历过的相邻节点加入队列中。 3. 标记已经遍历过的节点,避免重复遍历。 4. 重复步骤2,直到队列为空。 DFS(深度优先搜索)是一种递归或者栈的实现方式,它从起点开始,沿着一个路径一直走到底,然后回退到上一个节点,再沿着其他的路径继续遍历,直到遍历完所有的节点。DFS可以使用递归或栈来实现,具体实现步骤如下: 1. 对于当前节点,标记为已经遍历过。 2. 遍历当前节点的未遍历过的相邻节点。 3. 重复步骤1和2,直到遍历完所有节点。 以下是BFSDFS的C语言实现示例: BFS: ``` #include <stdio.h> #include <stdlib.h> #define MAX_SIZE 100 typedef struct node { int vertex; struct node* next; } Node; typedef struct graph { Node* vertices[MAX_SIZE]; int visited[MAX_SIZE]; int n; } Graph; void init_graph(Graph* g) { int i; g->n = 0; for (i = 0; i < MAX_SIZE; i++) { g->visited[i] = 0; g->vertices[i] = NULL; } } void add_edge(Graph* g, int u, int v) { Node* node = (Node*)malloc(sizeof(Node)); node->vertex = v; node->next = g->vertices[u]; g->vertices[u] = node; } void bfs(Graph* g, int start) { int queue[MAX_SIZE], front = 0, rear = 0, u, v; Node* node; queue[rear++] = start; g->visited[start] = 1; while (front != rear) { u = queue[front++]; printf("%d ", u); for (node = g->vertices[u]; node != NULL; node = node->next) { v = node->vertex; if (!g->visited[v]) { g->visited[v] = 1; queue[rear++] = v; } } } } int main() { Graph g; int i, j, k; init_graph(&g); g.n = 6; add_edge(&g, 0, 1); add_edge(&g, 0, 2); add_edge(&g, 1, 2); add_edge(&g, 2, 0); add_edge(&g, 2, 3); add_edge(&g, 3, 3); bfs(&g, 2); return 0; } ``` DFS: ``` #include <stdio.h> #include <stdlib.h> #define MAX_SIZE 100 typedef struct node { int vertex; struct node* next; } Node; typedef struct graph { Node* vertices[MAX_SIZE]; int visited[MAX_SIZE]; int n; } Graph; void init_graph(Graph* g) { int i; g->n = 0; for (i = 0; i < MAX_SIZE; i++) { g->visited[i] = 0; g->vertices[i] = NULL; } } void add_edge(Graph* g, int u, int v) { Node* node = (Node*)malloc(sizeof(Node)); node->vertex = v; node->next = g->vertices[u]; g->vertices[u] = node; } void dfs(Graph* g, int u) { Node* node = g->vertices[u]; g->visited[u] = 1; printf("%d ", u); while (node != NULL) { if (!g->visited[node->vertex]) { dfs(g, node->vertex); } node = node->next; } } int main() { Graph g; int i, j, k; init_graph(&g); g.n = 6; add_edge(&g, 0, 1); add_edge(&g, 0, 2); add_edge(&g, 1, 2); add_edge(&g, 2, 0); add_edge(&g, 2, 3); add_edge(&g, 3, 3); dfs(&g, 2); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值