图算法(1)-广度优先遍历

图的广度优先遍历其实并不难,当边的权重相同时,由图的广度优先遍历可以得到其余节点到源节点的最短路径。我使用了邻接表实现了这个算法。

首先来看看图的数据结构的定义:

 1 struct Edge
 2 {
 3     int end;
 4 };
 5 
 6 enum Color {WHITE, GRAY, BLACK};
 7 
 8 struct Node
 9 {
10     std::string value;
11     std::vector<Edge> edges;
12     int d;
13     int p;
14     Color color;
15 };
16 
17 struct Graph
18 {
19     std::vector<Node> nodes;
20     std::map<std::string, int> nodemap;
21 
22     void InsertNode(std::string value)
23     {
24         Node n;
25         n.value = value;
26         nodes.push_back(n);
27         nodemap[value] = nodes.size() - 1;
28     }
29 
30     void InsertEdge(int begin, int end)
31     {
32         Edge e = { end };
33         nodes[begin].edges.push_back(e);
34     }
35 
36     void InsertEdge(std::string beginv, std::string endv)
37     {
38         int begin = nodemap[beginv];
39         int end = nodemap[endv];
40         InsertEdge(begin, end);
41     }
42     
43     void InsertUndirEdge(int begin, int end)
44     {
45         InsertEdge(begin, end);
46         InsertEdge(end, begin);
47     }
48 
49     void InsertUndirEdge(std::string beginv, std::string endv)
50     {
51         int begin = nodemap[beginv];
52         int end = nodemap[endv];
53         InsertUndirEdge(begin, end);
54     }
55 };

在这里,Edge只记录了end节点,之所以单独封装成一个结构,一是语义上更加直观,二是以后想要扩充时会比较方便(比如需要扩充为带权重的图时,在Edge里加一个权重项就可以了,已有算法不用改变)。Node里value代表节点的语义值,比如我们常常面对实际问题的时候,并不是直接给的“节点1”,给的可能是“节点a”,记录这个语义值可以方便最后输出计算结果。Node里还有一个edges记录以该node为begin的边,同时要注意的时,Node里还加入了d,p,color。d用来记录该节点到源节点的距离,p记录该节点到源节点最短路径的父节点,color用于记录在遍历过程中,节点是否已经遍历到(WHITE没有遍历到,GRAY遍历到,但是还有与之相连的节点没有,BLACK表示遍历完成)。Graph主要是存储了一个邻接表nodes,其余的函数都是为了方便建图。(采取先插入所有节点,再插入边的方式)。其中插入边的时候,可以按照节点的语义值插入,这时候我们先搜索语义值对应的节点编号,然后再插入对应边信息。

有了以上的数据结构,我们的广度优先遍历算法就变得非常简单明了了:

 1 void BFS(Graph& g, int s)
 2 {
 3     for (size_t i = 0; i < g.nodes.size(); ++i)
 4     {
 5         g.nodes[i].d = -1;
 6         g.nodes[i].p = -1;
 7         g.nodes[i].color = WHITE;
 8     }
 9     g.nodes[s].d = 0;
10     g.nodes[s].p = -1;
11     g.nodes[s].color = GRAY;
12     queue<int> q;
13     q.push(s);
14     while (!q.empty())
15     {
16         int u = q.front(); q.pop();
17         for (size_t i = 0; i < g.nodes[u].edges.size(); ++i)
18         {
19             int v = g.nodes[u].edges[i].end;
20             if (g.nodes[v].color == WHITE)
21             {
22                 g.nodes[v].d = g.nodes[u].d + 1;
23                 g.nodes[v].p = u;
24                 g.nodes[v].color = GRAY;
25                 q.push(v);
26             }
27         }
28         g.nodes[u].color = BLACK;
29     }
30 }

 

posted @ 2014-01-07 14:02  Tiancai Ye  阅读(571)  评论(0)    收藏  举报