首页 > 编程知识 正文

数据结构图的算法,图的遍历的实现 数据结构课程设计

时间:2023-05-04 13:30:36 阅读:49601 作者:1555

文章目录定义深度优先导线宽度优先导线测试代码

定义

从图中某一顶点出发访遍图中其余顶点,且使每一个顶点仅被访问一次,这一过程就叫做图的遍历(Traversing Graph)。

深度优先遍历深度优先遍历(Depth_First_Search),也有称深度优先搜索,简称DFS。

为了优先理解的深度,用一个小游戏来说明。

假设要完成任务,必须在如图1-1左图所示的迷宫中,从顶点a绕着所有图的顶点进行标记。 请注意,不要只是看着这样的平面图走啊。 像现实一样在只有高墙和通道的迷宫里执行任务。

图1-1

显然需要战略,现在使用深度优先的遍历进行。

首先从顶点a开始,做了表示制作的记号,然后前面有两条路,通向b和f。 我们给了自己原则,只要不撞到重复顶点,总是走到右边的手边,去了顶点b。 行走过程请参照图1-1的右图。 此时,发现存在与顶点c、I、g的右手通行原则相通的三个分支。 我们去了顶点c。 就这样,我们一直沿着右手边的通道走,一直走到了顶点f。 尽管如此,我还是选择右手通道通过时,发现已经回到了顶点a。 此时,我们返回顶点f,前往从右数第二个通道。 到了g点,他有三条通道。 B和d已经通过了。 在那里去h,到h,你会发现两条通道d和e已经通过了。

此时,我们还没有穿越完所有的顶点。 在顶点h,没有通道走。 回到g。 另外,也没有没有没有走过的通道。 回到f。 没有通道。 回到e,有一条通往h的通道。 验证后也通过了。 回到d。 这个时候,还有三条还没有通过。 有一条在走。 h、g、I继续返回,直到返回顶点a,并确认遍历任务完成。 我找到了九个顶点。

深度优点遍历其实就是递归的过程,如果在仔细点,会发现转换成1-1的右图之后,就像是一棵树的前序遍历。从图中某个顶点V开始,访问此顶点,然后从V的未被访问的邻接点出发深度优先遍历图,直到图中所有和V有路径相通的顶点都被访问到。其实,这里说的是连通图。 对于非连通图,只要对其连通分量分别进行深优点扫描即可,可以使用即在先前一个顶点进行一次深度优先遍历后,如图中有顶点没有被访问,则选图中一个未曾被访问的顶点做起始点,重复上述过程,直到图中所有顶点都被访问到为止。

使用相邻矩阵方法时,代码如下所示:

类型在线布尔; /* Boolean是布尔型,其值为TRUE或FALSE */Boolean visited[MAXVEX]; /*访问标志数组*//*相邻矩阵的深度优先递归算法*/voidDFS(mgraphg,int i ) ) intj; 可视[ I ]=true; printf('%c ',G.vexs[i] ); /*打印顶点,执行其他操作*/for(j=0; j G.numVertexes; j ) if(g.arc[I][j]==1! 可视[ j ] ) DFS(g,j ); /*对要访问的相邻顶点递归调用*/}/*相邻矩阵的深度遍历操作*/voidDFStraverse(mgraphg ) {int i; for(I=0; i G.numVertexes; I )可视[ I ]=false; /*初始所有顶点状态为未访问状态*/for(I=0; i G.numVertexes; I ) if (! visited[i] )/*对未访问的顶点调用DFS,对于连通图,*/DFS(g,I )只运行一次。 }如果图表结构为邻接表结构,则DFSTraverse函数的代码大致相同,但递归函数将数组转换为链表,因此代码不同。

类型在线布尔; /* Boolean是布尔型,其值为TRUE或FALSE */Boolean visited[MAXVEX]; /*访问标志数组*//*相邻矩阵的深度优先递归算法*/voidDFS(mgraphGL,int i ) {EdgeNode *p; 可视[ I ]=true; printf('%c ',GL-adjList[i].data; /*打印顶点以执行其他操作*/p=GL-adjList[i]firstedge; while(p ) ) if (! 可视[ p-adjvex ] (DFS (GL.p-adjvex ); p=p-next; }/*相邻矩阵的深度遍历操作*/voidDFStraverse(mgraphlistGL ) {int i; for(I=0; i GL.numVertexes; I )可视[ I ]=false; /*初始所有顶点状态为未访问状态*/for(I=0; i GL.numVertexes; I ) if (! visited[i] )/*对未访问的顶点调用DFS,对于连通图,*/DFS(GL,I )只运行一次。 广度优先遍历广度优先遍历(Br

eafth_First_Search),又称广度优先搜索,简称BFS。
如果说图的深度优先遍历类似于树的前序遍历,那么图的广度优先遍历就类似于树的层序遍历了。我们将图1-2的第一幅稍微变形,变形原则就是顶点A放置在最上第一层,让与他有边的顶点B,F成为第二层,再让B和F有边的顶点C,I,G,E为第三层,在将这四个顶点有边的D,H放在第四层,如图1-2第二幅图所示、此时在视觉上感觉图的形状发生了变化,其实顶点和边的关系还是完全相同的。

图1-2

/* 邻接矩阵的广度遍历算法 */void BFSTraverse(MGraph G){int i, j;Queue Q;for(i = 0; i < G.numVertexes; i++) visited[i] = FALSE; InitQueue(&Q);/* 初始化一辅助用的队列 */ for(i = 0; i < G.numVertexes; i++) /* 对每一个顶点做循环 */ {if (!visited[i])/* 若是未访问过就处理 */{visited[i]=TRUE;/* 设置当前顶点访问过 */printf("%c ", G.vexs[i]);/* 打印顶点,也可以其它操作 */EnQueue(&Q,i);/* 将此顶点入队列 */while(!QueueEmpty(Q))/* 若当前队列不为空 */{DeQueue(&Q,&i);/* 将队对元素出队列,赋值给i */for(j=0;j<G.numVertexes;j++) { /* 判断其它顶点若与当前顶点存在边且未访问过 */if(G.arc[i][j] == 1 && !visited[j]) { visited[j]=TRUE;/* 将找到的此顶点标记为已访问 */printf("%c ", G.vexs[j]);/* 打印顶点 */EnQueue(&Q,j);/* 将找到的此顶点入队列 */} } }}}} 测试代码 #include "stdio.h" #include "stdlib.h" #include "io.h" #include "math.h" #include "time.h"#define OK 1#define ERROR 0#define TRUE 1#define FALSE 0typedef int Status;/* Status是函数的类型,其值是函数结果状态代码,如OK等 */ typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */typedef char VertexType; /* 顶点类型应由用户定义 */typedef int EdgeType; /* 边上的权值类型应由用户定义 */#define MAXSIZE 9 /* 存储空间初始分配量 */#define MAXEDGE 15#define MAXVEX 9#define INFINITY 65535typedef struct{VertexType vexs[MAXVEX]; /* 顶点表 */EdgeType arc[MAXVEX][MAXVEX];/* 邻接矩阵,可看作边表 */int numVertexes, numEdges; /* 图中当前的顶点数和边数 */ }MGraph;/* 用到的队列结构与函数********************************** *//* 循环队列的顺序存储结构 */typedef struct{int data[MAXSIZE];int front; /* 头指针 */int rear;/* 尾指针,若队列不空,指向队列尾元素的下一个位置 */}Queue;/* 初始化一个空队列Q */Status InitQueue(Queue *Q){Q->front=0;Q->rear=0;return OK;}/* 若队列Q为空队列,则返回TRUE,否则返回FALSE */Status QueueEmpty(Queue Q){ if(Q.front==Q.rear) /* 队列空的标志 */return TRUE;elsereturn FALSE;}/* 若队列未满,则插入元素e为Q新的队尾元素 */Status EnQueue(Queue *Q,int e){if ((Q->rear+1)%MAXSIZE == Q->front)/* 队列满的判断 */return ERROR;Q->data[Q->rear]=e;/* 将元素e赋值给队尾 */Q->rear=(Q->rear+1)%MAXSIZE;/* rear指针向后移一位置, *//* 若到最后则转到数组头部 */return OK;}/* 若队列不空,则删除Q中队头元素,用e返回其值 */Status DeQueue(Queue *Q,int *e){if (Q->front == Q->rear)/* 队列空的判断 */return ERROR;*e=Q->data[Q->front];/* 将队头元素赋值给e */Q->front=(Q->front+1)%MAXSIZE;/* front指针向后移一位置, *//* 若到最后则转到数组头部 */return OK;}/* ****************************************************** */void CreateMGraph(MGraph *G){int i, j;G->numEdges=15;G->numVertexes=9;/* 读入顶点信息,建立顶点表 */G->vexs[0]='A';G->vexs[1]='B';G->vexs[2]='C';G->vexs[3]='D';G->vexs[4]='E';G->vexs[5]='F';G->vexs[6]='G';G->vexs[7]='H';G->vexs[8]='I';for (i = 0; i < G->numVertexes; i++)/* 初始化图 */{for ( j = 0; j < G->numVertexes; j++){G->arc[i][j]=0;}}G->arc[0][1]=1;G->arc[0][5]=1;G->arc[1][2]=1; G->arc[1][8]=1; G->arc[1][6]=1; G->arc[2][3]=1; G->arc[2][8]=1; G->arc[3][4]=1;G->arc[3][7]=1;G->arc[3][6]=1;G->arc[3][8]=1;G->arc[4][5]=1;G->arc[4][7]=1;G->arc[5][6]=1; G->arc[6][7]=1; for(i = 0; i < G->numVertexes; i++){for(j = i; j < G->numVertexes; j++){G->arc[j][i] =G->arc[i][j];}}} Boolean visited[MAXVEX]; /* 访问标志的数组 *//* 邻接矩阵的深度优先递归算法 */void DFS(MGraph G, int i){int j; visited[i] = TRUE; printf("%c ", G.vexs[i]);/* 打印顶点,也可以其它操作 */for(j = 0; j < G.numVertexes; j++)if(G.arc[i][j] == 1 && !visited[j]) DFS(G, j);/* 对为访问的邻接顶点递归调用 */}/* 邻接矩阵的深度遍历操作 */void DFSTraverse(MGraph G){int i; for(i = 0; i < G.numVertexes; i++) visited[i] = FALSE; /* 初始所有顶点状态都是未访问过状态 */for(i = 0; i < G.numVertexes; i++) if(!visited[i]) /* 对未访问过的顶点调用DFS,若是连通图,只会执行一次 */ DFS(G, i);}/* 邻接矩阵的广度遍历算法 */void BFSTraverse(MGraph G){int i, j;Queue Q;for(i = 0; i < G.numVertexes; i++) visited[i] = FALSE; InitQueue(&Q);/* 初始化一辅助用的队列 */ for(i = 0; i < G.numVertexes; i++) /* 对每一个顶点做循环 */ {if (!visited[i])/* 若是未访问过就处理 */{visited[i]=TRUE;/* 设置当前顶点访问过 */printf("%c ", G.vexs[i]);/* 打印顶点,也可以其它操作 */EnQueue(&Q,i);/* 将此顶点入队列 */while(!QueueEmpty(Q))/* 若当前队列不为空 */{DeQueue(&Q,&i);/* 将队对元素出队列,赋值给i */for(j=0;j<G.numVertexes;j++) { /* 判断其它顶点若与当前顶点存在边且未访问过 */if(G.arc[i][j] == 1 && !visited[j]) { visited[j]=TRUE;/* 将找到的此顶点标记为已访问 */printf("%c ", G.vexs[j]);/* 打印顶点 */EnQueue(&Q,j);/* 将找到的此顶点入队列 */} } }}}}int main(void){ MGraph G;CreateMGraph(&G);printf("n深度遍历:");DFSTraverse(G);printf("n广度遍历:");BFSTraverse(G);return 0;}

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。