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的更多相关文章

  1. 【数据结构与算法】二叉树的 Morris 遍历(前序、中序、后序)

    前置说明 不了解二叉树非递归遍历的可以看我之前的文章[数据结构与算法]二叉树模板及例题 Morris 遍历 概述 Morris 遍历是一种遍历二叉树的方式,并且时间复杂度O(N),额外空间复杂度O(1 ...

  2. 数据结构与算法实验题 9.1 K 歌 DFS+剪枝

    数据结构与算法实验题 K 歌 ★实验任务 3* n 个人(标号1~ 3 * n )分成 n 组 K 歌.有 m 个 3 人组合,每个组合都对应一个分数,你能算出最大能够得到的总分数么? ★数据输入 输 ...

  3. 重新整理数据结构与算法(c#)—— 图的深度遍历和广度遍历[十一]

    参考网址:https://www.cnblogs.com/aoximin/p/13162635.html 前言 简介图: 在数据的逻辑结构D=(KR)中,如果K中结点对于关系R的前趋和后继的个数不加限 ...

  4. 算法导论—无向图的遍历(BFS+DFS,MATLAB)

    华电北风吹 天津大学认知计算与应用重点实验室 最后改动日期:2015/8/22 无向图的存储方式有邻接矩阵,邻接链表,稀疏矩阵等. 无向图主要包括双方面内容,图的遍历和寻找联通分量. 一.无向图的遍历 ...

  5. 数据结构与算法--树(tree)结构

    树 二叉树 遍历原则:前序遍历是根左右, 中序遍历是左根右,后序遍历是左右根. 二叉搜索树 特点:对于树中的每个节点X,它的左子树中所有节点的值都小于X,右子树中所有节点的值都大于X. 遍历:采取二叉 ...

  6. 算法学习 - 图的广度优先遍历(BFS) (C++)

    广度优先遍历 广度优先遍历是非经常见和普遍的一种图的遍历方法了,除了BFS还有DFS也就是深度优先遍历方法.我在我下一篇博客里面会写. 遍历过程 相信每一个看这篇博客的人,都能看懂邻接链表存储图. 不 ...

  7. 数据结构学习笔记05图 (邻接矩阵 邻接表-->BFS DFS、最短路径)

    数据结构之图 图(Graph) 包含 一组顶点:通常用V (Vertex) 表示顶点集合 一组边:通常用E (Edge) 表示边的集合 边是顶点对:(v, w) ∈E ,其中v, w ∈ V 有向边& ...

  8. 图的创建和遍历(BFS/DFS)

    图的表示方法主要有邻接矩阵和邻接表.其中邻接表最为常用,因此这里便以邻接表为例介绍一下图的创建及遍历方法. 创建图用到的结构有两种:顶点及弧 struct ArcNode { int vertexIn ...

  9. 模板 图的遍历 bfs+dfs 图的最短路径 Floyed+Dijkstra

    广搜 bfs //bfs #include<iostream> #include<cstdio> using namespace std; ],top=,end=; ][]; ...

  10. Java数据结构和算法(一)线性结构

    Java数据结构和算法(一)线性结构 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 线性表 是一种逻辑结构,相同数据类型的 ...

随机推荐

  1. Python笔记(5)——if 语句一:条件测试(Python编程:从入门到实践)

    每条if语句的核心都是一个值为True或False的表达式.Python根据条件测试的值为True还是False来决定是否执行if语句中的代码.如果条件测试的值为True,Python就执行紧跟在if ...

  2. nojejs 弹出子窗口,取值后返回

    1.主窗口: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <ti ...

  3. 源代码管理工具-Github

    一.实验目的 个人编程:每个开发人员电脑上有自己的代码.硬盘坏了,所有的数据和资料不能找回或是很难复原.安全意识强一些的公司会要求开发人员将代码隔一段时间放到一个集中的计算机上,以日期为文件夹进行备份 ...

  4. 简单的继承练习——疑问:私有属性在类的方法内调用时,有必要使用get,set方法嘛?

    要求: 创建一个Circle类,设置半径属性和返回面积的方法,在无参构造器中初始化半径值为1. 创建一个Cylinder类,继承Circle类,设置属性高和返回体积的方法,在无参构造器中初始化长度为1 ...

  5. 使用npm包安装vant组件

  6. 动力节点的MySQL的34题目的第7题的我的参考答案

    以下是:薪水的平均等级最低的部门的名称 select t4.t4deptno,t4.t4grade,d1.dname from( ##求出各部门平均等级begin select avg(t3.t3gr ...

  7. Unity图片转存及读取

    [code]csharpcode: /// <summary> /// 加载图片 /// </summary> private Sprite LoadTexture(strin ...

  8. 网络安全(中职组)-B模块:Web安全渗透测试

    Web安全渗透测试任务环境说明: 服务器场景:PYsystem003(关闭链接)服务器操作系统:未知用户名:未知 密码:未知 1.    通过浏览器访问http://靶机服务器IP/1,对该页面进行渗 ...

  9. Android笔记--在活动之间传递消息

    显式Intent和隐式Intent Intent--各个组件信息沟通的桥梁 组成部分: 显式Intent:--精确匹配 具体实现: 1.在Intent的构造函数中指定 2.调用意图对象的setClas ...

  10. Typora怎么插入行内公式?内联公式设置

    文件 偏好设置 把内联公式那个勾上就可以了.然后就能写latex了,像这样,$\alpha\$ \(\alpha\) 输入一个\$后再按esc,会自动补全为$$