数据结构封装之《LGraph邻接表式图》
2018-02-02 11:48
253 查看
说明:
邻接表是图的另一种有效的存储表示方法. 每个顶点u建立一个单链表, 链表中每个结点代表一条边《u, v》,为边结点,每个单链表相当于邻接矩阵的一行;通过复用LinkList和LinkQueue的方法封装的LGraph,请看:
数据结构封装之《LinkList单向链表》
数据结构封装之《LinkQueue链式队列》
下面将给出该数据结构的代码,每个函数的结构分析 ,以及个别主要函数的汇编分析
代码:
TGraph.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_Destroy(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); //深度优先遍历 void LGraph_DFS(LGraph* graph, int v, LGraph_Printf* pFunc); //广度优先遍历 void LGraph_BFS(LGraph* graph, int v, LGraph_Printf* pFunc); void LGraph_Display(LGraph* graph, LGraph_Printf* pFunc); #endif
TGraph.c
#include <malloc.h> #include <stdio.h> #include "LGraph.h" #include "LinkList.h" f243 #include "LinkQueue.h" typedef struct _tag_LGraph { int count; LVertex** v; LinkList** la; } TLGraph; typedef struct _tag_ListNode { LinkListNode header; int v; int w; } TListNode; //深度优先递归遍历 static void recursive_dfs(TLGraph* graph, int v, int visited[], LGraph_Printf* pFunc) { int i = 0; pFunc(graph->v[v]);//打印当前元素数据 visited[v] = 1;//已访问的元素下标,要做标志 printf(", "); //当前元素的下级元素访问 for(i=0; i<LinkList_Length(graph->la[v]); i++) { TListNode* node = (TListNode*)LinkList_Get(graph->la[v], i); //检查是否被访问过,若无则进入该元素的深度遍历 if( !visited[node->v] ) { recursive_dfs(graph, node->v, visited, pFunc); } } } //广度优先遍历 static void bfs(TLGraph* graph, int v, int visited[], LGraph_Printf* pFunc) { LinkQueue* queue = LinkQueue_Create(); if( queue != NULL ) { LinkQueue_Append(queue, graph->v + v);//将当前元素入队 visited[v] = 1;//已访问的元素下标,要做标志 while( LinkQueue_Length(queue) > 0 ) { int i = 0; v = (LVertex**)LinkQueue_Retrieve(queue) - graph->v;//当前元素出队 pFunc(graph->v[v]);//打印当前访问的元素 printf(", "); //检查当前元素是否有下级元素 for(i=0; i<LinkList_Length(graph->la[v]); i++) { TListNode* node = (TListNode*)LinkList_Get(graph->la[v], i);//逐一获取其下级元素 if( !visited[node->v] )//检查该下级元素是否被访问过 { LinkQueue_Append(queue, graph->v + node->v);//将该没被访问的元素入队 visited[node->v] = 1;//入队的元素,标记已访问 } } } } LinkQueue_Destroy(queue); } LGraph* LGraph_Create(LVertex** v, int n) // O(n) { TLGraph* ret = NULL; int ok = 1; if( (v != NULL ) && (n > 0) ) { ret = (TLGraph*)malloc(sizeof(TLGraph)); if( ret != NULL ) { ret->count = n; ret->v = (LVertex**)calloc(n, sizeof(LVertex*)); ret->la = (LinkList**)calloc(n, sizeof(LinkList*)); ok = (ret->v != NULL) && (ret->la != NULL); 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 && ((ret->la[i] = LinkList_Create()) != NULL); } } if( !ok ) { if( ret->la != NULL ) { int i = 0; for(i=0; i<n; i++) { LinkList_Destroy(ret->la[i]); } } free(ret->la); free(ret->v); free(ret); ret = NULL; } } } return ret; } void LGraph_Destroy(LGraph* graph) // O(n*n) { TLGraph* tGraph = (TLGraph*)graph; LGraph_Clear(tGraph); if( tGraph != NULL ) { int i = 0; for(i=0; i<tGraph->count; i++) { LinkList_Destroy(tGraph->la[i]); } free(tGraph->la); free(tGraph->v); free(tGraph); } } void LGraph_Clear(LGraph* graph) // O(n*n) { TLGraph* tGraph = (TLGraph*)graph; if( tGraph != NULL ) { int i = 0; for(i=0; i<tGraph->count; i++) { while( LinkList_Length(tGraph->la[i]) > 0 ) { free(LinkList_Delete(tGraph->la[i], 0)); } } } } int LGraph_AddEdge(LGraph* graph, int v1, int v2, int w) // O(1) { TLGraph* tGraph = (TLGraph*)graph; TListNode* node = NULL; int ret = (tGraph != NULL); ret = ret && (0 <= v1) && (v1 < tGraph->count); ret = ret && (0 <= v2) && (v2 < tGraph->count); ret = ret && (0 < w) && ((node = (TListNode*)malloc(sizeof(TListNode))) != NULL); if( ret ) { node->v = v2; node->w = w; LinkList_Insert(tGraph->la[v1], (LinkListNode*)node, 0); } return ret; } int LGraph_RemoveEdge(LGraph* graph, int v1, int v2) // O(n*n) { TLGraph* tGraph = (TLGraph*)graph; int condition = (tGraph != NULL); int ret = 0; 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<LinkList_Length(tGraph->la[v1]); i++) { 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) // O(n*n) { TLGraph* tGraph = (TLGraph*)graph; int condition = (tGraph != NULL); int ret = 0; 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<LinkList_Length(tGraph->la[v1]); i++) { 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) // O(n*n*n) { TLGraph* tGraph = (TLGraph*)graph; int condition = (tGraph != NULL); int ret = 0; 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++; } } } ret += LinkList_Length(tGraph->la[v]); } return ret; } int LGraph_VertexCount(LGraph* graph) // O(1) { TLGraph* tGraph = (TLGraph*)graph; int ret = 0; if( tGraph != NULL ) { ret = tGraph->count; } return ret; } int LGraph_EdgeCount(LGraph* graph) // O(n) { TLGraph* tGraph = (TLGraph*)graph; int ret = 0; if( tGraph != NULL ) { int i = 0; for(i=0; i<tGraph->count; i++) { ret += LinkList_Length(tGraph->la[i]); } } return ret; } void LGraph_DFS(LGraph* graph, int v, LGraph_Printf* pFunc) { TLGraph* tGraph = (TLGraph*)graph; int* visited = NULL; int condition = (tGraph != NULL); condition = condition && (0 <= v) && (v < tGraph->count); condition = condition && (pFunc != NULL); condition = condition && ((visited = (int*)calloc(tGraph->count, sizeof(int))) != NULL); if( condition ) { int i = 0; //以深度优先方式,打印当前顶点的所有内容 recursive_dfs(tGraph, v, visited, pFunc); //检查未访问的顶点 for(i=0; i<tGraph->count; i++) { if( !visited[i] ) { recursive_dfs(tGraph, i, visited, pFunc); } } printf("\n"); } free(visited); } void LGraph_BFS(LGraph* graph, int v, LGraph_Printf* pFunc) { TLGraph* tGraph = (TLGraph*)graph; int* visited = NULL; int condition = (tGraph != NULL); condition = condition && (0 <= v) && (v < tGraph->count); condition = condition && (pFunc != NULL); condition = condition && ((visited = (int*)calloc(tGraph->count, sizeof(int))) != NULL); if( condition ) { int i = 0; //以广度优先方式,打印当前顶点的所有内容 bfs(tGraph, v, visited, pFunc); //检查未访问的顶点 for(i=0; i<tGraph->count; i++) { if( !visited[i] ) { bfs(tGraph, i, visited, pFunc); } } printf("\n"); } free(visited); } void LGraph_Display(LGraph* graph, LGraph_Printf* pFunc) // O(n*n*n) { TLGraph* tGraph = (TLGraph*)graph; if( (tGraph != NULL) && (pFunc != NULL) ) { int i = 0; int j = 0; for(i=0; i<tGraph->count; i++) { printf("%d:", i); pFunc(tGraph->v[i]); printf(" "); } printf("\n"); 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", node->w); printf(">"); printf(" "); } } printf("\n"); } }
main.c
#include <stdio.h> #include <stdlib.h> #include "LGraph.h" void print_data(LVertex* v) { printf("%s", (char*)v); } int main(int argc, char *argv[]) { 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); LGraph_RemoveEdge(graph, 0, 1, 1); int edgeW = LGraph_GetEdge(graph,0,2); int td = LGraph_TD(graph,0); int vc = LGraph_VertexCount(graph); int ec = LGraph_EdgeCount(graph); LGraph_DFS(graph, 0, print_data); LGraph_BFS(graph, 0, print_data); LGraph_Destroy(graph); return 0; }
函数结构分析:
1.tGraph_Create2.LGraph_Destroy
3.LGraph_Clear
4.LGraph_AddEdge
5.LGraph_RemoveEdge
6.LGraph_GetEdge
7.LGraph_TD
8.LGraph_VertexCount
9.LGraph_EdgeCount
汇编分析:
main1.tGraph_Create
2.LGraph_Destroy
3.LGraph_Clear
4.LGraph_AddEdge
5.LGraph_RemoveEdge
6.LGraph_GetEdge
7.LGraph_TD
8.LGraph_VertexCount
9.LGraph_EdgeCount
相关文章推荐
- 封装TableView有可能用到的数据结构和UITableViewCell的一个继承类
- 数据结构4.进一步封装的双向链表
- JS高级-数据结构的封装
- 【算法和数据结构】线性表(三)栈的定义和封装
- java 数据结构实现数组封装 (一)
- 数据结构封装之《DLinkList双向链表》
- C++与C#对常用数据结构封装的对比(STL vs System.Collections.Generic)
- 对象容器 - Java对数据结构的封装 - List, ArrayList, LinkedList, Set, SortedSet, HashSet, Map, TreeMap
- 3D游戏引擎底层数据结构的封装之Stack
- 封装c++与matlab引擎交互的数据结构:行优先矩阵类
- 数据结构封装之《SeqList顺序栈》
- 对象容器 - Java对数据结构的封装 - List, ArrayList, LinkedList, Set, SortedSet, HashSet, Map, TreeMap
- 【原】C++与C#对常用数据结构封装的对比(STL vs System.Collections.Generic)
- 3D游戏引擎底层数据结构的封装之List
- 3D游戏引擎底层数据结构的封装之Stack
- 数据结构-有头双向循环链表2(封装)
- 数据结构封装之《LinkQueue链式队列》
- week03_python内置数据结构__封装、解构
- 3D游戏引擎底层数据结构的封装之List
- 二维表的数据可以被封装成的数据结构(集合)