图的遍历

一、DFS(Depth First Search)

概念:
从初始访问点出发,访问其第一个邻接节点;然后把这个邻接节点作为初始节点,继续访问它的第一个邻接节点。

即每次都在访问完当前节点过后,访问它的第一个邻接节点。

算法:

  1. 访问初始节点v(下标),并标记v已被访问;
  2. 查找节点v的第一个邻接节点w(下标);
  3. 如果w存在,则继续4步骤;如果w不存在,则返回1步骤;
  4. 如果w未被访问过,对w进行dfs递归操作(重复123操作);
  5. 查找节点v的w邻接节点的下一个邻接节点,返回3步骤

源代码如下:

import java.util.ArrayList;
import java.util.Arrays;public class graph {private ArrayList<String> vertexList;// 定义顶点列表private int[][] edges;// 存储图对应的邻接矩阵private int numOfEdges;// 存储边private boolean isVisited[];// 标记顶点是否已被访问public static void main(String[] args) {// TODO Auto-generated method stub// 测试图int n = 5;// 定义顶点个数String vertexs[] = { "A", "B", "C", "D", "E" };// 创建图对象graph graph = new graph(n);// 循环添加顶点for (String vertex : vertexs) {// 每次循环从vertexValue取出来一个值(定义为value)graph.insertVertex(vertex);// 把顶点加进去}// 添加边// A-B A-C B-C B-D B-E// 权值默认为是1graph.insertEdges(0, 1, 1);// A-Bgraph.insertEdges(0, 2, 1);// A-Cgraph.insertEdges(1, 2, 1);// B-Cgraph.insertEdges(1, 3, 1);// B-Dgraph.insertEdges(1, 4, 1);// B-E// 显示邻接矩阵graph.show();// DFSgraph.dfs();}// ————————————--------------------------------------------------------// 首先定义图的属性// 1.构造器public graph(int n) {// 首先要传入顶点的数目// 初始化矩阵和vertexListedges = new int[n][n];vertexList = new ArrayList<String>();// 初始化顶点列表numOfEdges = 0;// 可省略,因为默认为0isVisited = new boolean[5];}// 2.插入顶点public void insertVertex(String vertex) {vertexList.add(vertex);}// 3.设置边/*** * @param v1     第一个顶点的下标* @param v2     第二个顶点的下标* @param weight 权值*/public void insertEdges(int v1, int v2, int weight) {// 这里是定义无向图,所以两个方向都要定义edges[v1][v2] = weight;edges[v2][v1] = weight;numOfEdges++;}// 4.返回顶点个数public int getnumOfVertexs() {return vertexList.size();}// 5.返回边个数public int getnumOfEdges() {return numOfEdges;}// 6.返回顶点i(顶点的下标)的对应的数据/*** * @param i返回数据下标* @return 返回数据 例:0->A 1->B 2->C 3->D 4->E*/public String getValueByIndex(int i) {return vertexList.get(i);}// 7.返回v1,v2两顶点之间的权值public int getWeight(int v1, int v2) {return edges[v1][v2];}// 8.打印邻接矩阵(本质:遍历图)public void show() {for (int[] link : edges) {System.out.println(Arrays.toString(link));}}
//————————————--------------------------------------------------------  // DFS算法步骤// 1.得到第一个邻接节点下标w/*** * @param index* @return 如果存在就返回它的下标,没有就返回-1*/public int getFirstNerghborIndex(int index) {// 传入当前节点的下标indexfor (int w = 0; w < vertexList.size(); w++) {if (edges[index][w] > 0) {// 如果下一个邻接节点存在return w;// 返回它的下标}}return -1;// 没有返回就返回-1}// 2.根据前一个邻接节点的下标来获取下一个邻接节点/*** * @param v1* @param v2* @return*/public int getNextNeighbor(int v1, int v2) {for (int w = v2 + 1; w < vertexList.size(); w++) {if (edges[v1][w] > 0) {return w;}}return -1;}// 3.开始深搜遍历public void dfs(boolean[] isVisited, int i) {// 判断是否遍历过的标记,定义节点下标// 首先访问当前节点,输出System.out.print(getValueByIndex(i) + "->");// 访问过后,要标记节点已访问isVisited[i] = true;// 查找节点i的第一个邻接节点int w = getFirstNerghborIndex(i);while (w != -1) {// 存在if (!isVisited[w]) {// 如果没有被标记过dfs(isVisited, w);// 以w为初始节点重新开始,递归操作dfs}// 如果已经被访问过w = getNextNeighbor(i, w);}}// 对dfs进行重载,遍历所有节点public void dfs() {for (int i = 0; i < getnumOfVertexs(); i++) {while (!isVisited[i]) {// 如果没被访问过dfs(isVisited, i);}}}
}

二、BFS(Broad First Search)

.addLast() 获取最后一个节点


概念:
类似一个分层搜索过程,BFS需要一个队列以保持访问过节点的顺序,以便按照这个顺序来访问他们的邻接节点。

算法:

  1. 访问初始节点v,并将其标记已经访问;
  2. 把节点v加入队列;
  3. 当队列非空时,继续执行,否则算法结束;
  4. 出队列,取得队头结点u;
  5. 查找初始节点也是队头结点u第一个邻接节点w;
  6. 若节点u的第一个邻接节点w不存在,执行步骤3,否则循环执行下述三个操作:
    (1)若节点w未被访问,访问它并标记已经访问;
    (2)节点w入队列;
    (3)查找节点u的继w邻接节点后的下一个邻接节点,转到步骤6

源代码如下:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;public class graph {private ArrayList<String> vertexList;// 定义顶点列表private int[][] edges;// 存储图对应的邻接矩阵private int numOfEdges;// 存储边private boolean isVisited[];// 标记顶点是否已被访问public static void main(String[] args) {// TODO Auto-generated method stub// 测试图int n = 5;// 定义顶点个数String vertexs[] = { "A", "B", "C", "D", "E" };// 创建图对象graph graph = new graph(n);// 循环添加顶点for (String vertex : vertexs) {// 每次循环从vertexValue取出来一个值(定义为value)graph.insertVertex(vertex);// 把顶点加进去}// 添加边// A-B A-C B-C B-D B-E// 权值默认为是1graph.insertEdges(0, 1, 1);// A-Bgraph.insertEdges(0, 2, 1);// A-Cgraph.insertEdges(1, 2, 1);// B-Cgraph.insertEdges(1, 3, 1);// B-Dgraph.insertEdges(1, 4, 1);// B-E// 显示邻接矩阵graph.show();/*// DFSSystem.out.println();System.out.println("DFS:");graph.dfs();*/System.out.println();System.out.println();System.out.println("BFS:");graph.bfs();}// ————————————--------------------------------------------------------// 首先定义图的属性// 1.构造器public graph(int n) {// 首先要传入顶点的数目// 初始化矩阵和vertexListedges = new int[n][n];vertexList = new ArrayList<String>();// 初始化顶点列表numOfEdges = 0;// 可省略,因为默认为0isVisited = new boolean[vertexList.size() + 1];}// 2.插入顶点public void insertVertex(String vertex) {vertexList.add(vertex);}// 3.设置边/*** * @param v1     第一个顶点的下标* @param v2     第二个顶点的下标* @param weight 权值*/public void insertEdges(int v1, int v2, int weight) {// 这里是定义无向图,所以两个方向都要定义edges[v1][v2] = weight;edges[v2][v1] = weight;numOfEdges++;}// 4.返回顶点个数public int getnumOfVertexs() {return vertexList.size();}// 5.返回边个数public int getnumOfEdges() {return numOfEdges;}// 6.返回顶点i(顶点的下标)的对应的数据/*** * @param i返回数据下标* @return 返回数据 例:0->A 1->B 2->C 3->D 4->E*/public String getValueByIndex(int i) {return vertexList.get(i);}// 7.返回v1,v2两顶点之间的权值public int getWeight(int v1, int v2) {return edges[v1][v2];}// 8.打印邻接矩阵(本质:遍历图)public void show() {for (int[] link : edges) {System.out.println(Arrays.toString(link));}}
//————————————--------------------------------------------------------  // DFS算法步骤// 1.得到第一个邻接节点下标w/*** * @param index* @return 如果存在就返回它的下标,没有就返回-1*/public int getFirstNerghborIndex(int index) {// 传入当前节点的下标indexfor (int w = 0; w < vertexList.size(); w++) {if (edges[index][w] > 0) {// 如果下一个邻接节点存在return w;// 返回它的下标}}return -1;// 没有返回就返回-1}// 2.根据前一个邻接节点的下标来获取下一个邻接节点/*** * @param v1为前驱点* @param v2为前驱点的当前邻接节点* @return*/public int getNextNeighbor(int v1, int v2) {for (int w = v2 + 1; w < vertexList.size(); w++) {if (edges[v1][w] > 0) {return w;}}return -1;}// 3.开始深搜遍历private void dfs(boolean[] isVisited, int i) {// 判断是否遍历过的标记,定义节点下标// 首先访问当前节点,输出System.out.print(getValueByIndex(i) + "->");// 访问过后,要标记节点已访问isVisited[i] = true;// 查找节点i的第一个邻接节点int w = getFirstNerghborIndex(i);while (w != -1) {// 存在if (!isVisited[w]) {// 如果没有被标记过dfs(isVisited, w);// 以w为初始节点重新开始,递归操作dfs}// 如果已经被访问过// 以u为前驱点,找w的下一个邻接节点// w为辅助变量,每次进行此操作的时候更新值w = getNextNeighbor(i, w);}}// 对dfs进行重载,遍历所有节点public void dfs() {for (int i = 0; i < getnumOfVertexs(); i++) {while (!isVisited[i]) {// 如果没被访问过dfs(isVisited, i);}}}// ————————————--------------------------------------------------------// BFS算法步骤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();// 得到第一个邻接节点的下标ww = getFirstNerghborIndex(u);while (w != -1) {// 找到邻接节点// 判断是否访问过if (!isVisited[w]) {// 如果没有访问过System.out.print(getValueByIndex(w) + "->");// 访问isVisited[w] = true;// 标记为已访问// 邻接节点入队列queue.addLast(w);}// 以u为前驱点,访问w的下一个邻接节点w = getNextNeighbor(u, w);}}}// 对bfs进行重载,遍历所有节点public void bfs() {for (int i = 0; i < getnumOfVertexs(); i++) {while (!isVisited[i]) {// 如果没被访问过bfs(isVisited, i);}}}
}

如果要同时显示DFS和BFS遍历结果,需将构造器中的初始化部分摘出来,分别放到DFS和BFS的重载方法里,每次调用时重新分配,就不会出现执行完一种遍历无法执行第二种遍历的情况。

代码如下:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;public class graph {private ArrayList<String> vertexList;// 定义顶点列表private int[][] edges;// 存储图对应的邻接矩阵private int numOfEdges;// 存储边private boolean isVisited[];// 标记顶点是否已被访问public static void main(String[] args) {// TODO Auto-generated method stub// 测试图int n = 5;// 定义顶点个数String vertexs[] = { "A", "B", "C", "D", "E" };// 创建图对象graph graph = new graph(n);// 循环添加顶点for (String vertex : vertexs) {// 每次循环从vertexValue取出来一个值(定义为value)graph.insertVertex(vertex);// 把顶点加进去}// 添加边// A-B A-C B-C B-D B-E// 权值默认为是1graph.insertEdges(0, 1, 1);// A-Bgraph.insertEdges(0, 2, 1);// A-Cgraph.insertEdges(1, 2, 1);// B-Cgraph.insertEdges(1, 3, 1);// B-Dgraph.insertEdges(1, 4, 1);// B-E// 显示邻接矩阵graph.show();// DFSSystem.out.println();System.out.println("DFS:");graph.dfs();System.out.println();System.out.println();System.out.println("BFS:");graph.bfs();}// ————————————--------------------------------------------------------// 首先定义图的属性// 1.构造器public graph(int n) {// 首先要传入顶点的数目// 初始化矩阵和vertexListedges = new int[n][n];vertexList = new ArrayList<String>();// 初始化顶点列表numOfEdges = 0;// 可省略,因为默认为0}// 2.插入顶点public void insertVertex(String vertex) {vertexList.add(vertex);}// 3.设置边/*** * @param v1     第一个顶点的下标* @param v2     第二个顶点的下标* @param weight 权值*/public void insertEdges(int v1, int v2, int weight) {// 这里是定义无向图,所以两个方向都要定义edges[v1][v2] = weight;edges[v2][v1] = weight;numOfEdges++;}// 4.返回顶点个数public int getnumOfVertexs() {return vertexList.size();}// 5.返回边个数public int getnumOfEdges() {return numOfEdges;}// 6.返回顶点i(顶点的下标)的对应的数据/*** * @param i返回数据下标* @return 返回数据 例:0->A 1->B 2->C 3->D 4->E*/public String getValueByIndex(int i) {return vertexList.get(i);}// 7.返回v1,v2两顶点之间的权值public int getWeight(int v1, int v2) {return edges[v1][v2];}// 8.打印邻接矩阵(本质:遍历图)public void show() {for (int[] link : edges) {System.out.println(Arrays.toString(link));}}
//————————————--------------------------------------------------------  // DFS算法步骤// 1.得到第一个邻接节点下标w/*** * @param index* @return 如果存在就返回它的下标,没有就返回-1*/public int getFirstNerghborIndex(int index) {// 传入当前节点的下标indexfor (int w = 0; w < vertexList.size(); w++) {if (edges[index][w] > 0) {// 如果下一个邻接节点存在return w;// 返回它的下标}}return -1;// 没有返回就返回-1}// 2.根据前一个邻接节点的下标来获取下一个邻接节点/*** * @param v1* @param v2* @return*/public int getNextNeighbor(int v1, int v2) {for (int w = v2 + 1; w < vertexList.size(); w++) {if (edges[v1][w] > 0) {return w;}}return -1;}// 3.开始深搜遍历private void dfs(boolean[] isVisited, int i) {// 判断是否遍历过的标记,定义节点下标// 首先访问当前节点,输出System.out.print(getValueByIndex(i) + "->");// 访问过后,要标记节点已访问isVisited[i] = true;// 查找节点i的第一个邻接节点int w = getFirstNerghborIndex(i);while (w != -1) {// 存在if (!isVisited[w]) {// 如果没有被标记过dfs(isVisited, w);// 以w为初始节点重新开始,递归操作dfs}// 如果已经被访问过w = getNextNeighbor(i, w);}}// 对dfs进行重载,遍历所有节点public void dfs() {isVisited = new boolean[5];for (int i = 0; i < getnumOfVertexs(); i++) {while (!isVisited[i]) {// 如果没被访问过dfs(isVisited, i);}}}// ————————————--------------------------------------------------------// BFS算法步骤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();// 得到第一个邻接节点的下标ww = getFirstNerghborIndex(u);while (w != -1) {// 找到邻接节点// 判断是否访问过if (!isVisited[w]) {// 如果没有访问过System.out.print(getValueByIndex(w) + "->");// 访问isVisited[w] = true;// 标记为已访问// 邻接节点入队列queue.addLast(w);}// 以u为前驱点,访问w的下一个邻接节点w = getNextNeighbor(u, w);}}}// 对bfs进行重载,遍历所有节点public void bfs() {isVisited = new boolean[5];for (int i = 0; i < getnumOfVertexs(); i++) {while (!isVisited[i]) {// 如果没被访问过bfs(isVisited, i);}}}
}

图的遍历(Java)构造器相关推荐

  1. 【数据结构】图-图的遍历_深度优先遍历(动态图解、c++、java)

    文章目录 一.概述 二.深度优先搜索 算法步骤 递归 非递归 图解 BFS树 代码 邻接矩阵实现 邻接表实现 链式前向星实现 三.完整代码 邻接矩阵版 邻接表版 链式前向星版 四.总结 算法复杂度分析 ...

  2. 图深度优先、广度优先遍历(java)

    一.图的遍历 图的遍历,即是对结点的访问.一个图有那么多个结点,如何遍历这些结点,需要特定策略,一般有两种访问策略:(1)深度优先遍历(2)广度优先遍历深度优先遍历基本思想. 二.深度优先遍历 图的深 ...

  3. Java数据结构与算法:无向图,有向图,带权图,图的遍历,最小生成树

    文章目录 无向图 有向图 带权图 图的遍历 广度优先遍历 深度优先遍历 最小生成树 无向图 前面了解到树是有单一根结点的非线性结构,图(graph)也是一种非线性结构,其中的结点可以与许多其他的结点相 ...

  4. c++ 遍历list_数据结构之图的遍历,一篇文章get全部考点

    图的概念 举个例子,假设你的微信朋友圈中有若干好友:张三.李四.王五.赵六.七大姑.八大姨. 而你七大姑的微信号里,又有若干好友:你.八大姨.Jack.Rose. 微信中,许许多多的用户组成了一个多对 ...

  5. 周报(水管工问题,和图的遍历)

    枯木逢春不在茂,年少且惜镜边人 这周继续完成上周么有完成的目标,然后学学java,学学图的遍历,学学浴谷上的题,然后上天. 1.水管工问题 #include<stdio.h> int bo ...

  6. DFS(深度搜索)无向图遍历(JAVA手把手深入解析)

    DFS(深度搜索)无向图遍历(JAVA手把手深入解析) 目录 DFS(深度搜索)无向图遍历(JAVA手把手深入解析) 前言 DFS深度优先 无向图 DFS全局变量定义 1.节点 2.节点数 3.根据图 ...

  7. 二叉树的层级遍历/锯齿遍历--Java版

    二叉树的层级遍历/锯齿遍历--Java版 前言 题目 解题思路/知识点 showCode 创建节点对象 创建树对象 创建测试类 层序遍历 锯齿遍历 题目 解体思路 源码(测试类) 结语 前言 今天在力 ...

  8. 图的遍历 深度与广度优先遍历

    图的遍历 本文作者 Mr.赵 Email: lovelyalan@foxmail.com 原创文章,转载标明作者,部分图片素材来自网络 从图中某一顶点出发遍历图中其余顶点,且使每一个顶点仅被访问一次, ...

  9. 解题报告:luogu P3916 图的遍历( 缩点 + DFS ? × 思维 + 反向建边 + DFS √ )

    题目链接:图的遍历 本题是一个有向图,要求每个点能到达的编号最大的点.由于是有向图,如果直接DFS如果有环就可能忽略一些点,所以我们可以直接缩点 缩点之后 在同一个强联通分量中的点可以相互到达,那么我 ...

最新文章

  1. dbeaver导出表结构和数据_python中的哈希表数据结构
  2. 让那些为Webkit优化的网站也能适配IE10(转载)
  3. java冒泡遍历对象_Java经典排序算法(冒泡、选择、插入)
  4. 熵值法确定权重(matlab附代码)
  5. bootstrap table传回的数据后端怎么获取_基于 Spring Cloud 开发的分布式系统,遇到爬虫、接口盗刷怎么办
  6. Scala Object
  7. PIE SDK矢量点生成等值线、面
  8. Learning Data Structure_2_线性表、栈和队列
  9. 烟花散尽漫说无(參考资料)
  10. 专业营销手段汇编及研究
  11. 单片机c语言串口中断函数,12手把手教你学单片机的C语言程序设计_中断服务函数.pdf...
  12. 禁忌搜索算法求解TSP问题python实现
  13. python机器人编程教材_python人工智能机器人工具书籍: Learn Robotics Programming(python and Raspberry Pi 3) - 2018...
  14. kakfa 3.0 创建topic流程(源码)
  15. c语言将浮点变成字符串,c语言将浮点型数据转换成字符串
  16. html+JavaScript 实现贪吃蛇程序
  17. Java如何实现定时任务——从某一天起每天定点执行
  18. JRebel and XRebel idea热部署插件的使用
  19. 微信小程序详细图文讲解
  20. NAND flash和NOR flash 基础知识

热门文章

  1. getvalue参数计数不匹配_OpenCV开发笔记(六十八):红胖子8分钟带你使用特征点Flann最邻近差值匹配识别...
  2. html如何将多个复选框组织成一组_[Selenium]18.如何处理一组元素
  3. 详解C++17下的string_view
  4. Android开发之虹软人脸识别活体检测SDK包Bitmap转NV21方法
  5. Android开发之ApiCloud模块开发的注意事项
  6. matlab第三方控件,第三方控件介绍
  7. day13 生成器 三元运算 列表解析
  8. Android Status(状态栏) 着色
  9. 又一波你可能不知道的 Linux 命令行网络监控工具
  10. jquery表单数据反序列化为字典