【数据结构与算法】无向图的结构与遍历 BFS&DFS
1 表示无向图的数据类型
1.1 邻接矩阵
可以使用一个V*V的二维布尔矩阵,当定点v和定点w相连的时候,定义第v行第w列的值为true,否则为false。邻接矩阵不适合定点较多的情况,含有百万的顶点数的图是很常见的,V^2的空间很难得满足。
1.2 邻接表
邻接表使用一个记录当前顶点相邻顶点的链表即边表,和一个快速访问给定顶点的顶点列表即顶点表。数据类型如下:
public class Graph {
private final int V;
private int E;
private Bag<Integer>[] adj;
Graph(int V) {
this.V = V;
adj = (Bag<Integer>[]) new Bag[V];
for (int i = 0; i < V; i++)
adj[i] = new Bag<Integer>();
}
public void addEdge(int u, int v) {
adj[u].add(v);
}
public int V() {
return this.V;
}
public int E() {
return this.E;
}
public Iterable<Integer> adj(int v) {
return adj[v];
}
public String toString() {
String s = V + " vertices, " + E + " edges.\n";
for (int i = 0; i < V; i++) {
s += i + " : ";
for(int w : this.adj(i))
s += w + " ";
s += "\n";
}
return s;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int V = sc.nextInt();
int E = sc.nextInt();
Graph g = new Graph(V);
for (int i = 0; i < E; i++) {
int u = sc.nextInt();
int v = sc.nextInt();
g.addEdge(u, v);
g.addEdge(v, u);
}
System.out.println(g);
}
}
测试输入:
13
13
0 5
4 3
0 1
9 12
6 4
5 4
0 2
11 12
9 10
0 6
7 8
9 11
5 3
输出结果
13 vertices, 0 edges.
0 : 6 2 1 5
1 : 0
2 : 0
3 : 5 4
4 : 5 6 3
5 : 3 4 0
6 : 0 4
7 : 8
8 : 7
9 : 11 10 12
10 : 9
11 : 9 12
12 : 11 9
2 深度优先搜索
DepthFirstSearch.class
2.1 DFS的递归写法
public class DepthFirstSearch {
boolean[] marked;
private int count;
DepthFirstSearch(Graph g, int s) {
marked = new boolean[g.V()];
dfs(g, s);
}
void visit(int v) {
System.out.print(v + " ");
}
void dfs(Graph g, int v) {
marked[v] = true;
visit(v);
for(int w : g.adj(v)) {
if(!marked[w]) {
dfs(g, w);
}
}
}
}
测试结果
0 6 4 5 3 2 1
2.2 ★DFS的非递归写法
非递归写法主要借助了栈,思想与二叉树的先序遍历类似:每次将栈顶出栈再将栈顶的右节点和左节点依次入栈,只不过这里需要每次入栈一个相邻未访问节点,等到全被访问才将栈顶出栈。
①首先将第一个顶点入栈,并标记为已访问。
②遍历栈顶顶点第一个未被访问过的相邻节点将其入栈,如果栈顶顶点没有未被访问过的相邻顶点则将栈顶节点出栈。
③重复执行②直至栈空。
void dfs2(Graph g, int v) {
Stack<Integer> s = new Stack<>();
s.push(v);
visit(v);
marked[v] = true;
while(!s.empty()) {
int x = s.peek();
boolean flag = false;
// 每次访问第一个未被访问的相邻节点
for(int w : g.adj(x)) {
if(!marked[w]) {
visit(w);
s.push(w);
marked[w] = true;
flag = true;
break;
}
}
// 如果不存在相邻顶点则将栈顶顶点出栈
if(!flag)
s.pop();
}
}
2.3 寻找路径
2.4 DFS寻找所有路径
3 广度优先搜索
广度优先遍历一般用于求单源最短路径。
public class BreadthFirstPaths {
private boolean[] marked;
private int[] edgeTo;
private int s;
BreadthFirstPaths(Graph g, int s) {
marked = new boolean[g.V()];
edgeTo = new int[g.V()];
this.s = s;
bfs(g, s);
}
public void bfs(Graph g, int v) {
Queue<Integer> q = new LinkedBlockingQueue<>();
q.add(v);
marked[v] = true;
while (!q.isEmpty()) {
int x = q.poll();
for (int w : g.adj(x)) {
if (!marked[w]) {
edgeTo[w] = x;
q.add(w);
marked[w] = true;
}
}
}
}
public Stack<Integer> pathTo(int v) {
Stack<Integer> s = new Stack<>();
while (v != this.s) {
s.push(v);
v = edgeTo[v];
}
s.push(v);
return s;
}
}
【数据结构与算法】无向图的结构与遍历 BFS&DFS的更多相关文章
- 【数据结构与算法】二叉树的 Morris 遍历(前序、中序、后序)
前置说明 不了解二叉树非递归遍历的可以看我之前的文章[数据结构与算法]二叉树模板及例题 Morris 遍历 概述 Morris 遍历是一种遍历二叉树的方式,并且时间复杂度O(N),额外空间复杂度O(1 ...
- 数据结构与算法实验题 9.1 K 歌 DFS+剪枝
数据结构与算法实验题 K 歌 ★实验任务 3* n 个人(标号1~ 3 * n )分成 n 组 K 歌.有 m 个 3 人组合,每个组合都对应一个分数,你能算出最大能够得到的总分数么? ★数据输入 输 ...
- 重新整理数据结构与算法(c#)—— 图的深度遍历和广度遍历[十一]
参考网址:https://www.cnblogs.com/aoximin/p/13162635.html 前言 简介图: 在数据的逻辑结构D=(KR)中,如果K中结点对于关系R的前趋和后继的个数不加限 ...
- 算法导论—无向图的遍历(BFS+DFS,MATLAB)
华电北风吹 天津大学认知计算与应用重点实验室 最后改动日期:2015/8/22 无向图的存储方式有邻接矩阵,邻接链表,稀疏矩阵等. 无向图主要包括双方面内容,图的遍历和寻找联通分量. 一.无向图的遍历 ...
- 数据结构与算法--树(tree)结构
树 二叉树 遍历原则:前序遍历是根左右, 中序遍历是左根右,后序遍历是左右根. 二叉搜索树 特点:对于树中的每个节点X,它的左子树中所有节点的值都小于X,右子树中所有节点的值都大于X. 遍历:采取二叉 ...
- 算法学习 - 图的广度优先遍历(BFS) (C++)
广度优先遍历 广度优先遍历是非经常见和普遍的一种图的遍历方法了,除了BFS还有DFS也就是深度优先遍历方法.我在我下一篇博客里面会写. 遍历过程 相信每一个看这篇博客的人,都能看懂邻接链表存储图. 不 ...
- 数据结构学习笔记05图 (邻接矩阵 邻接表-->BFS DFS、最短路径)
数据结构之图 图(Graph) 包含 一组顶点:通常用V (Vertex) 表示顶点集合 一组边:通常用E (Edge) 表示边的集合 边是顶点对:(v, w) ∈E ,其中v, w ∈ V 有向边& ...
- 图的创建和遍历(BFS/DFS)
图的表示方法主要有邻接矩阵和邻接表.其中邻接表最为常用,因此这里便以邻接表为例介绍一下图的创建及遍历方法. 创建图用到的结构有两种:顶点及弧 struct ArcNode { int vertexIn ...
- 模板 图的遍历 bfs+dfs 图的最短路径 Floyed+Dijkstra
广搜 bfs //bfs #include<iostream> #include<cstdio> using namespace std; ],top=,end=; ][]; ...
- Java数据结构和算法(一)线性结构
Java数据结构和算法(一)线性结构 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 线性表 是一种逻辑结构,相同数据类型的 ...
随机推荐
- CentOS7 64位 部署AVA项目:jar包方式
步骤:1.挂载磁盘2.安装jdk1.83.安装mysql5.74.导入数据库5.防火墙端口放行5.运行jar文件 1.挂载磁盘https://www.cnblogs.com/xiang96/p/102 ...
- OpenCV图像拼接函数
图像拼接函数 第一种方法:通过遍历图像,将待拼接的图像每个像素赋值给输出图像 //图像拼接函数 //imageVector 输入图像数组 //outputImage 输出图像 //colCount_ ...
- redis启动报错(TCP backlog setting of 511/overcommit_memory is set to 0/THP)
WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is s ...
- 【帆吖】Java学习零基础21
数组 1 package array; 2 3 public class Demo1 { 4 public static void main(String[] args) { 5 int[ ] num ...
- 转发:基于Lerna打造多包管理最佳实践之道
最近在看vue-cli的源码部分,注意到这一个仓库下维护了多个package,很好奇他是如何在一个repo中管理这些package的. 我们组现在也在使用组件库的方式维护项目间共用的业务代码.有两个组 ...
- MFS分布式存储特性及组件说明
1.MFS MooseFS是一个具有冗余容错功能的分布式网络文件系统,它将数据分别存放在多个物理服务器或单独磁盘或分区上,确保一份数据有多个备份副本,然而对于访问MFS的客户端或者用户来说,整个分布式 ...
- ffmpeg gcc is unable to create an executable file C compiler test failed
ffmpeg 编译出现 #sudo ./configure --enable-shared --prefix=/usr/local/ffmpeg gcc is unable to create an ...
- 什么是5G垂直行业?
什么是垂直行业呢? 感觉"垂直行业"这个词在太多地方遇到,但是这个词的涵盖范围到底是什么呢? 垂直这一概念源于两条直线(或平面)的直角交叉,两条直线是相互作为参照物的.比如,我们可 ...
- 联邦学习开源框架FATE架构
作者:京东科技 葛星宇 1.前言 本文除特殊说明外,所指的都是fate 1.9版本. fate资料存在着多处版本功能与发布的文档不匹配的情况,各个模块都有独立的文档,功能又有关联,坑比较多,首先要理清 ...
- RHEL8使用NMCLI管理网络
使用 NMCLI 配置静态以太网连接 要在命令行上配置以太网连接,请使用 nmcli 工具. 例如,以下流程使用以下设置为 enp7s0 设备创建 NetworkManager 连接配置文件: 静态 ...