【2019暑假刷题笔记-图的存储和图的遍历】绪论(代码模板-总结自《算法笔记》)
一、图的存储
- 图有两种存储办法,分别是邻接矩阵(顶点数≤1000,0表示不连通,数字表示权重)和邻接表(用vector数组实现),具体实现如下:
/* 邻接矩阵,G[][] */G[2][3]=1; //2和3连接(可以认为权重为1) G[4][5]=0; //4和5不连接 G[7][8]=6; //7和8连接且权重为6 /* 邻接表 vector<int> Adj[N]; */Adj[1].push_back(3); //1和3连接//邻接表加权重 struct Node{int v; //边的终点编号int w; //边权 }; vector<Node> Adj[N]; //这样vector的邻接表的类型就是Node了Node temp; temp.v=3; temp.w=4; Adj[1].push_back(temp);//邻接表的另一种构造 struct Node{int v,w;Node(int_v,int_w):v(_v),w(_w){}; //构造函数 };Adj[1].push_back(Node(3,4));
以DFS法遍历图:
/* 伪码思想:不管是邻接表还是邻接矩阵都是采用这种办法的(注:连通图一次DFS解决) */ DFS(u){ //访问定点uvis[u]=true; //设置u被访问过了for(从u出发能到达的所有顶点v) //枚举从u出发的所有顶点vif vis[v]==false //如果v没有被访问过DFS(v); }DFSTrave(G){ //遍历Gfor(G的所有顶点u) //对G的所有顶点uif vis[u]==false //如果u未被访问DFS(u); //访问u所在的连通块 }
/* 邻接矩阵版DFS *///首先定义MAXV为最大顶点数、INF为一个很大的数字 const int MAXV=1000; const int INF=1000000000;int n,G[MAXV][MAXV]; //n为顶点数,MAXV为最大顶点数 bool vis[MAXV]={false}; void DFS(int u,int depth){vis[u]=true; //设置u已被访问//如果需要对u进行一些操作,可以在这里进行//下面对所有从u出发能到达的分支顶点进行枚举for(int v=0;v<n;v++){ //对每个顶点vif(vis[v]==false&&G[u][v]!=INF){ //如果v没有被访问且u可以达到vDFS(v,depth+1); //访问v,深度加1}} }void DFSTrave(){ //遍历图Gfor(int u=0;u<n;u++){ //对每个顶点uif(vis[u]==false){ //若u没有被访问过DFS(n,1); //访问u和u所在的连通块,1表示初试的第一层}} }
/* 邻接表版 */ const int MAXV=1000; vector<int> Adj[MAXV]; //图G的邻接表 int n; //n为顶点数,MAXV为最大顶点数 bool vis[MAXV]={false}; //若顶点i已经被访问过了,则vis[i]==true.初值为falsevoid DFS(int u,int depth){ //u为当前访问的顶点标号,depth为深度vis[u]=true; //设置u已经被访问//如果需要对u进行一些操作,可以在此处进行for(int i=0;i<Adj[u].size();i++){ //对从u出发可以到达的所有顶点vint v=Adj[u][i];if(vis[v]==false){ //若v没有被访问过DFS(v,depth+1); //访问v,深度+1}} }void DFSTrave(){ //遍历图Gfor(int u=0;u<n;u++){ //对每个顶点uif(vis[u]==false){ //若u未被访问DFS(u,1); //访问u和u所在的联通块,1表示初始值为第一层}} }
以BFS法遍历图:
/* 伪码思想 */ BFS(u){ //遍历u所在的连通块queue q;将u入队;inq[u]=true; //设置u已经被加入过队列while(q非空){ //只要队列非空取出q的队首元素u进行访问for(u出发可达的所有顶点v){ //枚举从u所能直接到达的顶点vif(inq[v]==false){ //若v未曾加入过队列将v入队inq[v]=true; //设置v已被加入过队列}}} }BFSTrave(){ //遍历图Gfor(G的所有顶点u) //枚举G的所有顶点uif(inq[u]==false){ //若u未曾加入过队列BFS(G); //遍历u所在的连通块} }
/* 邻接矩阵版 */ int n,G[MAXV][MAXV]; //n为顶点数,MAXV为最大顶点数 bool inq[MAXV]=false; //若顶点i曾入过队列,则inq[i]==true。初值为falsevoid BFS(int u){ //遍历u所在的连通块queue<int> q; //定义队列qq.push(u); //将初始点u入队inq[u]=true; //设置u已经进入过队列while(!q.empty()){ //只要队列非空int u=q.front(); //取出队首元素q.pop(); //将队首元素出队for(int v=0;v<n;v++){ if(inq[v]==false&&G[u][v]!=INF){ //若u的邻接点v未曾加入过队列q.push(v); //将v入队inq[v]=true; //标记v为已经被加入过队列}}} }void BFSTrave(){ //遍历图Gfor(int u=0;u<n;u++){ //枚举所有顶点if(inq[u]==false){ //若u未曾加入过队列BFS(q); //遍历u所在连通块}} }
/* 邻接表版 */ vector<int> Adj[MAXV]; //图G,Adj[u]存放从顶点u出发可以到达的所有顶点 int n; //n为顶点数,MAXV为最大顶点数 bool inq[MAXV]={false}; //若顶点i曾入过队列,则inq[i]==true。初值为falsevoid BFS(int u){ //遍历u所在的连通块queue<int> q; //定义队列qq.push(u); //将初始点u入队inq[u]=true; //设置u已经进入过队列while(!q.empty()){ //只要队列非空int u=q.front(); //取出队首元素q.pop(); //将队首元素出队for(int i=0;i<Adj[u].size();i++){ //枚举从u出发能到达的所有顶点int v=Adj[u][i]; if(inq[v]==false){ //若u的邻接点v未曾加入过队列q.push(v); //将v入队inq[v]=true; //标记v为已经被加入过队列}}} }void BFSTrave(){ //遍历图Gfor(int u=0;u<n;u++){ //枚举所有顶点if(inq[u]==false){ //若u未曾加入过队列BFS(q); //遍历u所在连通块}} }
/* 邻接表版,设置层号和编号 */ struct Node{int v;int layer; }vector<Node> Adj[MAXV]; //图G,Adj[u]存放从顶点u出发可以到达的所有顶点 int n; //n为顶点数,MAXV为最大顶点数 bool inq[MAXV]={false}; //若顶点i曾入过队列,则inq[i]==true。初值为falsevoid BFS(int s){ //遍历s为起编号queue<Node> q; //定义队列qNode start;start.v=s;start.layer=0;q.push(start); //将初始点start入队inq[start.v]=true; //设置start已经进入过队列while(!q.empty()){ //只要队列非空Node topNode=q.front(); //取出队首元素q.pop(); //将队首元素出队int u=topNode.v; //队首顶点的编号for(int i=0;i<Adj[u].size();i++){ //枚举从u出发能到达的所有顶点int next=Adj[u][i]; next.layer=topNode.layer+1;if(inq[next.v]==false){ //若next的邻接点v未曾加入过队列q.push(next); //将next入队inq[next.v]=true; //标记next为已经被加入过队列}}} }void BFSTrave(){ //遍历图Gfor(int u=0;u<n;u++){ //枚举所有顶点if(inq[u]==false){ //若u未曾加入过队列BFS(q); //遍历u所在连通块}} }
【2019暑假刷题笔记-图的存储和图的遍历】绪论(代码模板-总结自《算法笔记》)相关推荐
- 【2019暑假刷题笔记-STL绪论】总结自《算法笔记》
目 录 一.vector的常见用法 二.set的常见用法 三.string的常见用法 四.map的常见用法 一.vector的常见用法 vector是一种可变长数组,常用于使用vector通过 ...
- 【2019暑假刷题笔记-树的遍历】总结
关于树这一块,前期没有做一个学习的绪论,因为时间来不及了.在总结上回顾一下这些题目的一些特点 树的遍历的是数据结构树这一块中的一部分. 树的遍历和二叉树的遍历本质上相同.二叉树用指针也可以做,但是在考 ...
- 【2019暑假刷题笔记-链表】总结自《算法笔记》
目 录 一.创建链表节点 二.创建链表 三.创建链表 四.查找元素 五.插入元素 六.删除元素 七.静态链表 一.创建链表节点 /* struct node{typename data; //数据域 ...
- 【2019暑假刷题笔记-STL绪论(二)】总结自《算法笔记》
目录 五.queue的常见用法 六.priority_queue的常见用法 七.stack的常见用法 八.algorithm头文件下的常用函数 五.queue的常见用法 queue也就是队列,是STL ...
- $2019$ 暑期刷题记录 $2$(基本算法专题)
$ 2019 $ 暑期刷题记录 $ 2 $ (基本算法专题) $ by~~wch $ $ BZOJ~1958~Strange~Towers~of~Hanoi $ (动态规划,递推) 题目大意: 求有 ...
- leetcode怎么用时间刷_LeetCode刷题专栏第一篇--思维导图时间安排
昨天是元宵节,过完元宵节相当于这个年正式过完了.不知道大家有没有投入继续投入紧张的学习工作中.年前我想开一个Leetcode刷题专栏,于是发了一个投票想了解大家的需求征集意见.投票于2019年2月1日 ...
- LeetCode刷题专栏第一篇--思维导图时间安排
昨天是元宵节,过完元宵节相当于这个年正式过完了.不知道大家有没有投入继续投入紧张的学习工作中.年前我想开一个Leetcode刷题专栏,于是发了一个投票想了解大家的需求征集意见.投票于2019年2月1日 ...
- LeetCode刷题实战314:二叉树的竖直遍历
算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试.所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 ! 今天和大家 ...
- LeetCode刷题(45)~位1的个数【布赖恩·克尼根算法】
题目描述 编写一个函数,输入是一个无符号整数,返回其二进制表达式中数字位数为 '1' 的个数(也被称为汉明重量). 示例 1: 输入:00000000000000000000000000001011 ...
最新文章
- WebView你真的熟悉吗?看了才知道
- TI-BLE协议栈的GATT
- 在Python中用turtle函数画同心圆
- svn提交报e200007错误
- SAP WebIDE的本地安装方式
- r语言 面板数据回归_R语言_018回归
- 战胜柯洁战胜不了高中生?DeepMind挑战高中数学题,完败
- 云原生与AI时代的存储该是什么样?新华三发布全NVMe智能闪存与智慧中枢数据平台
- C语言求素数中flag的作用,c语言编程判断素数 c语言程序设计(判断素数)
- HUSTOJ SPJ 示例
- 安装英伟达显卡旧版驱动
- ps文字工具学习笔记
- RGB,CMY(K),YUV,YIQ,YCbCr颜色的转换算法(java实现)
- idea运行项目流程
- Flying-Saucer使用HTML或者FTL(Freemarker模板)生成PDF
- 计算死亡率(百分号的输出)
- MAP实现一个key,对应多个Value值。
- Java implements和extends的区别
- seata: endpoint format should like ip:port
- SAP SD基础知识之免费货物(Free Goods)