【数据结构与算法】无向图的结构与遍历 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) 线性表 是一种逻辑结构,相同数据类型的 ...
随机推荐
- ESP32 环境搭建以及入门编程流程和体验-windows
本帖适合入门级人员,但同时欢迎新老读者批评指正. 某宝上买了个esp32,还有一本ESP32开发指南的书. 然后就是环境搭建.上面写的主要是linux上的,我在自己的orange pi pc开发板上搭 ...
- [Leetcode 111]二叉树的最短深度 BFS/DFS
题目 给定二叉树,求最短路径包含的节点个数 https://leetcode.com/problems/minimum-depth-of-binary-tree/ Given a binary tre ...
- 各种系统名词解释:MIS 、ERP、CRM、OA
MIS :信息系统.针对企业使用的软件,都可以叫做MIS系统. (管理信息系统--Management Information System)系统 ,是一个由人.计算机及其他外围设备等组成的能进行信息 ...
- day48-Mysql安装文件结构及SQL常用语句
1.安装文件结构 bin--mysql.exe 客户端运行程序: mysqld.exe 服务端运行程序: data--数据库.数据表等文件 注:修改配置文件后需要重启服务端 2.常用SQL语句 1) ...
- idea修改背景颜色|护眼色|项目栏背景修改
https://blog.csdn.net/heytyrell/article/details/89743068
- input_subsys 输入子系统框架分析
在linux内核中 已做好各类驱动的框架,驱动程序也属于内核的一部分,我们可以在原有的驱动上修改,来匹配我们自已的硬件,也可以自已编写符合内核驱动框架的驱动程序.出于学习的目的,便于更好的理解各类驱动 ...
- TP5中redirect实现重定向及带参数跳转
1.控制器 重定向url传参 try{ $result = Db::name('wupin')->insert($ist); if($result){ $this->redirect(ur ...
- zip文件自动打包
简单的文件打包 首先是问题 我们有一个文件的文件过大,我需要删除或者压缩,当然我们就是选择压缩 如果是单个我们可以直接使用压缩功能 但是多个呢? 首先获取当前目录下的文件,使用 a=`ls` | te ...
- 04-Spring中的AOP编程之基于xml开发
AOP编程 AOP为Aspect Oriented Programming的缩写,意为:面向切面编程.利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的 ...
- 登录:ORA-12504:TNS:监听程序在CONNECT_DATA中未获得SERVICE_NAME
问题描述:在用pl/sql登录soctt用户时,显示: 解决办法:在tnsnames.ora文件中添加(文件位置的查找方法见文章末尾) ORCL = (DESCRIPTION = (ADDRESS = ...