图的基本操作,为了便于信息即可显示,在函数内部输出了数据,可后修改来实现更接近封装程序。
程序包可在次下载:http://download.csdn.net/detail/decting/4850581
GraphTestApp.c内容:
#include <stdio.h> #include "M_AL_Graph.h" int main() { int i,j,n,m,x,y,w; Mgraph A; //定义邻接矩阵, Graph* G=CreateGraph(); //定义图并创建图 //输入图信息,文件方式,可注释掉来手动输入 freopen("Input.txt","r",stdin); scanf("%d%d",&n,&m); //输入节点数和边数 for(i=0; i<m; i++) { scanf("%d%d%d",&x,&y,&w); AddGraphEdge(G,x,y,w); //无向图正反两遍加入边 AddGraphEdge(G,y,x,w); } AdjGraphMatrix(G,A); //得到邻接矩阵,以0填充无关边 //测试1、输出邻接矩阵 printf("1、\n邻接矩阵如下:\n"); for(i=1;i<=n;i++) { for(j=1;j<=n;j++) printf("%2d ",A[i][j]); printf("\n"); } //测试2、输出邻接表 printf("2、\n邻接表如下:\n"); DisplayGraph(G); //测试3、输出深度和宽度遍历 printf("3、\n深度遍历如下:\n"); GraphDeepthTraversal(G); printf("\n宽度遍历如下:\n"); GraphBreadthTraversal(G); //测试4、输出prim算法生成的最小生成树,个边和总权值 printf("\n4、\n最小生成树的各边分别为:"); printf("\n最小生成树总权值为:%d\n",GraphPrim(G)); return 0; } /* -------------------------------------- 测试图数据1 | 测试图数据2 6 10 | 6 10 1 6 21 | 1 2 6 1 5 19 | 1 3 1 1 2 10 | 1 4 5 2 6 11 | 2 3 5 5 6 33 | 3 4 5 4 6 14 | 2 5 3 4 5 18 | 3 5 6 3 4 6 | 3 6 4 2 4 6 | 5 6 6 2 3 5 | 4 6 2 -------------------------------------- */ /*测试图数据1的结果: -------------------------------------- 1、 邻接矩阵如下: 0 10 0 0 19 21 10 0 5 6 0 11 0 5 0 6 0 0 0 6 6 0 18 14 19 0 0 18 0 33 21 11 0 14 33 0 2、 邻接表如下: 1: 2 5 6 2: 1 3 4 6 3: 2 4 4: 2 3 5 6 5: 1 4 6 6: 1 2 4 5 3、 深度遍历如下: 1 2 3 4 5 6 宽度遍历如下: 1 2 5 6 3 4 4、 最小生成树的各边分别为:10 5 6 11 18 最小生成树总权值为:50 Press any key to continue -------------------------------------- */M_AL_Graph.h的内容:
/**** * 每个图会有一个图的头部,定义时如下 * Graph* G; * CreateGraphHead(&G); * 或者如下定义 * Graph* G=CreateGraph(); * Mgraph 是邻接矩阵的定义类型 * 定义时,Mgraph A;等价于WeightType A[MAXNODE][MAXNODE]; * WeightType是int型 * GraphDeepthTraversal(Graph*)和GraphBreadthTraversal(Graph*) * 分别是深度和宽度优先遍历的调用函数,直接调用 * GraphPrim(Graph*)为prim生成最小生成树,又返回值,为生成树总权值 *******/ #ifndef _M_AL_GRAPH_H_ #define _M_AL_GRAPH_H_ #include <memory.h> #include <string.h> #include <stdlib.h> #include <stdio.h> #define MAXWEIGHT 0x7FFFFFFF #define MAXNODE 300 //定义最大节点数 typedef int NodeType; //节点类型 typedef int WeightType; //定义邻接矩阵,Graph是二维数组的标示 typedef WeightType Mgraph[MAXNODE][MAXNODE]; typedef struct GNODE {//定义图中每个节点的信息,节点信息和连接的节点 NodeType data; WeightType weight; struct GNODE* link; }GraphNode; typedef struct GRAPH {//定义图类型 GraphNode *node; struct GRAPH* next; }Graph; Graph* CreateGraph(); void CreateGraphHead(Graph**); void CreateGraphNode(GraphNode**); void AddGraphNode(Graph*,NodeType); void DisplayGraphNode(Graph*); void AddGraphEdge(Graph*,NodeType,NodeType,WeightType); void AdjGraphMatrix(Graph*,Mgraph); void DisplayGraph(Graph*); GraphNode* FindGraphNode(Graph*,NodeType); void GraphDeapth(Graph*,GraphNode*,WeightType*); void GraphDeepthTraversal(Graph*); void GraphBreadthTraversal(Graph*); WeightType GraphPrim(Graph*); #endif //_M_AL_GRAPH_H_M_AL_Graph.c的内容:
#include "M_AL_Graph.h" Graph* CreateGraph(void) {//返回式创建图节点 Graph* Temp_G; CreateGraphHead(&Temp_G); return Temp_G; } void CreateGraphHead(Graph** G) {//调用式创建图头部节点 *G=(Graph*)malloc(sizeof(Graph)); (*G)->next=NULL; CreateGraphNode(&(*G)->node); } void CreateGraphNode(GraphNode** N) {//创建节点 *N=(GraphNode*)malloc(sizeof(GraphNode)); (*N)->weight=(*N)->data=0; (*N)->link=NULL; } void AddGraphNode(Graph* G,NodeType N) {//增加节点,向图中增加节点,会按照从小到大的顺序排列 Graph* Temp_G=CreateGraph(); while(G->next!=NULL&&G->next->node->data<=N) G=G->next; if(G->node->data==N) return; Temp_G->next=G->next; Temp_G->node->data=N; G->next=Temp_G; } void DisplayGraphNode(Graph* G) {//临时的图节点输出,便于调试,查看 while(G->next!=NULL) { G=G->next; printf("%d ",G->node->data); } } void AddGraphEdge(Graph* G,NodeType N1,NodeType N2,WeightType W) {//加入边,N1到N2的权值为W GraphNode *Temp_N,*N; CreateGraphNode(&Temp_N); //先创建个节点 AddGraphNode(G,N1); //保证N1在图中 AddGraphNode(G,N2); //保证N2在图中 while(G->next->node->data!=N1) G=G->next;//寻找N1节点的位置 N=G->next->node; Temp_N->data=N2; Temp_N->weight=W; while(N->link!=NULL&&N->link->data<=N2) N=N->link;//寻找N2该插入的位置 Temp_N->link=N->link; N->link=Temp_N; } void AdjGraphMatrix(Graph* G,Mgraph A) {//Adjacent Matrix, 得到图G的邻接矩阵A GraphNode *N; NodeType X; //初始化A内权值为0,表示不相连接 memset(A,0,MAXNODE*MAXNODE*sizeof(WeightType)); while(G->next!=NULL) { G=G->next; N=G->node; X=N->data; while(N->link!=NULL) { N=N->link; A[X][N->data]=N->weight; } } } void DisplayGraph(Graph* G) {//以邻接矩阵的形式输出G GraphNode *N; while(G->next!=NULL) { G=G->next; N=G->node; printf("%2d: ",N->data); while(N->link!=NULL) { N=N->link; printf("%2d ",N->data); } printf("\n"); } } GraphNode* FindGraphNode(Graph* G,NodeType N) {//根据N节点,寻找并返回结构体节点指针 while(G->next!=NULL&&G->next->node->data!=N) G=G->next; return G->next->node; } void GraphDeapth(Graph* G,GraphNode* N,WeightType* Visited) {//深度优先遍历Deeth First Traversal,过程函数 GraphNode *Temp_N=FindGraphNode(G,N->data); if(Temp_N==NULL||Visited[Temp_N->data]) return; printf("%d ",Temp_N->data); Visited[Temp_N->data]=1; while(Temp_N->link!=NULL) { Temp_N=Temp_N->link; GraphDeapth(G,Temp_N,Visited); } } void GraphDeepthTraversal(Graph* G) {//深度优先遍历operator调用函数 int Visited[MAXNODE]={0};//访问点表示数组 if(G->next==NULL) return; GraphDeapth(G,G->next->node,Visited); } void GraphBreadthTraversal(Graph* G) {//宽度优先遍历Breadth First Traversal,使用循环队列实现 int front=0,rear=0,Visited[MAXNODE]={0}; GraphNode **GraphQueue,*N;//定义循环队列头 if(G->next==NULL) return; GraphQueue=(GraphNode*)malloc(MAXNODE*sizeof(GraphNode)); GraphQueue[rear++]=G->next->node;//初始第一个成员为G图中的第一个 while(front!=rear) { N=FindGraphNode(G,GraphQueue[front++]->data); if(Visited[N->data]) continue; printf("%d ",N->data); Visited[N->data]=1; while(N->link!=NULL) { N=N->link; GraphQueue[rear++]=N; } } } WeightType GraphPrim(Graph* G) {//prim算法实现的最小生成树,各边的weight直接在函数内部 //输出,返回最小生成树的总权值 Mgraph A; GraphNode* N; int n=0,Visited[MAXNODE]={0}; WeightType M[MAXNODE]={MAXWEIGHT},STree=0; if(G->next==NULL) return; AdjGraphMatrix(G,A); N=G->next->node; Visited[N->data]=1; while(G->next!=NULL)G=G->next,n++; while(N->link!=NULL)N=N->link,M[N->data]=N->weight; while(1) { int i,k=0; for(i=1; i<=n; i++) if(!Visited[i]&&(M[k]>M[i]&&M[i])) k=i; if(!k) break; printf("%d ",M[k]); Visited[k]=1; STree+=M[k]; for(i=1; i<=n; i++) if(!Visited[i]&&(M[i]>A[k][i]||!M[i])&&A[k][i]) M[i]=A[k][i]; } return STree; }附加文件Input.txt:
6 10 1 6 21 1 5 19 1 2 10 2 6 11 5 6 33 4 6 14 4 5 18 3 4 6 2 4 6 2 3 5