今天我和大家一起来学习图,首先说下图的定义:
图分为有向图和无向图
在这里,来一起了解下度和权的概念:
这里介绍图的常用操作:
l 创建图
l 销毁图
l 清空图的边
l 在图中两个顶点连接起来,并带权
l 删除两个顶点的边,把权返回
l 返回图中某两个顶点之间边的权值
l 返回图中某个顶点的度
l 返回图中顶点数
l 返回图中的边数
l 输出图
代码总分为三个文件:
MGraph.h , MGraph.c , Main.c
整体结构图为:
简单说下邻接矩阵:
这里就不再详细介绍图的一些操作细节,因为是用邻接矩阵实现的,也就是用一个二维数组实现的,所以大部分操作都类似于二维数组操作,只要细细阅读代码就会理解的。
OK! 上代码:
MGraph.h ,
#ifndef _MGRAPH_H_ #define _MGRAPH_H_ typedef void MGraph; typedef void MVertex; typedef void (MGraph_Printf)(MVertex*); /* 创建并返回有n个顶点的图 */ MGraph* MGraph_Create(MVertex** v, int n); /* 销毁graph所指向的图 */ void MGraph_Destory(MGraph* graph); /* 将graph所指图的边集合清空 */ void MGraph_Clear(MGraph* graph); /* 在graph所指图中的v1和v2之间加上边,且边的权为w */ int MGraph_AddEdge(MGraph* graph, int v1, int v2, int w); /* 将graph所指图中v1和v2之间的边删除,返回权值 */ int MGraph_RemoveEdge(MGraph* graph, int v1, int v2); /* 将graph所指图中v1和v2之间的边的权值返回 */ int MGraph_GetEdge(MGraph* graph, int v1, int v2); /* 将graph所指图中v顶点的度数 */ int MGraph_TD(MGraph* graph, int v); /* 将graph所指图中的顶点数返回 */ int MGraph_VertexCount(MGraph* graph); /* 将graph所指图中的边数返回 */ int MGraph_EdgeCount(MGraph* graph); /* 将graph所指图输出 */ void MGraph_Display(MGraph* graph, MGraph_Printf* pFunc); #endif
MGraph.c ,
#include <malloc.h> #include <stdio.h> #include "MGraph.h" typedef struct _tag_MGraph//定义图 { int count; MVertex** v; int** matrix; }TMGraph; MGraph* MGraph_Create(MVertex** v, int n) { TMGraph* ret = NULL; if((NULL!=v) && (0<n)) { ret = (TMGraph*)malloc(sizeof(TMGraph)); if(NULL != ret) { int* p = NULL; ret->count = n; //通过二级指针动态申请一维指针数组 ret->v = (MVertex**)malloc(sizeof(MVertex*) * n); ret->matrix = (int**)malloc(sizeof(int*) * n); //通过一级指针申请数据空间 //calloc函数把申请的数据空间全清0 p = (int*)calloc(n * n, sizeof(int)); if((NULL!=ret->v) && (NULL!=ret->matrix) && (NULL!=p)) { int i = 0; for(i=0; i<n; i++) {//把指针数组和数据空间连接起来 ret->v[i] = v[i]; ret->matrix[i] = p + i* n; } } else { free(ret->v); free(ret->matrix); free(p); free(ret); ret = NULL; } } } return ret; } void MGraph_Destory(MGraph* graph) { TMGraph* tGraph = (TMGraph*)graph; if(NULL != tGraph) { free(tGraph->v); //销毁通过一级指针申请的数据空间 free(tGraph->matrix[0]); //销毁通过二级指针申请的一维指针空间 free(tGraph->matrix); free(tGraph); } } void MGraph_Clear(MGraph* graph) { TMGraph* tGraph = (TMGraph*)graph; if(NULL != tGraph) { int i = 0; int j = 0; for(i=0; i<tGraph->count; i++) { for(j=0; j<tGraph->count; j++) {//清楚边的信息 保存顶点的信息 tGraph->matrix[i][j] = 0; } } } } int MGraph_AddEdge(MGraph* graph, int v1, int v2, int w) { TMGraph* tGraph = (TMGraph*)graph; int ret = (NULL!=tGraph); ret = ret && (0 <= v1) && (v1 < tGraph->count); ret = ret && (0 <= v2) && (v2 < tGraph->count); ret = ret && (0 <= w); if(ret) {//增加连线也就是给描述边的数组相应位置赋值 tGraph->matrix[v1][v2] = w; } return ret; } int MGraph_RemoveEdge(MGraph* graph, int v1, int v2) { int ret = MGraph_GetEdge(graph, v1, v2); if(0 != ret) {//相应的,删除边的信息也就是给相应位置赋空 ((TMGraph*)graph)->matrix[v1][v2] = 0; } return ret; } int MGraph_GetEdge(MGraph* graph, int v1, int v2) { TMGraph* tGraph = (TMGraph*)graph; int ret = 0; int condition = (NULL != tGraph); condition = condition && (0 <= v1) && (v1 < tGraph->count); condition = condition && (0 <= v2) && (v2 < tGraph->count); if(condition) {//从二维数组相应位置取权值 ret = tGraph->matrix[v1][v2]; } return ret; } int MGraph_TD(MGraph* graph, int v) { TMGraph* tGraph = (TMGraph*)graph; int ret = 0; if((NULL != tGraph) && (0 <= v) && (v < tGraph->count)) { int i = 0; int j = 0; for(i=0; i<tGraph->count; i++) {//直接返回V所在的行和列顶点的总数也就是 出度+入度 if(0 != tGraph->matrix[i][v]) { ret++; } if(0 != tGraph->matrix[v][i]) { ret++; } } } return ret; } int MGraph_VertexCount(MGraph* graph) { TMGraph* tGraph = (TMGraph*)graph; int ret = 0; if(NULL != tGraph) { ret = tGraph->count; } return ret; } int MGraph_EdgeCount(MGraph* graph) { TMGraph* tGraph = (TMGraph*)graph; int ret = 0; if(NULL != tGraph) { int i = 0; int j = 0; for(i=0; i<tGraph->count; i++) { for(j=0; j<tGraph->count; j++) {//返回总边数,也就是判断描述边信息的数组的非0值个数 if(0 != tGraph->matrix[i][j]) { ret++; } } } } return ret; } void MGraph_Display(MGraph* graph, MGraph_Printf* pFunc) { TMGraph* tGraph = (TMGraph*)graph; if((NULL != tGraph) && (NULL != pFunc)) { int i = 0; int j = 0; for(i=0; i<tGraph->count; i++) {//输出顶点信息 printf("%d: ", i+1); pFunc(tGraph->v[i]); printf(" "); } printf(" "); for(i=0; i<tGraph->count; i++) { for(j=0; j<tGraph->count; j++) { if(0 != tGraph->matrix[i][j]) {//输出边信息 printf("<"); pFunc(tGraph->v[i]); printf(", "); pFunc(tGraph->v[j]); printf(": %d", tGraph->matrix[i][j]); printf(" > "); } } } printf(" "); } }
Main.c
#include <stdio.h> #include "MGraph.h" void print_data(MVertex* v) { if(NULL != v) { printf("%s", (char*)v); } } int main(void) { MVertex* v[] = {"A", "B", "C", "D", "E", "F"}; MGraph* graph = MGraph_Create(v, 6); MGraph_AddEdge(graph, 0, 1, 1); MGraph_AddEdge(graph, 0, 2, 1); MGraph_AddEdge(graph, 0, 3, 1); MGraph_AddEdge(graph, 1, 5, 1); MGraph_AddEdge(graph, 1, 4, 1); MGraph_AddEdge(graph, 2, 1, 1); MGraph_AddEdge(graph, 3, 4, 1); MGraph_AddEdge(graph, 4, 2, 1); MGraph_Display(graph, print_data); printf("2 TD : %d ", MGraph_TD(graph, 2)); printf("Vertex: %d ", MGraph_VertexCount(graph)); printf("Edge : %d ", MGraph_EdgeCount(graph)); MGraph_Destory(graph); return 0; }