二哥学算法之图(开篇)
2015-03-17 18:29
169 查看
图论问题几乎涉及整个计算机科学,成千上百的计算问题几乎都可以归纳总结为图论问题。生活中也有很多需要图论的例子,如以后为大家提到的最大二分图匹配,最小费用最大流,单源最短路径等等,我对这部分也只是略知一个,有错误之处还望大家指出。
先定义一下图:一个图(Graph)可以看做是边和点的集合。我们有G=(V,E) V(vertex)表示顶点集,E(Edge)表示边集。每一条边就是一个点对(u,v),如果一个点对是有序的,比如说只能从u到v,从v到u是 非法的;则(u,v)这条边就是有序的。反之,则有无向图。即(u,v),(v,u)都是合法的。图常常还会具有第三种属性,叫做权(weight)或值(cost)。
现在给大家介绍两种图的表示方法。邻接链表和邻接矩阵。
邻接矩阵表示起来相对来说比较简单即通过一个二维数组Array[N
,对于每一条边(u,v),可以置Array[u[[v]=1,如果边上有权值。则可以用一个很大或者很小的值表示不存在的边。
下面是一个用邻接矩阵表示图的示例代码:
用这种方法表示图很简单,不要很明显看以看出。图的空间需求为
,如果图的边不是很多,那么这种表示方法就有点浪费内存了。如果图是稠密的,
这种方法就是很合适的。
另一方面如果图不是稠密的,换句话说如果是稀疏的,则更好的解决办法就是用上面提高的邻接链表了。对于每一个顶点,我们使用一个表来存储所有的邻接顶点。此时空间需求度为
。下面我写一个示例性的邻接表实现(质量很渣渣,不要模仿,仅供参考)
以上;下篇为大家带来图的BFS和DFS。
先定义一下图:一个图(Graph)可以看做是边和点的集合。我们有G=(V,E) V(vertex)表示顶点集,E(Edge)表示边集。每一条边就是一个点对(u,v),如果一个点对是有序的,比如说只能从u到v,从v到u是 非法的;则(u,v)这条边就是有序的。反之,则有无向图。即(u,v),(v,u)都是合法的。图常常还会具有第三种属性,叫做权(weight)或值(cost)。
现在给大家介绍两种图的表示方法。邻接链表和邻接矩阵。
邻接矩阵表示起来相对来说比较简单即通过一个二维数组Array[N
,对于每一条边(u,v),可以置Array[u[[v]=1,如果边上有权值。则可以用一个很大或者很小的值表示不存在的边。
下面是一个用邻接矩阵表示图的示例代码:
#include <iostream> #define INIFY 66553 #define N 8 //顶点数目 int array int Edge_Numbers; int main(void){ int i,j,k; std::cout<<"请输入顶点数: "<<std::endl; std::cin>>Edge_Numbers; //初始化顶点 for(i=0;i<N;i++) for(j=0,j<N;j++) array[i][j]=INIFY; std::cout<<"请输入顶点关系和权值"<<std::endl; for(int m=0;m<Edge_Numbers;m++){ std::cin>>i>>j>>k; array[i][j]=k; //如果是无向图 array[j][i]=array[i][j]=K; } return 0; }
用这种方法表示图很简单,不要很明显看以看出。图的空间需求为
,如果图的边不是很多,那么这种表示方法就有点浪费内存了。如果图是稠密的,
这种方法就是很合适的。
另一方面如果图不是稠密的,换句话说如果是稀疏的,则更好的解决办法就是用上面提高的邻接链表了。对于每一个顶点,我们使用一个表来存储所有的邻接顶点。此时空间需求度为
。下面我写一个示例性的邻接表实现(质量很渣渣,不要模仿,仅供参考)
#include <iostream> #define N 4 int array[N][N]; //邻接表 struct Edge{ int from; int to; int weight; Edge *next; Edge(int _from=-1,int _to=-1,int _weight=0): from(_from),to(_to),weight(_weight){ } }; Edge *edge[N]={nullptr,nullptr,nullptr}; void add_edge(){ int u,v,k; Edge *p=nullptr; std::cout<<"请输入顶点i,j和k;以-2作为结束。"<<std::endl; while(std::cin>>u>>v>>k&&u!=-2,v!=-2){ p=new Edge; p->from=u,p->to=v,p->weight=k,p->next=nullptr; p->next=edge[u]; edge[u]=p; } } void print_edge(Edge *p){ Edge *v; std::cout<<"和"<<p->from<<"邻接的顶点及其权重值如下: "<<std::endl; for(v=p;v!=nullptr;p=p->next,v=p) std::cout<<v->to<<" weight:"<<v->weight<<std::endl; } int main(void){ add_edge(); print_edge(edge[1]); return 0; }
以上;下篇为大家带来图的BFS和DFS。
相关文章推荐
- 算法总结与思考(开篇)
- 算法与数据结构开篇
- 算法系列——开篇及目录
- Java数据结构和算法(一)——开篇
- 各大IT公司算法、数据结构面试题、分析、考点、解答(开篇)
- 一步一步写算法(开篇)
- 一步一步写算法(开篇)
- 【算法学习笔记】87. 枚举路径 SJTU OJ 1999 二哥找宝藏
- 共识算法之开篇
- 【算法学习笔记】24.记忆化搜索 解题报告 SJTU OJ 1002 二哥种花生
- 数据结构与算法开篇
- 算法开篇
- 一步一步写算法(开篇)
- 二哥学算法之链表逆转
- 【算法学习笔记】45. 二分答案 BFS路径 SJTU OJ 1031 二哥在黄山
- [开篇]基础算法和数据结构0
- 二哥学算法之单向链表
- 【算法学习笔记】53.单调队列的简单应用 SJTU OJ 1034 二哥的金链
- 每天一个算法题:开篇
- 1.算法开篇