图的应用
(1)创建无向图的邻接矩阵存储结构
(2)输出无向图的邻接矩阵表示
(3)输入任意两个结点,判断是否有边存在
(4)输入任意一个结点,求顶点的度
(5)根据邻接矩阵求该无向图中边的数目
(6)实现图的深度优先遍历
(7)实现图的广度优先遍历
#include<stdio.h> #include<stdlib.h> #define MAX 100 // 图中最大顶点个数 //建立邻接矩阵 typedef struct{ int n,e; // 顶点数、边数 char vexs[MAX]; // 顶点数组 int edges[MAX][MAX]; // 边的邻接矩阵 }MGraph; /*建立邻接矩阵*/ void CreateMGraph(MGraph *G){ int i,j,k; char ch1,ch2; // 输入的顶点 printf("请输入顶点数:"); scanf("%d",&G->n); printf("请输入边数:"); scanf("%d",&G->e); printf("请输入各顶点信息(每个顶点以回车键作为结束):\n"); for(i=0; i<G->n; i++){ getchar(); printf("请输入%d个顶点:",i+1); scanf("%c",&G->vexs[i]); } for(i=0; i<G->n; i++) for(j=0;j<G->n;j++) G->edges[i][j] = 0; // 将邻接矩阵元素全部置0 for(k=0;k<G->e;k++){ getchar(); printf("建立第%d条边 (两顶点之间用空格分开)",k+1); scanf("%c %c",&ch1,&ch2); for(i=0; i<G->n; i++) for(j=0;j<G->n;j++) if(ch1==G->vexs[i] && ch2==G->vexs[j]){ G->edges[i][j] = 1; G->edges[j][i] = 1; //加上该语句为无向邻接矩阵,去掉为有向邻接矩阵 } } } /*输出邻接矩阵*/ void DispMGraph(MGraph G){ int i,j; printf("\n图的邻接矩阵:\n"); for(i=0;i<G.n;i++){ for(j=0;j<G.n;j++) printf("%5d",G.edges[i][j]); printf("\n"); } } // 判断两个结点之间是否有边存在 int EdgeMGraph(MGraph *G, char m, char n) { int x=0,y=0,num=0; while(num++ != G->n) //遍历数组找到两个节点序号 { if(G->vexs[num] == n) x = num; if(G->vexs[num] == m) y = num; } return G->edges[x][y]; } //求任意一个顶点的度 int DegreeMGraph(MGraph *G, char m){ int i=0,j,sum=0; while(G->vexs[i]!=m && i<G->n) //i 为 m的下标 i++; if(i<G->n) { for(j=0;j<G->n;j++) sum += G->edges[i][j]; } return sum; } //根据邻接矩阵求该无向图中边的数目 int AllMGraph(MGraph *G){ int x=0,y=0,bian=0; for(x=0; x<G->n; x++) for(y=0; y<G->n; y++) if(G->edges[x][y]) bian++; return bian/2; } //建立邻接表 (结构体嵌套) typedef char VertexType; int visited[MAX]; typedef struct node{ //定义边表节点 int adjvex; //邻接点域 struct node *next; //指向下一邻接点的指针域 }EdgeNode; typedef struct vexnode{ //定义顶点表节点 VertexType data; //顶点域 EdgeNode *firstedge; //指向第一条边节点 }VHeadNode; typedef struct{ VHeadNode adjlist[MAX]; //邻接表头节点数组 int n,e; //顶点数、边数 }AdjList; //建立图的邻接表的算法 //可以实现根据参数flag的值为0或1来选择生成无向图还是有向图 void CreateAGraph(AdjList *g, int flag){ //生成无向图的邻接表函数 int i,j,k; EdgeNode *p; if(flag == 0) printf("\n建立一个无向图:\n"); else printf("\n建立一个有向图:\n"); printf("请输入图的顶点数:"); scanf("%d",&g->n); printf("请输入图的边数:"); scanf("%d",&g->e); printf("请输入图的各顶点信息:\n"); for(i=0; i<g->n; i++){ //生成n个顶点的顶点表 getchar(); printf("第%d个顶点信息",i+1); scanf("\n%c",&(g->adjlist[i].data)); //读入顶点信息,data为adjlist[i]的数据域 g->adjlist[i].firstedge = NULL; //点的边表头指针设为空,firstedge为adjlist[i]的指针域 } printf("\n请输入边的信息,输入格式为:序号1 [空格] 序号2(序号依次为0、1、2···)\n"); for(k=0; k<g->e; k++){ printf("请输入第%d条边:",k); scanf("\n%d %d",&i,&j); //将编号为i的节点添加到邻接表中 p = (EdgeNode *)malloc(sizeof(EdgeNode)); p->adjvex = j; p->next = g->adjlist[i].firstedge; g->adjlist[i].firstedge = p; //将编号为j的节点添加到邻接表中,有向图不用添加节点,去掉下面if语句 if(flag == 0){ p = p = (EdgeNode *)malloc(sizeof(EdgeNode)); p->adjvex = i; //邻接点序号为i p->next = g->adjlist[j].firstedge; //将新节点p插到顶点vi边表头 g->adjlist[j].firstedge = p; } } } //输出图的邻接表 void DispAGraph(AdjList *g){ int i; EdgeNode *p; printf("\n图的邻接表图表示如下:\n"); for(i=0; i<g->n; i++){ printf("%2d [%c]",i,g->adjlist[i].data); p = g->adjlist[i].firstedge; while(p != NULL){ printf("-->[%d]",p->adjvex); p = p->next; } printf("\n"); } } //图的深度优先遍历 void DFS(AdjList *g,int vi){ EdgeNode *p; printf("(%d",vi); printf("%c)",g->adjlist[vi].data); visited[vi] = 1; p = g->adjlist[vi].firstedge; while(p != NULL){ if(visited[p->adjvex] == 0) DFS(g,p->adjvex); p = p->next; } } //图的广度优先遍历 void BFS(AdjList *g,int vi){ int i,v,visited[MAX]; int qu[MAX],front=0,rear=0; //定义循环队列 EdgeNode *p; for(i=0; i<g->n; i++) //辅助的访问数组赋初值 visited[i] = 0; printf("(%d",vi); //输出起始访问顶点 printf("%c)",g->adjlist[vi].data); visited[vi] = 1; rear = (rear+1) % MAX; //队尾指针后移 qu[rear] = vi; //将vi入队 while(front != rear){ //当队不空时 front = (front+1) % MAX; v = qu[front]; //将对头元素出队,赋给顶点v p = g->adjlist[v].firstedge; //将顶点v的下一条邻接边顶点指针赋给p while(p != NULL){ if(visited[p->adjvex] == 0){ //若未被访问过 visited[p->adjvex] = 1; //访问数组该元素置1,已访问 printf("(%d",p->adjvex); //输出该顶点编号 printf("%c)",g->adjlist[p->adjvex].data); //输出该顶点信息 rear = (rear+1) % MAX; //队尾指针后移 qu[rear] = p->adjvex; //将p所指的顶点入队 } p = p->next; //p指针后移 } } } void Menu() { printf(" 图的各种操作"); printf("\n=================================================="); printf("\n| 1--创建该无向图的邻接矩阵存储结构 |"); printf("\n| 2--输出该无向图的邻接矩阵表示 |"); printf("\n| 3--输入任意两个结点,判断是否有边存在 |"); printf("\n| 4--输入任意一个结点,求顶点的度 |"); printf("\n| 5--根据邻接矩阵求该无向图中边的数目 |"); printf("\n| 6--建立图的邻接表的算法 |"); printf("\n| 7--实现图的深度优先遍历 |"); printf("\n| 8--实现图的广度优先遍历 |"); printf("\n| 0--返回 |"); printf("\n=================================================="); printf("\n请输入菜单号(0-8):"); } main(){ MGraph G; AdjList g; char choice,a,m,n; int f,i; while(1){ Menu(); scanf("%c",&choice); getchar(); switch(choice){ case '1': CreateMGraph(&G); printf("建立成功!\n"); break; case '2': printf("该无向图的邻接矩阵表示为:\n"); DispMGraph(G); break; case '3': printf("请输入两个顶点(中间用空格分开): "); scanf("%c %c",&m,&n); if(EdgeMGraph(&G,m,n)) printf("有边!\n"); else printf("无边!\n"); break; case '4': printf("请输入一个结点:"); scanf("%c",&m); printf("这个结点的度为:%d\n",DegreeMGraph(&G,m)); break; case '5': printf("该无向图中边的数目是:%d\n",AllMGraph(&G)); break; case '6': printf("要建立的是有向图(1)还是无向图(0),请选择: "); scanf("%d",&f); CreateAGraph(&g,f); DispAGraph(&g); break; case '7': printf("请输入开始深度优先遍历的顶点序号(序号从0开始编号): "); scanf("%d",&f); printf("\n从顶点%d开始深度优先遍历序列为:",f); for(i=0; i<g.n; i++) visited[i] = 0; DFS(&g,f); break; case '8': printf("请输入开始广度优先遍历的顶点序号(序号从0开始编号): "); scanf("%d",&i); printf("\n从顶点%d开始广度优先遍历序列为:",i); BFS(&g,i); break; case '0': exit(1); default: printf("请重新输入\n"); } if(choice != '0'){ printf("\n按回车继续,按任意键返回主菜单!\n"); a = getchar(); if(a != '\xA'){ getchar(); exit(1); } } } }