为什么要用到图

线性表局限于一个直接前驱和一个直接后继的关系
树也只能有一个直接前驱也就是父节点
当我们需要表示多对多的关系时,这里我们就用到了图

也就是说图可以代表多对多之间的关系

图是一种数据结构,其中结点可以具有零个或多个相邻元素两个结点之间的连接称为边。结点也可以称为顶点。

常用概念

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));}}
}

广度优先遍历

基本思想

类似子一个分层搜索的过程,广度优先遍历需要使用一个队列以保持访问过的结点的顺序,以便按这个顺序来访问这些结点的邻接结点

步骤

  1. 访问初始结愈并标记结点v为已访问。
  2. 结点入队列
    3当队列非空时,继续执行,(香则算法结束。
  3. 出队列,取得队头结点u。
  4. 查找结点u的第二个邻接结点w。
  5. 若落点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->

两种遍历方式的区别

数据结构------图-----深度广度优先遍历相关推荐

  1. 数据结构 图的广度优先遍历 C++

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! Bool ...

  2. 数据结构(廿五) -- C语言版 -- 图 - 图的遍历 -- 邻接矩阵 - 深度/广度优先遍历/搜索(DFS、BFS)

    内容预览 零.读前说明 一.概 述 二.深度优先遍历(DFS) 2.1.无向图的遍历过程 2.2.有向图的遍历过程 2.3.总结说明 2.4.实现源代码 三.广度优先遍历(BFS) 3.1.广度优先的 ...

  3. 数据结构(廿六) -- C语言版 -- 图 - 图的遍历 -- 邻接表 - 深度/广度优先遍历/搜索(DFS、BFS)

    内容预览 零.读前说明 一.深度优先遍历 1.1.深度优先的遍历过程 1.2.深度优先的遍历实现代码 二.广度优先遍历 2.1.广度优先的遍历过程 2.2.广度优先的遍历实现代码 三.源码测试效果 3 ...

  4. 数据结构与算法:终于可以用三种语言(C,C#,JavaScript)把图的广度优先遍历讲清楚了(推荐收藏)

    文章目录 邻接矩阵存储图的广度优先遍历过程分析 C语言实现队列编程 程序中加入图的处理函数 结果的再次分析 C#语言实现图的广度优先遍历.并显示广度优先遍历生成树 JavaScript语言实现图的广度 ...

  5. 数据结构之栈的应用:树的层次遍历、图的广度优先遍历、OS的FCFS策略

    栈的应用:树的层次遍历.图的广度优先遍历.OS的FCFS策略 树的层次遍历: 图的广度优先遍历 OS的FCFS策略: 树的层次遍历: 算法思想: 1.先遍历头节点1,头节点1入队 2.在遍历头节点的孩 ...

  6. 数据结构笔记(二十八)-- 图的广度优先遍历

    图的广度优先遍历 一.基本思想 二.图的广度优先遍历举例 三.伪代码实现 邻接点的访问的实现需要根据图的存储方式来进行实现

  7. 图的深度广度优先遍历(DFC与BFC)JavaScript版

    graph.js 创建一个js文件用于表示图这个类型,这个对象的键为节点,所对应的值为这个节点所连接的节点. const graph={0:[1,2],1:[2],2:[0,3],3:[3] }; m ...

  8. [C] 图的广度优先遍历

    图的广度优先遍历 我一直觉得图的遍历没有地图类型的题目难,遍历嘛,每个点都走一遍就行了. 但是给定地图求面积啊,数量啊的那种题目,花样挺多的. 图的遍历真挺难把人绕晕的,关于广度优先,理解好层层递进这 ...

  9. 获取图顶点的入度、出度;获取图的两个顶点之间的权值; 图的深度优先算法、图的广度优先遍历

    广度优先结果: 深度优先结果: 代码整理: public class Graph {private int vertexSize;//顶点数量private int[] vertexs;//顶点数组p ...

  10. 邻接表存储图的广度优先遍历

    试实现邻接表存储图的广度优先遍历. 函数接口定义: void BFS ( LGraph Graph, Vertex S, void (*Visit)(Vertex) ); 其中LGraph是邻接表存储 ...

最新文章

  1. git stash和git stash pop
  2. 汇编语言随笔(9)-实验11(用条件转移指令来编写子程序)
  3. java弱引用怎么手动释放,Java 如何有效地避免OOM:善于利用软引用和弱引用
  4. 30个使用jQuery打造的世界级一流网站
  5. Redis【入门】就这一篇!
  6. 【分享预告】细数GAN和图像分类的前世今生
  7. 【Java】矩阵乘法的朴素算法
  8. 机器学习实战11-训练深层神经网络
  9. 云原生时代,政企混合云场景IT监控和诊断的难点和应对之道
  10. LINUX 安装 PHP5.6.13
  11. [Android Memory] Android系统中查看某个应用当前流量的方法
  12. 揭秘Keras推荐系统如何建立模型、获取用户爱好
  13. 系统分析师视频教程-张友生
  14. 通赢A5管理系统服务器连不进,赢通软件A5A6系列管理系统参数设置说明
  15. 怎么选择企业即时通讯软件
  16. 中药配方颗粒调剂设备解决方案!基于一体化步进电机,全闭环,集成原点回归算法,丰富的报警功能
  17. 使用Fiddler对手机App抓包
  18. 扩展easyUI样式,全新的easyUI体验样式
  19. Linux操作系统学习 | Linux常用命令
  20. 华为cmr一al09升级鸿蒙,华为平板 M5 10.8英寸 全网通(CMR-AL09)一键刷机教程,看教程秒懂刷机...

热门文章

  1. python arduino 蓝牙_树莓和Arduino之间的蓝牙通讯
  2. throw new exception后程序不停止_Java之Exception剖析
  3. commons-beanutils实现java深度克隆
  4. 论文笔记_S2D.40_2017_CVPR_半监督深度学习的单目深度图预测
  5. 自动驾驶_产品象限图_清洁机器人场景
  6. status函数(自学数据结构第一天)
  7. 无监督/自监督/半监督的景物分割方法
  8. LeetCode之长度最小的子数组
  9. 字符串格式连接sqlserver数据库的字段概念解释
  10. Linux的基本指令(2)-Linux从入门到精通第三天(非原创)