数据结构复习笔记 图的遍历及连通性问题
- 1. 图的遍历及连通性问题
一、深度优先收索 Depth-First-Search(DFS)
//教材上面算法,这个最重要。后面的具体实现了解。
// ,
Boolean visited[MAX]; // 访问标志数组
Status (* VisitFunc))(int v); // 函数指针变量
void DFSTraverse(Graph G, Status(* Visit)(int v))
// 对图
G 作深度优先遍历
{VisitFunc = Visit;
// VisitFunc,使 DFS 不必设函数指针参数
//使用全局变量 VisitFunc
for(v=0; v<G.vexnum; ++v) visited[v] = FALSE ;
// 访问标志数组初始化
for(v=0; v<G.vexnum; ++v )
if(!Visited[v]) DFS (G,v ); //
//对尚未访问的顶点调用 DFS
}
//从第 v 个顶点出发递归地深度优先遍历图 G
//
void DFS(Graph G, int v)
{visited[v]=TRUE;
VistFunc(v); //访问第 v 个顶点
//
for(w=FirstAdjVex(G,v);w;
w=NextAdjVex(G,v,w))
if(!visted[w]) DFS(G,w);
// v 的尚未访问的邻接顶点 w 递归调用 DFS
//对
}
//邻接矩阵作为作为存储结构
Boolean visited[MAX_VERTEX_NUM]; /* 访问标志数组(全局量) */
void(*VisitFunc)(VertexType); /* 函数变量 */
void DFS(MGraph G,int v)
{ /* 从第 v 个顶点出发递归地深度优先遍历图 G。算法 7.5 */
int w;
visited[v]=TRUE; /* 设置访问标志为 TRUE(已访问) */
VisitFunc(G.vexs[v]); /* 访问第 v 个顶点 */
for(w=FirstAdjVex(G,G.vexs[v]);w>=0;w=NextAdjVex(G,G.vexs[v],G.vexs[w]))
if(!visited[w])
DFS(G,w); /* 对 v 的尚未访问的序号为 w 的邻接顶点递归调用 DFS */
}
void DFSTraverse(MGraph G,void(*Visit)(VertexType))
1
- 2. { /* 初始条件:图 G 存在,Visit 是顶点的应用函数。算法 7.4 */
/* 操作结果:从第 1 个顶点起,深度优先遍历图 G,并对每个顶点调用函数 Visit 一次且
仅一次 */
int v;
VisitFunc=Visit; /* 使用全局变量 VisitFunc,使 DFS 不必设函数指针参数 */
for(v=0;v<G.vexnum;v++)
visited[v]=FALSE; /* 访问标志数组初始化(未被访问) */
for(v=0;v<G.vexnum;v++)
if(!visited[v])
DFS(G,v); /* 对尚未访问的顶点 v 调用 DFS */
}
//邻接表作为存储结构
Boolean visited[MAX_VERTEX_NUM]; /* 访问标志数组(全局量) */
void(*VisitFunc)(char* v); /* 函数变量(全局量) */
void DFS(ALGraph G,int v)
{ /* 从第 v 个顶点出发递归地深度优先遍历图 G。算法 7.5 */
int w;
visited[v]=TRUE; /* 设置访问标志为 TRUE(已访问) */
VisitFunc(G.vertices[v].data); /* 访问第 v 个顶点 */
for(w=FirstAdjVex(G,G.vertices[v].data);w>=0;w=NextAdjVex(G,G.vertices[v].data,G.vertices[w].d
ata))
if(!visited[w])
DFS(G,w); /* 对 v 的尚未访问的邻接点 w 递归调用 DFS */
}
void DFSTraverse(ALGraph G,void(*Visit)(char*))
{ /* 对图 G 作深度优先遍历。算法 7.4 */
int v;
VisitFunc=Visit; /* 使用全局变量 VisitFunc,使 DFS 不必设函数指针参数 */
for(v=0;v<G.vexnum;v++)
visited[v]=FALSE; /* 访问标志数组初始化 */
for(v=0;v<G.vexnum;v++)
if(!visited[v])
DFS(G,v); /* 对尚未访问的顶点调用 DFS */
}
二、广度优先搜索(Breadth_First Search
Breadth_First Search)
//教材上面算法,这个最重要。后面的具体实现了解。
// ,
void BFSTraverse(Graph G,Status(* Visit)(int v))
{ // 按广度优先非递归遍历图 G。使用辅助队列 Q 和访问标志数组 visited visited。
for(v=0; v<G.vexnum; ++v ) visited[v] = FALSE;
InitQueue(Q); // 置空的辅助队列 Q
for (v=0; v<G.vexnum; ++v )
2
- 3. if (!visited[v]) // v 尚未访问
{EnQueue(Q, v); // v 入队列
while (!QueueEmpty(Q))
{DeQueue(Q, u); // 队头元素出队并置为 u
visited[u] = TRUE; Visit(u); // 访问 u
for(w=FirtAdjVex(G,u);w;w=NextAdjVex(G,u,w))
if(!visited[w]) EnQueue(Q,w);
// u 的尚未访问的邻接顶点 w
入队列 Q
}//while
}// if
}// BFSTraverse
//邻接矩阵作为存储结构
void BFSTraverse(MGraph G,void(*Visit)(VertexType))
{ /* 初始条件:图 G 存在,Visit 是顶点的应用函数。算法 7.6 */
/* 操作结果: 从第 1 个顶点起,按广度优先非递归遍历图 G,并对每个顶点调用函数 Visit
一次且仅一次 */
int v,u,w;
LinkQueue Q; /* 使用辅助队列 Q 和访问标志数组 visited */
for(v=0;v<G.vexnum;v++)
visited[v]=FALSE; /* 置初值 */
InitQueue(&Q); /* 置空的辅助队列 Q */
for(v=0;v<G.vexnum;v++)
if(!visited[v]) /* v 尚未访问 */
{
visited[v]=TRUE; /* 设置访问标志为 TRUE(已访问) */
Visit(G.vexs[v]);
EnQueue(&Q,v); /* v 入队列 */
while(!QueueEmpty(Q)) /* 队列不空 */
{
DeQueue(&Q,&u); /* 队头元素出队并置为 u */
for(w=FirstAdjVex(G,G.vexs[u]);w>=0;w=NextAdjVex(G,G.vexs[u],G.vexs[w]))
if(!visited[w]) /* w 为 u 的尚未访问的邻接顶点的序号 */
{
visited[w]=TRUE;
Visit(G.vexs[w]);
EnQueue(&Q,w);
}
}
}
}
//邻接表作为存储结构
void BFSTraverse(ALGraph G,void(*Visit)(char*))
3
- 4. {/*按广度优先非递归遍历图 G。使用辅助队列 Q 和访问标志数组 visited。算法 7.6 */
int v,u,w;
LinkQueue Q;
for(v=0;v<G.vexnum;++v)
visited[v]=FALSE; /* 置初值 */
InitQueue(&Q); /* 置空的辅助队列 Q */
for(v=0;v<G.vexnum;v++) /* 如果是连通图,只 v=0 就遍历全图 */
if(!visited[v]) /* v 尚未访问 */
{
visited[v]=TRUE;
Visit(G.vertices[v].data);
EnQueue(&Q,v); /* v 入队列 */
while(!QueueEmpty(Q)) /* 队列不空 */
{
DeQueue(&Q,&u); /* 队头元素出队并置为 u */
for(w=FirstAdjVex(G,G.vertices[u].data);w>=0;w=NextAdjVex(G,G.vertices[u].data,G.vertices[w].d
ata))
if(!visited[w]) /* w 为 u 的尚未访问的邻接顶点 */
{
visited[w]=TRUE;
Visit(G.vertices[w].data);
EnQueue(&Q,w); /* w 入队 */
}
}
}
printf("n");
}
三、无向图的连通分量和生成树
应该会画就行了吧,对算法应该没有要求的。
1.连通分量
无向图的极大连通子图。即子图中不能再增加一个顶点,已有顶点的边均包含在内。
无向图的连通分量的产生——多次调用 DFS
2.生成树 一个连通图的生成树是一个极小连通子图,且含有图中全部顶点
3.无向图的生成树
对一个连通图 G,从图中任意一个顶点出发遍历图时,把 E 分为 E1 和 E2,E1 为遍历过程
中经过的边的集合,E2 为剩余边的集合,则 E1 与 V 构成 G 的极小连通图,即连通图的一棵
生成树
若遍历为 DFS,则称为深度优先生成树
若遍历为 BFS,则称为广度优先生成树
对于非连通图,每个连通分量中的顶点集合,加上遍历时经过的边,构成了非连通图的生成
森林。
4