您的位置:首页 > 其它

图的基础算法-广度优先搜索/深度优先搜索

2016-01-22 17:25 218 查看
图有矩阵存储和链表存储两种。这里采用链表存储。

参考《算法导论》上面的做法,首先定义图结点的结构。为了跟踪算法的进展,广度优先搜索在概念上将每个结点涂成白色。在算法推进过程中,结点的颜色可能变成灰色或者黑色。在搜索过程中,第一次遇到一个结点时,表示该结点已被发现,此时该结点的颜色将从白色变成灰色。灰色或黑色结点都是已经被发现过的结点。所有与黑色结点邻接的结点都已经被发现。对于灰色结点来说,其邻接结点中可能存在未被发现的白色结点。

struct graphNode {
int ver;
//为结点定义颜色,方便在遍历树的时候,标记结点是否已经访问。
//white表示还没有访问过的结点
//gray表示已经访问过的结点(结点一旦被访问,就设置color为“gray”)
//black表示该节点的邻接结点都已访问过,由gray变成black
string color;
//遍历过程中记录该结点的父结点
graphNode* peer;
//遍历过程记录该结点的深度
int dest;
//stime是遍历该结点的起始时间,ftime该结点的邻接结点遍历完成回到该结点的时间(用于深度优先搜索)
int stime;
int ftime;
graphNode() {
color = "white";
peer = NULL;
dest = 0;
stime = 0;
ftime = 0;
}
graphNode(int v):ver(v) {
color = "white";
peer = NULL;
dest = 0;
stime = 0;
ftime = 0;
}
graphNode(graphNode &g) {
ver = g.ver;
color = g.color;
peer = g.peer;
dest = g.dest;
stime = g.stime;
ftime = g.ftime;
}
};


BFS

在执行广度优先搜索的过程中将构造出一棵广度优先树。一开始树中只有根结点s,在扫描已发现结点u的邻接链表时,每当发现一个白色结点v,就将白色结点v和边(u,v)同时加入该树里面。在广度优先树中,u是v的父结点。

首先选定源结点s作为根结点,从源结点开始遍历。利用队列来管理灰色结点。

广度优先搜索能够正确计算出最短路径距离

void BFSearch(linkedgraph &g, int v) {
arrayQueue<graphNode*> q;
graphNode *s = &g.gnode[v-1];
s->color = "gray";
//将源结点插入队列
q.push(s);
while (q.empty() == false) {
graphNode *u = q.front();
int size = g.gchain[u->ver - 1].size();
//遍历队列首项的结点的邻接链表中所有的结点
for (int i = 1; i <= size; i++) {
graphNode *v = g.gchain[u->ver - 1].get(i);
if (v->color == "white") {
v->color = "gray";
v->peer = u;
v->dest = u->dest + 1;
cout << v->ver << endl;
q.push(v);
}
}
//遍历完该结点的邻接结点后,将该结点的color改为“black”,然后删除队列中该结点
u->color = "black";
q.pop();
}
return;
}


DFS

深度优先搜索总是对最近才发现的结点v的出发边进行探索,直到该结点所有出发边都被发现为止。一旦结点v的所有出发边都被发现为止。一旦结点的所有出发边都被发现,搜索则“回溯”到v的前驱结点(v是经过该结点才被发现的),来搜索该前驱结点的出发边。该过程一直持续到从源结点可以到达的所有结点都被发现为止。

void DFSvisit(linkedgraph &g, graphNode* s,int &time) {
time++;
s->color = "gray";
s->stime = time;
int size = g.gchain[s->ver - 1].size();
for (int i = 1; i <= size; i++) {
graphNode* v = g.gchain[s->ver - 1].get(i);
if (v->color == "white") {
v->peer=u;
//递归遍历
DFSvisit(g, v, time);
}
}
s->color = "black";
time++;
s->ftime = time;
cout << s->stime << " " << s->ftime << endl;
return;
}

void DFSearch(linkedgraph &g, int v) {
graphNode* s = &g.gnode[v - 1];
int time = 0;
DFSvisit(g, s,time);
return;
}


代码的实现细节是针对笔者实现的图的类的相关接口来编写的。所以读者可能看不太懂代码,可以留言向笔者索要源代码,欢迎大家交流讨论。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  BFS DFS