数据结构------图-----深度广度优先遍历
图
为什么要用到图
线性表局限于一个直接前驱和一个直接后继的关系
树也只能有一个直接前驱也就是父节点
当我们需要表示多对多的关系时,这里我们就用到了图
也就是说图可以代表多对多之间的关系
图是一种数据结构,其中结点可以具有零个或多个相邻元素。两个结点之间的连接称为边。结点也可以称为顶点。
常用概念
1.顶点 就是我们的节点
2.边 我们相邻节点的连线
3.路径 节点之间有多少种方式连接
4.无向图
5.有向图 边有方向
6.带权图 带值的图
表示方式
1.二维数组表示法 邻接矩阵
2.链表表示 邻接表
我们发现很多地方都是无意义的,比较浪费空间
快速入门
代码
package 图;import java.util.ArrayList;
import java.util.Arrays;public class Graph {private ArrayList<String> vertexList; //存储顶点集合private int[][] edges; //存储图对应的邻接矩阵private int numOfEdges; //表示边的数目public static void main(String[] args) {int n = 5; //节点的个数String VertexValue[] = {"A","B","C","D","E"};//创建图对象Graph graph = new Graph(n);//循环添加顶点for(String value : VertexValue){graph.insertVertex(value);}//添加边// A-B A-C B-C B-D B-Egraph.insertEdge(0, 1, 1);graph.insertEdge(0, 2, 1);graph.insertEdge(1, 2, 1);graph.insertEdge(1, 3, 1);graph.insertEdge(1, 4, 1);//输出邻接矩阵graph.showGraph();}//构造器public Graph(int n){//初始化矩阵和vertexListedges = new int[n][n];vertexList = new ArrayList<String>(n);numOfEdges = 0;}//插入节点public void insertVertex(String vertex){vertexList.add(vertex);}//添加边/*** * @param v1 表示第一个顶点的下标即是第几个顶点* @param v2 第一个顶点的下标* @param weight 表示值是不是1即有没有连接起来*/public void insertEdge(int v1,int v2,int weight){edges[v1][v2] = weight;edges[v2][v1] = weight;numOfEdges++;}//返回节点的个数public int getNumOfVertex(){return vertexList.size();}//返回边的数目public int getNumOfEdges(){return numOfEdges;}//返回节点i对应的数据public String getValueByIndex(int i){return vertexList.get(i);}//返回v1和v2的权值public int getWeight(int v1,int v2){return edges[v1][v2];}//显示图对应的矩阵public void showGraph(){for (int[] link : edges) {System.err.println(Arrays.toString(link));}}
}
深度优先遍历
基本思想
深度优先遍历,从初始访问结点出发,初始访问结点可能有多个邻接结点,深度优先遍历的策略就是首先访问第一个邻接结点,然后再以这个被访问的邻接结点作为初始结点,访问它的第一个邻接结点, 可以这样理解: 每次都在访问完当前结点后首先访问当前结点的第一个邻接结点。
我们可以看到,这样的访问策略是优先往纵向挖掘深入,而不是对一-个结点的.所有邻接结点进行横向访问。
显然,深度优先搜索是一个递归的过程
步骤
1.访问初始结点v,并标记结点v已访问
2.查找节点V的第一个邻接节点W
3.若W存在,则执行第4步,如果w不存在,则回到第1步,将从v的下一个结点继续。
4.若w未被访问,对w进行深度优先遍历递归(即把w当做另一个v, 然后进行步骤123)。
5.查找节点v的W邻接节点的下一个邻接节点,转到步骤3
package 图;import java.util.ArrayList;
import java.util.Arrays;public class Graph {private ArrayList<String> vertexList; //存储顶点集合private int[][] edges; //存储图对应的邻接矩阵private int numOfEdges; //表示边的数目//定义一个boolean[] 记录某个点是否被访问过private boolean[] isVisited;public static void main(String[] args) {int n = 5; //节点的个数String VertexValue[] = {"A","B","C","D","E"};//创建图对象Graph graph = new Graph(n);//循环添加顶点for(String value : VertexValue){graph.insertVertex(value);}//添加边// A-B A-C B-C B-D B-Egraph.insertEdge(0, 1, 1);graph.insertEdge(0, 2, 1);graph.insertEdge(1, 2, 1);graph.insertEdge(1, 3, 1);graph.insertEdge(1, 4, 1);//输出邻接矩阵graph.showGraph();System.out.println("深度遍历");graph.dfs();}//构造器public Graph(int n){//初始化矩阵和vertexListedges = new int[n][n];vertexList = new ArrayList<String>(n);numOfEdges = 0;isVisited = new boolean[5];}//得到第一个邻接节点的下标public int getFirstNeighbor(int index){for (int i = 0; i < vertexList.size(); i++) {if(edges[index][i] > 0){return i;}}return -1;}//根据前一个邻接节点的下标,来获取下一个邻接节点的下标public int getNextNeighbor(int v1,int v2){for(int j = v2+1;j<vertexList.size();j++){if(edges[v1][j] > 0){return j;}}return -1;}//深度优先遍历算法public void dfs(boolean[] isVisited,int i){//首先访问该节点System.out.println(getValueByIndex(i)+"->");//将该节点设置为已访问isVisited[i] = true;//查找节点i的邻接节点int w = getFirstNeighbor(i);while(w!=-1){//有邻接节点if(!isVisited[w]){dfs(isVisited,w);}//如果已经被访问过w = getNextNeighbor(i, w);}}//对dfs重载,遍历所有节点,并进行dfspublic void dfs(){for(int i=0;i<getNumOfVertex();i++){if(!isVisited[i]){dfs(isVisited,i);}}}//插入节点public void insertVertex(String vertex){vertexList.add(vertex);}//添加边/*** * @param v1 表示第一个顶点的下标即是第几个顶点* @param v2 第一个顶点的下标* @param weight 表示值是不是1即有没有连接起来*/public void insertEdge(int v1,int v2,int weight){edges[v1][v2] = weight;edges[v2][v1] = weight;numOfEdges++;}//返回节点的个数public int getNumOfVertex(){return vertexList.size();}//返回边的数目public int getNumOfEdges(){return numOfEdges;}//返回节点i对应的数据public String getValueByIndex(int i){return vertexList.get(i);}//返回v1和v2的权值public int getWeight(int v1,int v2){return edges[v1][v2];}//显示图对应的矩阵public void showGraph(){for (int[] link : edges) {System.err.println(Arrays.toString(link));}}
}
广度优先遍历
基本思想
类似子一个分层搜索的过程,广度优先遍历需要使用一个队列以保持访问过的结点的顺序,以便按这个顺序来访问这些结点的邻接结点
步骤
- 访问初始结愈并标记结点v为已访问。
- 结点入队列
3当队列非空时,继续执行,(香则算法结束。 - 出队列,取得队头结点u。
- 查找结点u的第二个邻接结点w。
- 若落点u的邻接结点w不存在,则转到步骤3;否则循环执行以下三个步骤:
6.1若结点w尚未被访问,则访问结点w并标记为已访间。
6.2结点w入队列
6.3查找结点u的继w邻接结点后的下一个邻接结点w,转到步骤6。
代码
这里就直接贴出来我们的方法代码
//广度优先遍历private void bfs(boolean[] isVisited, int i){int u; //表示队列头结点的下标int w; //邻接节点的下标//需要一个队列,记录节点访问的顺序LinkedList queue = new LinkedList();//访问节点,输出节点信息System.out.print(getValueByIndex(i)+"->");//标记已访问isVisited[i] = true;//将节点加入队列queue.addLast(i);while(!queue.isEmpty()){//取出队列的头结点下标u = (Integer)queue.removeFirst();//得到第一个邻接节点的下标w = getFirstNeighbor(u);while(w != -1){//找到了 是否访问过if(!isVisited[w]){System.out.print(getValueByIndex(w)+"->");isVisited[w] = true;//入队queue.addLast(w);}//以u为前驱点,找w后面的下一个邻接节点w = getNextNeighbor(u, w);//体现出广度优先遍历 }}}//对所有节点进行广度优先搜索public void bfs(){for(int i=0;i<getNumOfVertex();i++){if(!isVisited[i]){bfs(isVisited, i);}}}
广度优先遍历
[0, 1, 1, 0, 0]
[1, 0, 1, 1, 1]
[1, 1, 0, 0, 0]
[0, 1, 0, 0, 0]
[0, 1, 0, 0, 0]
A->B->C->D->E->
两种遍历方式的区别
数据结构------图-----深度广度优先遍历相关推荐
- 数据结构 图的广度优先遍历 C++
分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! Bool ...
- 数据结构(廿五) -- C语言版 -- 图 - 图的遍历 -- 邻接矩阵 - 深度/广度优先遍历/搜索(DFS、BFS)
内容预览 零.读前说明 一.概 述 二.深度优先遍历(DFS) 2.1.无向图的遍历过程 2.2.有向图的遍历过程 2.3.总结说明 2.4.实现源代码 三.广度优先遍历(BFS) 3.1.广度优先的 ...
- 数据结构(廿六) -- C语言版 -- 图 - 图的遍历 -- 邻接表 - 深度/广度优先遍历/搜索(DFS、BFS)
内容预览 零.读前说明 一.深度优先遍历 1.1.深度优先的遍历过程 1.2.深度优先的遍历实现代码 二.广度优先遍历 2.1.广度优先的遍历过程 2.2.广度优先的遍历实现代码 三.源码测试效果 3 ...
- 数据结构与算法:终于可以用三种语言(C,C#,JavaScript)把图的广度优先遍历讲清楚了(推荐收藏)
文章目录 邻接矩阵存储图的广度优先遍历过程分析 C语言实现队列编程 程序中加入图的处理函数 结果的再次分析 C#语言实现图的广度优先遍历.并显示广度优先遍历生成树 JavaScript语言实现图的广度 ...
- 数据结构之栈的应用:树的层次遍历、图的广度优先遍历、OS的FCFS策略
栈的应用:树的层次遍历.图的广度优先遍历.OS的FCFS策略 树的层次遍历: 图的广度优先遍历 OS的FCFS策略: 树的层次遍历: 算法思想: 1.先遍历头节点1,头节点1入队 2.在遍历头节点的孩 ...
- 数据结构笔记(二十八)-- 图的广度优先遍历
图的广度优先遍历 一.基本思想 二.图的广度优先遍历举例 三.伪代码实现 邻接点的访问的实现需要根据图的存储方式来进行实现
- 图的深度广度优先遍历(DFC与BFC)JavaScript版
graph.js 创建一个js文件用于表示图这个类型,这个对象的键为节点,所对应的值为这个节点所连接的节点. const graph={0:[1,2],1:[2],2:[0,3],3:[3] }; m ...
- [C] 图的广度优先遍历
图的广度优先遍历 我一直觉得图的遍历没有地图类型的题目难,遍历嘛,每个点都走一遍就行了. 但是给定地图求面积啊,数量啊的那种题目,花样挺多的. 图的遍历真挺难把人绕晕的,关于广度优先,理解好层层递进这 ...
- 获取图顶点的入度、出度;获取图的两个顶点之间的权值; 图的深度优先算法、图的广度优先遍历
广度优先结果: 深度优先结果: 代码整理: public class Graph {private int vertexSize;//顶点数量private int[] vertexs;//顶点数组p ...
- 邻接表存储图的广度优先遍历
试实现邻接表存储图的广度优先遍历. 函数接口定义: void BFS ( LGraph Graph, Vertex S, void (*Visit)(Vertex) ); 其中LGraph是邻接表存储 ...
最新文章
- git stash和git stash pop
- 汇编语言随笔(9)-实验11(用条件转移指令来编写子程序)
- java弱引用怎么手动释放,Java 如何有效地避免OOM:善于利用软引用和弱引用
- 30个使用jQuery打造的世界级一流网站
- Redis【入门】就这一篇!
- 【分享预告】细数GAN和图像分类的前世今生
- 【Java】矩阵乘法的朴素算法
- 机器学习实战11-训练深层神经网络
- 云原生时代,政企混合云场景IT监控和诊断的难点和应对之道
- LINUX 安装 PHP5.6.13
- [Android Memory] Android系统中查看某个应用当前流量的方法
- 揭秘Keras推荐系统如何建立模型、获取用户爱好
- 系统分析师视频教程-张友生
- 通赢A5管理系统服务器连不进,赢通软件A5A6系列管理系统参数设置说明
- 怎么选择企业即时通讯软件
- 中药配方颗粒调剂设备解决方案!基于一体化步进电机,全闭环,集成原点回归算法,丰富的报警功能
- 使用Fiddler对手机App抓包
- 扩展easyUI样式,全新的easyUI体验样式
- Linux操作系统学习 | Linux常用命令
- 华为cmr一al09升级鸿蒙,华为平板 M5 10.8英寸 全网通(CMR-AL09)一键刷机教程,看教程秒懂刷机...
热门文章
- python arduino 蓝牙_树莓和Arduino之间的蓝牙通讯
- throw new exception后程序不停止_Java之Exception剖析
- commons-beanutils实现java深度克隆
- 论文笔记_S2D.40_2017_CVPR_半监督深度学习的单目深度图预测
- 自动驾驶_产品象限图_清洁机器人场景
- status函数(自学数据结构第一天)
- 无监督/自监督/半监督的景物分割方法
- LeetCode之长度最小的子数组
- 字符串格式连接sqlserver数据库的字段概念解释
- Linux的基本指令(2)-Linux从入门到精通第三天(非原创)