图 邻接矩阵 邻接表

来源:互联网 发布:c语言变量名命名规则 编辑:程序博客网 时间:2024/05/17 04:23

1.图常用的两种存储结构:邻接矩阵和邻接表。

2. 邻接矩阵结构和操作定义

SeqQueue.h

//功能:邻接矩阵图的广度遍历用到的队列结构体#define QUEUE_MAXSIZE 256typedef struct{int Data[QUEUE_MAXSIZE];//QUEUE_MAXSIZE在GraphTest.cpp文件中定义int head;int tail;}SeqQueue;//队列相关操作void QueueInit(SeqQueue *Q){Q->head=Q->tail = 0;}//因为判断空函数不设计改变队列Q,所以参数不是指针变量int QueueIsEmpty(SeqQueue *Q){return (Q->head == Q->tail);}int QueueIsFull(SeqQueue *Q){return ((Q->tail + 1) %QUEUE_MAXSIZE == Q->head);}int QueueIn(SeqQueue *Q, int ch){if(QueueIsFull(Q)){printf("队列已满,无法再插入!!");return 0;}Q->Data[Q->tail] = ch;Q->tail = (Q->tail + 1)%QUEUE_MAXSIZE;return 1;}int QueueOut(SeqQueue *Q, int *ch){if(QueueIsEmpty(Q)){printf("队列已空!!");return 0;}*ch = Q->Data[Q->head];Q->head = (Q->head + 1)%QUEUE_MAXSIZE;return 1;}


AdjMatrixGraph.h

#include"SeqQueue.h"#define VERTEX_MAX 26//图的最大顶点数,26个字母#define MAXVALUE 32767//表示两点间不构成边//Prim算法用到#define USED 0//已使用,加入U集合#define NOADJ -1//非邻接点//功能:邻接矩阵结构体typedef struct{char Vertex[VERTEX_MAX];//保存顶点信息int Endges[VERTEX_MAX][VERTEX_MAX];        //保存边的权int isTrav[VERTEX_MAX];//顶点遍历标识int VertexNum;//顶点总数int EndgeNum;//边总数int GraphType;//图的类型}MatrixGraph;/*--------------------------函数原型声明 start----------------------*/void CreateMatrixGraph(MatrixGraph *G);//功能:创建邻接矩阵图void OutMatrix(MatrixGraph *G);//功能:输出邻接矩阵图void BFSTraverse(MatrixGraph *G);//功能:广度优先遍历主函数void BFSM(MatrixGraph *G, int k);//功能:广度优先遍历具体实现void DFSTraverse(MatrixGraph *G);//功能:深度优先遍历主函数void DFSM(MatrixGraph *G, int k);//功能:深度优先遍历具体实现void Prim(MatrixGraph G);//功能:Prim最小生成树算法具体实现void Dijkstra(MatrixGraph G);//功能:Dijkstra最短路径算法具体实现/*--------------------------函数原型声明 end----------------------*//*--------------------------函数具体实现 start----------------------*///功能:创建邻接矩阵图void CreateMatrixGraph(MatrixGraph *G){char start, end;int i,j,k;int weight;printf("请输入生成图的类型(0:无向图, 1:有向图):");fflush(stdin);scanf("%d", &G->GraphType);printf("请输入图的顶点数和边数:");fflush(stdin);scanf("%d %d", &G->VertexNum, &G->EndgeNum);for(i=0; i<G->VertexNum; i++)//清空邻接矩阵for(j=0; j<G->VertexNum; j++)G->Endges[i][j] = MAXVALUE;printf("请输入各顶点信息:\n");for(i=0; i<G->VertexNum; i++){printf("请输入第%d个顶点的信息:", i+1);fflush(stdin);scanf("%c", &(G->Vertex[i]));}printf("请输入构成各边的两个顶点及权值:\n");for(k=0; k<G->EndgeNum; k++){printf("请输入第%d条边的两个顶点及权值(用空格分隔):", k+1);fflush(stdin);scanf("%c %c %d", &start, &end, &weight);for(i=0; start!=G->Vertex[i]; i++);for(j=0; end!=G->Vertex[j]; j++);G->Endges[i][j] = weight;if(G->GraphType == 0)G->Endges[j][i] = weight;}return;}//功能:输出邻接矩阵图void OutMatrix(MatrixGraph *G){int i, j;for(i=0; i<G->VertexNum; i++)printf("\t%c", G->Vertex[i]);printf("\n");for(i=0; i<G->VertexNum; i++){printf("%c\t", G->Vertex[i]);for(j=0; j<G->VertexNum; j++){if(G->Endges[i][j] == MAXVALUE)printf("∞\t");elseprintf("%d\t", G->Endges[i][j]);}printf("\n");}return;}//功能:广度优先遍历主函数void BFSTraverse(MatrixGraph *G){int i;for(i=0; i<G->VertexNum; i++)G->isTrav[i] =0;printf("广度优先遍历节点:");for(i=0; i<G->VertexNum; i++)if(!G->isTrav[i])BFSM(G, i);printf("\n");}//功能:广度优先遍历具体实现void BFSM(MatrixGraph *G, int k){int i,j;SeqQueue Q;QueueInit(&Q);G->isTrav[k] = 1;printf("->%c", G->Vertex[k]);QueueIn(&Q, k);while(!QueueIsEmpty(&Q)){QueueOut(&Q, &i);for(j=0; j<G->VertexNum; j++)if(G->Endges[i][j] != MAXVALUE && !G->isTrav[j]){G->isTrav[j] = 1;printf("->%c", G->Vertex[j]);QueueIn(&Q, j);}}}//功能:深度优先遍历主函数void DFSTraverse(MatrixGraph *G){int i;for(i=0; i<G->VertexNum; i++)G->isTrav[i] = 0;printf("深度优先遍历节点:");for(i=0; i<G->VertexNum; i++)if(!G->isTrav[i])DFSM(G, i);printf("\n");}//功能:深度优先遍历具体实现(递归)void DFSM(MatrixGraph *G, int k){int i,j;G->isTrav[k] = 1;printf("->%c",G->Vertex[k]);for(j=0; j<G->VertexNum; j++)if(G->Endges[k][j] != MAXVALUE && !G->isTrav[j])DFSM(G, j);}//功能:Prim最小生成树算法具体实现void Prim(MatrixGraph G){int i,j,k,min,sum=0;//Prim算法两个辅助数组int weight[VERTEX_MAX];//保存tmpvertex中对应邻接边的权值char tmpvertex[VERTEX_MAX];//保存邻接顶点信息//初始化:保存邻接矩阵中的一行数据,即0号顶点的邻接顶点、权值for(i=1; i<G.VertexNum; i++){weight[i] = G.Endges[0][i];if(weight[i] == MAXVALUE)tmpvertex[i] = NOADJ;//非邻接点elsetmpvertex[i] = G.Vertex[0];//邻接点}tmpvertex[0] = USED;weight[0] = MAXVALUE;//生成最小生成树:即包含所有顶点for(i=1; i<G.VertexNum; i++){min = weight[0];k=i;for(j=1; j<G.VertexNum; j++)if(weight[j] < min && tmpvertex[j]!=0){min = weight[j];k=j;}sum +=min;printf("(%c,%c),", tmpvertex[k],G.Vertex[k]);tmpvertex[k] = USED;weight[k] = MAXVALUE;for(j=0; j<G.VertexNum; j++)if(G.Endges[k][j] < weight[j] && tmpvertex[j] != 0){weight[j] = G.Endges[k][j];tmpvertex[j] = G.Vertex[k];}}printf("\n最小生成树的总权值为:%d\n", sum);}//功能:Dijkstra最短路径算法具体实现void Dijkstra(MatrixGraph G){//Dijkstra算法辅助数组int weight[VERTEX_MAX];int path[VERTEX_MAX];int tmpvertex[VERTEX_MAX];int i,j,k,v0,min;printf("\n请输入源点的编号:");fflush(stdin);scanf("%d", &v0);v0--;//编号减1(因为数组从0开始)//初始辅助数组for(i=0; i<G.VertexNum;i++){weight[i] = G.Endges[v0][i];//保存最小权值if(weight[i]<MAXVALUE && weight[i] > 0)  //有效权值path[i] = v0;tmpvertex[i] =0;}tmpvertex[v0] = 1;//将顶点v0添加到集合U中weight[v0] = 0;//将源顶点的权值设为0for(i=0; i<G.VertexNum; i++){min = MAXVALUE;k = v0;for(j=0;j<G.VertexNum;j++)if(tmpvertex[j] == 0 && weight[j]<min){min = weight[j];k = j;}tmpvertex[k] = 1;for(j=0; j<G.VertexNum; j++)if(tmpvertex[j] == 0 && weight[k] + G.Endges[k][j] < weight[j]){weight[j] = weight[k] + G.Endges[k][j];path[j] = k;}}//输出结果printf("\n顶点%c到各顶点的最短路径为(终点 < 源点):\n", G.Vertex[v0]);for(i=0; i<G.VertexNum; i++){if(tmpvertex[i]==1){k=i;while(k!=v0){printf("%c < ", G.Vertex[k]);k = path[k];//上一个顶点}printf("%c\n", G.Vertex[k]);}elseprintf("%c<-%c:无路径\n", G.Vertex[i], G.Vertex[v0]);}}/*--------------------------函数具体实现 end----------------------*/

3. 邻接表结构和操作定义

AdjListGraph.h

#define VERTEX_MAX 20//功能:邻接表边的结构体typedef struct edgeNode{int Vertex;//顶点序号int weight;//权值struct edgeNode *next;//指向下一个顶点}EdgeNode;//功能:图的邻接表存储结构体typedef struct{EdgeNode *AdjList[VERTEX_MAX];int VertexNum;int EndgeNum;int GraphType;}ListGraph;/*--------------------------函数原型声明 start----------------------*/void CreateListGraph(ListGraph *G);//功能:创建邻接表图void OutList(ListGraph *G);//功能:输出表图/*--------------------------函数原型声明 end----------------------*//*--------------------------函数具体实现 start----------------------*///功能:创建表图void CreateListGraph(ListGraph *G){int i, weight;int start, end;EdgeNode *s;printf("请输入生成图的类型(0:无向图, 1:有向图):");fflush(stdin);scanf("%d", &G->GraphType);printf("请输入图的顶点数和边数:");fflush(stdin);scanf("%d %d", &G->VertexNum, &G->EndgeNum);for(i=0; i<G->VertexNum; i++)//将图中各顶点指针清空G->AdjList[i] = NULL;for(i=1; i<=G->EndgeNum; i++){printf("请输入第%d条边的两个顶点及权值:", i);fflush(stdin);scanf("%d %d %d", &start, &end, &weight);s = (EdgeNode *)malloc(sizeof(EdgeNode));if(s==NULL){printf("申请内存失败!!");return ;}s->next = G->AdjList[start];//头插法,将顶点插入到链表中s->weight = weight;s->Vertex = end;G->AdjList[start] = s;if(G->GraphType == 0){s = (EdgeNode *)malloc(sizeof(EdgeNode));if(s==NULL){printf("申请内存失败!!");return ;}s->next = G->AdjList[end];s->weight = weight;s->Vertex = start;G->AdjList[end] = s;}}return;}//功能:输出表图void OutList(ListGraph *G){int i;EdgeNode *s;for(i=1; i<=G->VertexNum; i++){printf("顶点%d", i);s = G->AdjList[i];while(s){printf("->%d(%d)",s->Vertex, s->weight);s = s->next;}printf("\n");}return;}/*--------------------------函数具体实现 end----------------------*/

4.图操作测试函数

GraphTest.cpp

#include<stdio.h>#include<stdlib.h>#define QUEUE_MAXSIZE 30//SeqQueue.h头文件中队列元素最大值#include"AdjListGraph.h"#include"AdjMatrixGraph.h"int main(){int select;ListGraph LG;MatrixGraph G;do{printf("---------------------------\n");printf("1.用邻接矩阵法创建图       2.输出邻接矩阵\n");printf("3.用邻接表法创建图         4.输出邻接表\n");printf("5.广度优先遍历邻接矩阵图   6.深度优先遍历邻接矩阵图\n");printf("7.求邻接矩阵图的最小生成树 8.求邻接矩阵图指定顶点到其他顶点的最短路径\n");printf("0.退出\n");printf("请选择执行的操作序号:");//select = getch();fflush(stdin);scanf("%d", &select);switch(select){case 1:CreateMatrixGraph(&G);break;case 2:printf("邻接矩阵数据如下:\n");OutMatrix(&G);break;case 3:CreateListGraph(&LG);break;case 4:printf("邻接矩阵数据如下:\n");OutList(&LG);break;case 5:BFSTraverse(&G);break;case 6:DFSTraverse(&G);break;case 7:printf("构成最小生成树的边如下:\n");Prim(G);break;case 8:printf("最短路径算法开始执行:\n");Dijkstra(G);break;}}while(select != 0);system("pause");return 1;}


原创粉丝点击