算法分析与设计 PAT程序填空题 图的解析1

194 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

5-8 深度优先遍历邻接表存储的图

DFS 思想:

深度优先遍历图的方法是,从图中某顶点v出发:
1.访问顶点v;
2.依次从v的未被访问的邻接点出发,对图进行深度优先遍历;直至图中和v有路径相通的顶点都被访问;
3.若此时图中尚有顶点未被访问,则从一个未被访问的顶点出发,重新进行深度优先遍历,直到图中所有顶点均被访问过为止。

DFS伪代码:

DFS(当前被访问的节点pos)
{
	pos被标记访问过
		遍历与pos相连的节点(有边相连)
		如果这个节点没有被访问过
		搜索(DFS)当前节点
}

思路:这道题的关键是理解深度优先遍历时额外设定的visited[]数组的作用:用来标记是否访问过这个结点,从而确定遍历时是否回退。

题目代码:

typedef int Vertex;
typedef struct AdjNode {
    Vertex AdjV;
    struct AdjNode *Next;
    struct AdjNode *FirstEdge;
}AdjVNode;
typedef struct {
    AdjVNode G[MAX];
}Graph;
typedef Graph* LGraph;
/* 邻接表存储的图 - DFS */
bool Visited[MAX];
typedef AdjVNode* PtrToAdjVNode;

void Visit( Vertex V )
{
    printf("正在访问顶点%d\n", V);
}

/* Visited[]为布尔类型的全局数组,已经初始化为false */
void DFS( LGraph Graph, Vertex V, void (*Visit)(Vertex) ) //Graph表示邻接矩阵存储的图 V表示当前访问的节点 第三个参数为输出节点的函数
{   
    PtrToAdjVNode W;
    Visit(V); //访问V时打印访问的顶点
	Visited[V]=true; //标记V被访问过,此后不再访问
    for( W=Graph->G[V].FirstEdge; W; W=W->Next ) 
        if ( !Visited[W->AdjV] ) //如果当前节点V与遍历的节点w有边相连,且w没有被访问过           
			DFS(Graph,W,Visit); //从W开始搜索访问
}

5-9 基于邻接矩阵表示的深度优先遍历

思路:这道题给的代码很全,比较简单。

#include <stdio.h>
#define MVNum 100                           
typedef struct{ 
    char vexs[MVNum];          
    int arcs[MVNum][MVNum];   
    int vexnum,arcnum;      
}AMGraph;
int visited[MVNum];
void CreateUDN(AMGraph &G);//实现细节隐藏

void DFS(AMGraph G, int v){  
    printf("%c ",G.vexs[v]);  visited[v] =1;  
    int w;
    for(w = 0; w < G.vexnum; w++)
        if((visited[w]==0)&&(arcs[v][w]==1)) //visited[w]==0判断是否访问过,arcs[v][w]==1判断v和w之间有没有边存在
       		 DFS(G, w);
}

void DFSTraverse(AMGraph G){ 
    int v;
    for(v = 0; v < G.vexnum; ++v)  
        visited[v] = 0;
    for(v = 0; v < G.vexnum; ++v) 
        if(!visited[v]) //!visited[v]判断是否访问过                 
			DFS(G,v); 
}

int main(){
    AMGraph G;     
    CreateUDN(G);
    DFSTraverse(G);
    return 0;
}