16、图
来源:互联网 发布:淘宝手机下单减价 编辑:程序博客网 时间:2024/05/22 02:12
1、图作为一种模型来定义对象之间的关系。对象由顶点表示,而对象之间的关系则通过顶点之间的边来表示。
2、图分为有向图和无向图,有向图的边叫做弧。
3、图的表达式:G = (V, E),E包含有序对(u,v),对于无向图无所谓(u,v)和(v,u)。
如上图,有向图:V={v0, v1, v2, v3}. E={(v0,v1), (v2, v0), (v2, v3), (v3, v0)}.
无向图:V={v0, v1, v2, v3,v4}.E={(v0, v1), (v0, v3),(v1, v2), (v1, v4), (v2, v3), (v2, v4)}
4、图中两个重要关系:邻接、关联
邻接:有向图中(v0, v1)说明v1邻接v0。
完全图:一个图中每一个顶点都与其他顶点相邻接
关联:有向图中(v0, v1)说明边(v0, v1)从顶点v0关联到v1,顶点和边的关系。
5、顶点的入度:以该顶点为终点的边数。
顶点的出度:以该顶点为起点的边数。
简单路径:没有重复顶点的路径
环:路径包含相同的节点两次或以上,即从某点出发最后能返回到某点。
6、连通:每个顶点都能通过某条路径到达其他顶点。
关节点:移除某个顶点将使图或某分支失去连通性。
桥:移除某条边使得图失去连通性。
7、邻接表适用于稀疏图;邻接矩阵适用于稠密图
8、搜索方法:广度优先搜索、深度优先搜索
深度优先搜索
9、代码实现
(1)数据结构:每个顶点对应一个链表节点,节点中*data指向节点结构AdjList
//AdjList包含:顶点;与该顶点相连接的一个顶点集合。这是每个链表节点指向的数据datatypedef struct AdjList_{ void *vertex; Set adjacent;}AdjList;//整个图的属性,包含:节点数、边数、所有节点组成的链表属性typedef struct Graph_{ int vcount; int ecount; int (*match)(const void *key1, const void *key2); void (*destroy)(void *data); List adjlists;}Graph;typedef enum VertexColor_{ white, gray, black}VertexColor;
(2)初始化
void graph_init(Graph *graph, int (*match)(const void *key1, const void *key2), void(*destroy)(void *data)){ graph->vcount = 0; graph->ecount = 0; graph->match = match; graph->destroy = destroy; list_init(graph->adjlists, 0, NULL, NULL, NULL); return;}
(3)删除整个图
void graph_destroy(Graph *graph){ AdjList *adjlist; while(list_size(&graph->adjlists) > 0) { if(list_rem_next(&graph->adjlists, NULL, (void **)&adjlist) == 0) { //删除每个顶点的邻节点集合 set_destroy(&adjlist->adjacent); //删除该顶点,这两者就是链表节点指向的*data if(graph->destroy != NULL) graph->destroy(adjlist->vertex); //释放*data指向结构自身的空间,上面为该空间指向的内容 free(adjlist); } }}
(4)插入一个顶点:申请一个AdjList,其中成员vertex为data,其边集set初始化为NULL
//这里入口参数*data对应 *adjlist中vertex int graph_ins_vertex(Graph *graph, const void *data){ LIST_ELEMENT *element; AdjList *adjlist; int retval; for(element = list_tail(graph->adjlists); element != NULL; element = list_next(element)) { if(graph->match(data, ((AdjList *)list_data(element))->vertex)) return 1; } if((adjlist = (AdjList *)malloc(sizeof(AdjList))) == NULL) return -1; adjlist->vertex = (void *)data; set_init(&adjlist->adjacent, graph->match, NULL); if((retval = list_ins_next(&graph->adjlists, list_tail(&graph->adjlists), adjlist)) != 0) return retval; graph->vcount++; return 0;}
(5)插入一条边
//在图中加入一条连线 //对于图中已存在顶点data1和data2,单向data1指向data2,就是在顶点data1的集合中加入data2 int graph_ins_edge(Graph *graph, const void *data1, const *data2){ LIST_ELEMENT *element; int retval; //先找到顶点data2和data1 for(element = list_head(graph->adjlists); element != NULL; element = list_next(element)) { if(graph->match(data2, ((AdjList *)list_data(element))->vertex)) break; } if(element == NULL) return -1; //向data1的集合中插入data2 if((retval = set_insert( &( (AdjList *)(list_data(element))->adjacent ), data2)) != 0 ) { return retval; } graph->ecount++;}
(6)删除顶点,顶点不能和其他任何顶点相连,即不在其他节点的集合中,自己的集合为空。
int graph_rem_vertex(Graph *graph, void **data){ LIST_ELEMENT *element; AdjList *adjlist; int found; prev = NULL; found = 0; for(element = list_head(graph->adjlists); element != NULL; element = list_next(element)) { if(set_is_mumber(&( (AdjList *)(list_data(element))->adjacent ), *data)) return -1; if(graph->match(*data,&( (AdjList *)(list_data(element))->vertex )) { temp = element; fount =1; } //此处在for内部,如果没发现则prev一直在更新 if(!found) prev = element; } if(!found) return -1; if(set_size( &((AdjList *)list_data(temp))->adjacent )> 0) return -1; *data = adjlist->vertex; //此时节点集合为空可以直接释放 free(adjlist); graph->vcount--; return 0;}
(7)删除边,即删除data1集合中的元素data2
int graph_rem_edge(Graph *graph, const void *data1, const *data2){ LIST_ELEMENT *element; //先找到顶点data1 for(element = list_head(graph->adjlists); element != NULL; element = list_next(element)) { if(graph->match(data1, ((AdjList *)list_data(element))->vertex)) break; } if(element == NULL) return -1; if(set_remove(&( (AdjList *)(list_data(element))->adjacent ), *data2)) != 0) return -1; graph->ecount--; return 0;}
(8)找到某个顶点对应的结构adjlist
//data对应的结构返回到adjlist int graph_adjlist(const Graph *graph, const void *data, AdjList **adjlist){ LIST_ELEMENT *element, *prev; prev = NULL; for(element = list_head(graph->adjlists); element != NULL; element = list_next(element)) { if(graph->match(*data,&( (AdjList *)(list_data(element))->vertex )) { break; } prev = element; } if(element == NULL) return -1; *adjlist = list_data(element); return 0;}
(9)判断顶点data1和data2是否有邻接关系,即判断data2是否存在于data1的集合中
int graph_is_adjacent(const Graph *graph, const void *data1, const void *data2){ LIST_ELEMENT *element, *prev; prev = NULL; for(element = list_head(graph->adjlists); element != NULL; element = list_next(element)) { if(graph->match(*data,&( (AdjList *)(list_data(element))->vertex )) { break; } prev = element; } if(element == NULL) return -1; return set_is_mumber(&( (AdjList *)(list_data(element))->adjacent ), data2);}
- 16、图
- 疯狂坦克图16
- 16张图,揭秘16个商品的价格构成
- 16位灰度图之TIFF
- 数据结构(16)--图的存储及实现
- RGB,16进制色彩图
- nyoj 16 嵌套矩阵(DAG图)
- 二部图最大匹配(2006-11-05 16:34)
- 1987年日机对苏联轰炸机警告射击 图-16充耳不闻
- 精图规范1.0----16 交互性 Interactivity
- [NWPU][2014][TRN][16]图论拓扑排序 H - 基础
- 数据结构第一章知识结构导图(信管1133-16
- 【学习笔记----数据结构16-图的存储结构】
- 动图展示16个Sublime Text快捷键用法
- 动图展示16个Sublime Text快捷键用法
- 课程笔记 16:数据结构(清华) 图-邻接矩阵
- 16位BMP图转32位BMP图
- 2015-11-16 【项目1 - 图基本算法库】
- 设计模式
- 关于spring 启动类公共配置
- python datetime的加减操作
- HDU 6119 小小粉丝度度熊【尺取法】
- HTML5-调用-购物车商品(del)-班级添加-也买酒
- 16、图
- java基础学习总结——面向对象1
- 数据库详解
- kendo grid表格加载完成之后触发事件dataBound
- 图的深度优先遍历和广度优先遍历
- LRCN(1)
- 打靶
- 练习 2017-8-14 缓冲字节/字符 输入/输出 流~ 字符的编码和解码
- MySQL 的redo 和 undo