一步一步学数据结构之n--n(图--邻接链表法实现)

来源:互联网 发布:驾校时间安排 知乎 编辑:程序博客网 时间:2024/06/05 18:13

 

       在上篇文章已经介绍过图的内容,而且还介绍了用邻接矩阵实现的图,而在本篇文章,就说下用邻接链表实现的图。

       常做的操作可以在上篇文章中查找,因为两中方法实现的图操作都是一模一样的。 代码总分为三个文件:(LGraph.h , LGraph.c , Main.c  )。整体结构图为:

       简单说下邻接链表法:

          

      如果对邻接链表法还不懂的话,建议拿直笔把图画下和代码结合着看,代码里面也有注释,希望能帮到你,如果还不懂的话,可以在文章下面评论留言!

      OK! 上代码:

      LGraph.h ,

 

#ifndef _LGRAPH_H_#define _LGRAPH_H_typedef void LGraph;typedef void LVertex;typedef void (LGraph_Printf)(LVertex*);/* 创建并返回有n个顶点的图 */LGraph* LGraph_Create(LVertex** v, int n);/* 销毁graph所指向的图 */void LGraph_Destory(LGraph* graph);/* 将graph所指图的边集合清空 */void LGraph_Clear(LGraph* graph);/* 在graph所指图中的v1和v2之间加上边,且边的权为w */int LGraph_AddEdge(LGraph* graph, int v1, int v2, int w);/* 将graph所指图中v1和v2之间的边删除,返回权值 */int LGraph_RemoveEdge(LGraph* graph, int v1, int v2);/* 将graph所指图中v1和v2之间的边的权值返回 */int LGraph_GetEdge(LGraph* graph, int v1, int v2);/* 将graph所指图中v顶点的度数 */int LGraph_TD(LGraph* graph, int v);/* 将graph所指图中的顶点数返回 */int LGraph_VertexCount(LGraph* graph);/* 将graph所指图中的边数返回 */int LGraph_EdgeCount(LGraph* graph);/* 将graph所指图输出 */void LGraph_Display(LGraph* graph, LGraph_Printf* pFunc);#endif


 

      LGraph.c , 

#include <stdio.h>#include <malloc.h>#include "LGraph.h"#include "LinkList.h"typedef struct _tag_LGraph{//头结点定义 int count;//顶点个数 LVertex** v;//顶点相关的数据 LinkList** la;//链表数组 }TLGraph;typedef struct _tag_ListNode{//边描述结点 LinkListNode header; int v;//边指向的顶点标号 int w;//权值 }TListNode;LGraph* LGraph_Create(LVertex** v, int n){TLGraph* ret = NULL;int ok = 0;if((NULL != v) && (0 < n)){//申请头结点内存 ret = (TLGraph*)malloc(sizeof(TLGraph));if(NULL != ret){ret->count = n;//通过二级指针动态申请一维指针数组 ret->v = (LVertex**)calloc(n, sizeof(LVertex*));ret->la = (LinkList**)calloc(n, sizeof(LinkList*));ok = (NULL != ret->v) && (NULL != ret->la);if(ok){int i = 0;for(i=0; i<n; i++){//把指针数组和数据空间连接起来 ret->v[i] = v[i];}for(i=0; (i<n)&&ok; i++){//为指针数组每个指针创建链表 ok = ok && (NULL != (ret->la[i] = LinkList_Create()));}}if(!ok){if(NULL != ret->la){ int i = 0;for(i=0; i<n; i++){LinkList_Destroy(ret->la[i]);}}free(ret->v);free(ret->la);free(ret);ret = NULL;}}}return ret;}void LGraph_Destroy(LGraph* graph){//销毁图 TLGraph* tGraph = (TLGraph*)graph;//先清理,再销毁 LGraph_Clear(graph);if(NULL != tGraph){int i = 0;for(i=0; i<tGraph->count; i++){//销毁链表数组中的链表 LinkList_Destroy(tGraph->la[i]);}free(tGraph->v);free(tGraph->la);free(tGraph);}}void LGraph_Clear(LGraph* graph){TLGraph* tGraph = (TLGraph*)graph;if(NULL != tGraph){int i = 0;for(i=0; i<tGraph->count; i++){//遍历链表数组 while(0 < LinkList_Length(tGraph->la[i])){//把链表数组中每一个链表的每一个结点所占的内存都释放掉 free(LinkList_Delete(tGraph->la[i], 0));}}}}int LGraph_AddEdge(LGraph* graph, int v1, int v2, int w){//(v1--->v2  权值为w) TLGraph* tGraph = (TLGraph*)graph;TListNode* node = NULL;//安全性检测 int ret = (NULL != tGraph);ret = ret && (0 <= v1) && (v1 < tGraph->count);ret = ret && (0 <= v2) && (v2 < tGraph->count);ret = ret && (0 <=  w) && (NULL != (node = (TListNode*)malloc(sizeof(TListNode))));if(ret){node->v = v2;//赋入顶点 node->w = w;//赋入权值 //插入到v1链表中,因为v1链表中的结点都是v1的出度 LinkList_Insert(tGraph->la[v1], (LinkListNode*)node, 0);}return ret;}int LGraph_RemoveEdge(LGraph* graph, int v1, int v2){//(v1--->v2 删除v1到v2的边) TLGraph* tGraph = (TLGraph*)graph;int ret = 0;//安全性检测 int condition = (NULL != tGraph);condition = condition && (0 <= v1) && (v1 < tGraph->count);condition = condition && (0 <= v2) && (v2 < tGraph->count);if(condition){TListNode* node = NULL;int i = 0;for(i=0; i<tGraph->count; i++){//要删除v1到v2的边,就要从v1链表中寻找 node = (TListNode*)LinkList_Get(tGraph->la[v1], i);if(node->v == v2){//匹配到的话 就删除 ret = node->w;LinkList_Delete(tGraph->la[v1], i);free(node);break;}}}return ret;}int LGraph_GetEdge(LGraph* graph, int v1, int v2){//(v1--->v2  获取v1到v2的边的权值) TLGraph* tGraph = (TLGraph*)graph;int ret = 0;//安全性检测 int condition = (NULL != tGraph);condition = condition && (0 <= v1) && (v1 < tGraph->count);condition = condition && (0 <= v2) && (v2 < tGraph->count);if(condition){int i = 0;for(i=0; i<tGraph->count; i++){//从v1链表中寻找 TListNode* node = (TListNode*)LinkList_Get(tGraph->la[v1], i);if(node->v == v2){//匹配好以后把边的权值返回 ret = node->w;break;}}}return ret;}int LGraph_TD(LGraph* graph, int v){//获取v顶点的出度和入度和 TLGraph* tGraph = (TLGraph*)graph;int ret = 0;int condition = (NULL != tGraph);condition = condition && (0 <= v) && (v < tGraph->count);if(condition){int i = 0;int j = 0;for(i=0; i<tGraph->count; i++){//遍历链表数组中每一个链表 for(j=0; j<LinkList_Length(tGraph->la[i]); j++){// 遍历每一个链表中的每一个结点 TListNode* node = (TListNode*)LinkList_Get(tGraph->la[i], j);if(node->v == v){//匹配即进行自加 ret++;}}}//最后再加上v的出度,也就是v链表的长度 ret += LinkList_Length(tGraph->la[v]);}return ret;}int LGraph_VertexCount(LGraph* graph){//获取顶点个数 TLGraph* tGraph = (TLGraph*)graph;int ret = 0;if(NULL != tGraph){ret = tGraph->count;}return ret;}int LGraph_EdgeCount(LGraph* graph){//获取边的个数 TLGraph* tGraph = (TLGraph*)graph;int ret = 0;if(NULL != tGraph){int i = 0;for(i=0; i<tGraph->count; i++){//遍历链表数组中的每一个链表,获取长度,计算总和 ret += LinkList_Length(tGraph->la[i]);}}return ret;}void LGraph_Display(LGraph* graph, LGraph_Printf* pFunc){TLGraph* tGraph = (TLGraph*)graph;if((NULL!=tGraph) && (NULL!=pFunc)){int i = 0;int j = 0;for(i=0; i<tGraph->count; i++){//输出顶点信息 printf("%d: ", i);pFunc(tGraph->v[i]);printf("\n");}printf("\n");//输出边信息 包括 <xx顶点--->xx顶点 权值:xx> for(i=0; i<tGraph->count; i++){for(j=0; j<LinkList_Length(tGraph->la[i]); j++){TListNode* node  = (TListNode*)LinkList_Get(tGraph->la[i], j);printf("<");pFunc(tGraph->v[i]);printf(" , ");pFunc(tGraph->v[node->v]);printf(" : %d>\n", node->w);}}printf("\n");}}


 

      Main.c  

#include <stdio.h>#include "LGraph.h"void print_data(LVertex* v){if(NULL != v){printf("%s", (char*)v);}}int main(void){LVertex* v[] = {"A", "B", "C", "D", "E", "F"};LGraph* graph = LGraph_Create(v, 6);LGraph_AddEdge(graph, 0, 1, 1);LGraph_AddEdge(graph, 0, 2, 1);LGraph_AddEdge(graph, 0, 3, 1);LGraph_AddEdge(graph, 1, 5, 1);LGraph_AddEdge(graph, 1, 4, 1);LGraph_AddEdge(graph, 2, 1, 1);LGraph_AddEdge(graph, 3, 4, 1);LGraph_AddEdge(graph, 4, 2, 1);LGraph_Display(graph, print_data);printf("2 TD  : %d\n", LGraph_TD(graph, 2));printf("Vertex: %d\n", LGraph_VertexCount(graph));printf("Edge  : %d\n", LGraph_EdgeCount(graph));LGraph_Destroy(graph);return 0;}


 

原创粉丝点击