图-图的表示、搜索算法及其Java实现
1.图的表示方法
图:G=(V,E),V代表节点,E代表边。
图有两种表示方法:邻接链表和邻接矩阵
邻接链表因为在表示稀疏图(边的条数|E|远远小于|V|²的图)时非常紧凑而成为通常的选择。
如果需要快速判断任意两个节点之间是否有边相连,可能也需要使用邻接矩阵表示法。
邻接链表表示法的鲁棒性很高,可以对其进行简单修改来支持许多其他的图变种。
邻接链表的一个潜在缺陷是无法快速判断一条边是否是图中地一条边。邻接矩阵则克服了这个缺陷,但付出的代价是更大的存储空间消耗。
——摘自《算法导论》
(1)无向图的两种表示


(2)有向图的两种表示

2.图的搜索算法
图的搜索算法即:广度优先搜索和深度优先搜索
相信这两种搜索算法的基本概念根据名字就可窥得一二,不多说,直接上例子。

如上有向图,创建三个类:
- 点Vertex:包括点的名称(String)和访问标志(boolean)。
- 边Edge:包括前驱点(Vertex)和后继点(Vertex)。
- 图Graph:包括点集合(ArrayList<Vertex>)和边集合(ArrayList<Edge>)。
以下是构建好的图信息以及点遍历结果。

以下是Java源码。BFS辅以队列以非递归方法完成,DFS以递归方法完成。注释得很详细,我就不多解释了@(^<>^)@。
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue; class Graph{
ArrayList<Vertex> vertexs=new ArrayList<Vertex>();
ArrayList<Edge> edges=new ArrayList<Edge>(); public void addVertex(Vertex vertex) {
vertexs.add(vertex);
} public void addEdge(Edge edge) {
edges.add(edge);
}
} //顶点类
class Vertex{
String name;
boolean visited=false; //标记该点是否被查看-广度优先专用
boolean visited2=false; //标记该点是否被查看-深度优先专用 public Vertex(String name) {
this.name=name;
} @Override
public String toString() {
return "[" + name + "]";
}
}
//边类 有向图
class Edge{
Vertex start;
Vertex end; public Edge(Vertex start,Vertex end) {
this.start=start;
this.end=end;
} @Override
public String toString() {
return "(" + start + "," + end + ")";
}
} public class SearchGraph {
//广度优先 非递归
static void BFS(Graph graph) {
ArrayList<Vertex> vertexs=graph.vertexs;
ArrayList<Edge> edges=graph.edges;
Queue<Vertex> queue = new LinkedList<Vertex>(); //创建队列 queue.add(vertexs.get(0)); //顶节点放入队列
vertexs.get(0).visited=true; //顶节点设为已阅
System.out.print(vertexs.get(0)); while(!queue.isEmpty()) {
Vertex vertex=queue.remove();
for(Edge edge:edges) {
if(edge.start.equals(vertex)&&edge.end.visited==false) {
queue.add(edge.end);
edge.end.visited=true;
System.out.print(edge.end);
}
}
} } //深度优先 递归
static void DFS(Graph graph,Vertex vertex) { //参数:图、点信息
System.out.print(vertex);
vertex.visited2=true; for(Edge edge:graph.edges) {
if(edge.start.equals(vertex)&&edge.end.visited2==false) {
DFS(graph,edge.end);
}
}
} public static void main(String[] args) {
// TODO Auto-generated method stub //构造有向图
Graph graph=new Graph();
Vertex v0=new Vertex("v0");
Vertex v1=new Vertex("v1");
Vertex v2=new Vertex("v2");
Vertex v3=new Vertex("v3");
Vertex v4=new Vertex("v4");
Vertex v5=new Vertex("v5");
Vertex v6=new Vertex("v6");
graph.addVertex(v0);
graph.addVertex(v1);
graph.addVertex(v2);
graph.addVertex(v3);
graph.addVertex(v4);
graph.addVertex(v5);
graph.addVertex(v6);
Edge e0=new Edge(v0,v1);
Edge e1=new Edge(v0,v2);
Edge e2=new Edge(v0,v3);
Edge e3=new Edge(v1,v4);
Edge e4=new Edge(v1,v5);
Edge e5=new Edge(v2,v4);
Edge e6=new Edge(v3,v5);
Edge e7=new Edge(v4,v6);
Edge e8=new Edge(v5,v6);
graph.addEdge(e0);
graph.addEdge(e1);
graph.addEdge(e2);
graph.addEdge(e3);
graph.addEdge(e4);
graph.addEdge(e5);
graph.addEdge(e6);
graph.addEdge(e7);
graph.addEdge(e8);
//构造有向图 //测试图创建结果
ArrayList<Vertex> vertexs=graph.vertexs;
ArrayList<Edge> edges=graph.edges;
Iterator iVertex=vertexs.iterator();
Iterator iEdge=edges.iterator();
System.out.println("点集合:");
while(iVertex.hasNext()) {
System.out.print(iVertex.next());
}
System.out.println();
System.out.println("边集合:");
while(iEdge.hasNext()) {
System.out.print(iEdge.next());
}
//测试图创建结果 //遍历
System.out.println("");
System.out.println("广度优先遍历:");
BFS(graph);
System.out.println("");
System.out.println("深度优先遍历:");
DFS(graph,v0);
//遍历
} }
图-图的表示、搜索算法及其Java实现的更多相关文章
- 八大排序算法详解(动图演示 思路分析 实例代码java 复杂度分析 适用场景)
一.分类 1.内部排序和外部排序 内部排序:待排序记录存放在计算机随机存储器中(说简单点,就是内存)进行的排序过程. 外部排序:待排序记录的数量很大,以致于内存不能一次容纳全部记录,所以在排序过程中需 ...
- 八大排序算法——堆排序(动图演示 思路分析 实例代码java 复杂度分析)
一.动图演示 二.思路分析 先来了解下堆的相关概念:堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆:或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆.如 ...
- 八大排序算法——希尔(shell)排序(动图演示 思路分析 实例代码java 复杂度分析)
一.动图演示 二.思路分析 希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序:随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止. 简单插 ...
- 八大排序算法——基数排序(动图演示 思路分析 实例代码java 复杂度分析)
一.动图演 二.思路分析 基数排序第i趟将待排数组里的每个数的i位数放到tempj(j=1-10)队列中,然后再从这十个队列中取出数据,重新放到原数组里,直到i大于待排数的最大位数. 1.数组里的数最 ...
- 八大排序算法——归并排序(动图演示 思路分析 实例代码java 复杂度分析)
一.动图演示 二.思路分析 归并排序就是递归得将原始数组递归对半分隔,直到不能再分(只剩下一个元素)后,开始从最小的数组向上归并排序 1. 向上归并排序的时候,需要一个暂存数组用来排序, 2. 将 ...
- 八大排序算法——快速排序(动图演示 思路分析 实例代码Java 复杂度分析)
一.动图演示 二.思路分析 快速排序的思想就是,选一个数作为基数(这里我选的是第一个数),大于这个基数的放到右边,小于这个基数的放到左边,等于这个基数的数可以放到左边或右边,看自己习惯,这里我是放到了 ...
- 八大排序算法——插入排序(动图演示 思路分析 实例代码java 复杂度分析)
一.动图演示 二.思路分析 例如从小到大排序: 1. 从第二位开始遍历, 2. 当前数(第一趟是第二位数)与前面的数依次比较,如果前面的数大于当前数,则将这个数放在当前数的位置上,当前数的下标-1 ...
- 八大排序算法——冒泡排序(动图演示 思路分析 实例代码java 复杂度分析)
一.动图演示 二.思路分析 1. 相邻两个数两两相比,n[i]跟n[j+1]比,如果n[i]>n[j+1],则将连个数进行交换, 2. j++, 重复以上步骤,第一趟结束后,最大数就会被确定 ...
- 八大排序算法——选择排序(动图演示 思路分析 实例代码Java 复杂度分析)
一.动图演示 二.思路分析 1. 第一个跟后面的所有数相比,如果小于(或小于)第一个数的时候,暂存较小数的下标,第一趟结束后,将第一个数,与暂存的那个最小数进行交换,第一个数就是最小(或最大的数) ...
随机推荐
- 【转】Java学习---深入理解线程池
[原文]https://www.toutiao.com/i6566022142666736131/ 我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很 ...
- gl 绘制多边形的函数解析 分类: OpenGL(转)
http://blog.csdn.net/zhongjling/article/details/7528091 1,所谓正反面 glFrontFace(GL_CCW); // 设置CCW方向为“正面 ...
- django中url 和 path 的区别
django中 url 和 path 都是配置路径,有什么不同? django.urls path django.conf.urls url path 与 url 是两个不同的模块,效果都是响应返回 ...
- Hadoop HBase概念学习系列之HRegion服务器(三)
所有的数据库数据一般是保存在Hadoop分布式系统上面的,用户通过一系列HRegion服务器获取这些数据.一台机器上一般只运行一个HRegion服务器,而且每一分区段的HRegion也只会被一个HRe ...
- SDN 期末作业验收
前言 SDN 期末作业验收我们是采用的参考场景一,我们在此场景的基础上来做负载均衡,下面是我们搭建的拓扑图 演示视频 https://pan.baidu.com/s/1htkKLPM 负载均衡程序 相 ...
- python第四十二课——__str__(self)函数
4.__str__(self): 作用: 创建完对象,直接打印对象名/引用名我们得到的是对象的内存信息(十六进制的地址信息), 这串数据我们程序员并不关心,我们更希望看到的是属性赋值以后的内容(属性赋 ...
- 死磕nginx系列--nginx 限流配置
限流算法 令牌桶算法 算法思想是: 令牌以固定速率产生,并缓存到令牌桶中: 令牌桶放满时,多余的令牌被丢弃: 请求要消耗等比例的令牌才能被处理: 令牌不够时,请求被缓存. 漏桶算法 算法思想是: 水( ...
- 利用 Settings Sync 同步vs code配置
vs code上有各种各样不同的插件,如果要在不同的电脑上使用 vs code 配置是件比较麻烦的事情,使用 Settings Sync 将 vs code 配置备份起来,当需要在其他电脑使用 vs ...
- docker-machine create -d generic 运行的波折过程及遇见的问题
这是一个愚蠢的学习过程,但是因为觉得过程还是值得记录的,还是写了下来 2>driver = generic 1)在这个过程中使用的都是本地的mac系统,然后尝试在mac本地create -d g ...
- loglevel-metamask
pimterry/loglevel https://github.com/pimterry/loglevel Minimal lightweight simple logging for JavaSc ...