1.图的广度优先搜索
图的遍历:从图中某一顶点出发,按照某种搜索方法沿着图中的边对图中的所有顶点访问一次且仅访问一次。
广度优先搜索
(1)首先访问起始顶点v;
(2)接着由出发依次访问v的各个未被访问过的邻接顶点
w
1
w_1
w1,
w
2
w_2
w2,…,
w
t
w_t
wt;
(3)然后依次访问
w
1
w_1
w1,
w
2
w_2
w2,…,
w
t
w_t
wt的所有未被访问过的邻接顶点;
(4)在从这些访问过的顶点出发,访问它们所有未被访问过的邻接顶点;
(5)…,以此类推;
#define MAX_TREE_SIZE 100
bool visit[MAX_TREE_SIZE];
//避免因为图不连通导致的有结点没有被遍历
void BFSTraverse(Graph G)
{
for(int i=0;i<G.vexnum;i++)
visited[i]=false;
InitQuene(Q);
for(int i=0;i<G.vexnum;i++)
{
if(!visited[i])
BFS(G,i);
}
}
//对某个顶点的广度优先搜索
void BFS(Graph G,int v)
{
visit(v);
Enqueue(Q,v);
visited[v]=true;
while(!Q.empty())
{
Dequeue(Q,v);
for(w=FirstNeighbor(G,v);w>=0;w=NextNeighbor(G,v,w))
{
if(!visited[w])
{
visit(w);
visited[w]=true;
Enqueue(G,w);
}
}
}
}
复杂度分析:
空间复杂度分析:O(|V|)
时间复杂度:
邻接矩阵法:O(
∣
V
∣
2
|V|^2
∣V∣2)
邻接表法:O(|V|+|E|)
广度优先搜索应用——无权图单源最短路径问题
求解从u到v的任何路径中最少的边数。
Void BFS_MIN_Distance(Graph G,int u)
{
for(int i=0;i<G.vexnum;i++)
{
d[i]=INT_MAX;
}
visit(u);
Enqueue(Q,u);
d[u]=0;
visited[u]=true;
while(!Q.empty())
{
Dequeue(Q,v);
for(w=FirstNeighbor(G,v);w>=0;w=NextNeighbor(G,v,w))
{
if(!visited[w])
{
visit(w);
d[w]=d[u]+1;
visited[w]=true;
Enqueue(G,w);
}
}
}
}
广度优先生成树:
在广度遍历过程中,我们可以得到一棵遍历树,称为广度优先生成树(生成森林)。
**注意:**邻接矩阵的广度优先生成树唯一,邻接表法的不唯一(因为输入边的次序不唯一,对应顶点的边表就不唯一)。
2. 图的深度优先搜索
深度优先搜索DFS:
(1)首先访问起始顶点v;
(2)接着由v出发访问v的任意一个邻接且未被访问的邻接顶点
w
i
w_i
wi;
(3)然后再访问与
w
i
w_i
wi邻接且未被访问过的任意顶点
y
i
y_i
yi;
(4)若
w
i
w_i
wi没有邻接且未被访问的顶点时,退回到它的上一层顶点v;
(5)重复上述过程,直到所有顶点被访问为止。
深度优先搜索与树的前序遍历类似;因此可以采用递归(栈)+辅助标记数组方法进行深度优先搜索。
bool visited[MAX_TREE_SIZE];
void DFSTraversr(Graph G)
{
for(int i=0;i<G.vernum;i++)
{
visited[i]=false;
}
for(int i=0;i<G.vernum;i++)
{
if(!visited[i])
DFS(G,i);
}
}
void DFS(Graph G,int v)
{
visit(v);
visited[v]=true;
for(w=FirstNeighbor(G,v);w>=0;w=NextNeighbor(G,v,w)
{
if(!visited[w])
DFS(G,w);
}
}
因此,从上述可以看到,递归、回溯是与深度优先搜索捆绑的,而不是广度优先搜索。
DFS算法的性能分析:
空间复杂度(额外添加的空间): O|V| 工作栈
时间复杂度:
邻接矩阵法:O|
V
2
V^2
V2|
邻接表法:O(|V|+|E|)
深度优先生成树:
在深度遍历过程中,我们可以得到一棵遍历树,称为深度优先生成树。
注意:邻接矩阵的广度优先生成树唯一,邻接表法的不唯一(因为输入边的次序不唯一,对应顶点的边表就不唯一)。
遍历与连通性问题:
在无向图中,在任意结点出发进行一次遍历(调用一次DFS或BFS)时,若能访问全部结点,说明该无向图是连通的。
在无向图中,调用遍历函数(BFS或DFS)的次数为连通分量的个数。