剑指Offer--图的操作
剑指Offer–图的操作
前言
企业笔试过程中会涉及到数据结构的方方面面,现将有关图的深度优先搜索与广度优先搜索进行整理归纳,方便日后查阅。
在已做过的笔试题目中,可用DFS解决的题目有:
三道题目都是DFS的经典应用,主要采用递归+回溯的方式。
下面主要讲解一下DFS与BFS的具体实现。
深度优先搜索(DFS) && 广度优先搜索(BFS)
package cn.edu.ujn.graph;
import java.util.ArrayList;
import java.util.LinkedList;
/**
* @description 邻接矩阵模型类
* @author SHQ
* @time 2016.09.12
*/
public class DFS_BFS {
private ArrayList<Object> vertexList;// 存储点的链表
private int[][] edges; // 邻接矩阵,用来存储边
private int numOfEdges; // 边的数目
boolean[] isVisited; // 遍历标志位
public DFS_BFS(int n) {
//初始化矩阵,二维数组,和边的数目
edges = new int[n][n];
vertexList = new ArrayList<Object>(n);
numOfEdges = 0;
// 将所有节点访问标志位均置为未访问
isVisited = new boolean[n];
for(int i = 0; i < n; i++){
isVisited[i] = false;
}
}
// 得到结点的个数
public int getNumOfVertex() {
return vertexList.size();
}
// 得到边的数目
public int getNumOfEdges() {
return numOfEdges;
}
// 返回结点i的数据
public Object getValueByIndex(int i) {
return vertexList.get(i);
}
// 返回v1,v2的权值
public int getWeight(int v1,int v2) {
return edges[v1][v2];
}
//插入结点
public void insertVertex(Object vertex) {
vertexList.add(vertexList.size(),vertex);
}
//插入结点
public void insertEdge(int v1,int v2,int weight) {
edges[v1][v2]=weight;
numOfEdges++;
}
//删除结点
public void deleteEdge(int v1,int v2) {
edges[v1][v2] = 0;
numOfEdges--;
}
// 得到第一个邻接结点的下标
public int getFirstNeighbor(int index) {
for(int j = 0; j < vertexList.size(); j++) {
if (edges[index][j] > 0) {
return j;
}
}
return -1;
}
// 根据前一个邻接结点的下标来取得下一个邻接结点
public int getNextNeighbor(int v1, int v2) {
for (int j = v2+1; j < vertexList.size(); j++) {
if (edges[v1][j]>0) {
return j;
}
}
return -1;
}
// 私有函数,深度优先遍历
private void depthFirstSearch(boolean[] isVisited,int i) {
// 首先访问该结点,在控制台打印出来
System.out.print(getValueByIndex(i) + " ");
// 置该结点为已访问
isVisited[i] = true;
int w = getFirstNeighbor(i);
while (w != -1) {
if (!isVisited[w]) {
depthFirstSearch(isVisited,w);
}
w = getNextNeighbor(i, w);
}
}
// 对外公开函数,深度优先遍历,与其同名私有函数属于方法重载
public void depthFirstSearch() {
for(int i = 0; i < getNumOfVertex(); i++) {
//因为对于非连通图来说,并不是通过一个结点就一定可以遍历所有结点的。
if (!isVisited[i]) {
depthFirstSearch(isVisited,i);
}
}
}
/**
* 私有函数,广度优先遍历
* 遍历步骤:
* 1.访问初始结点v并标记结点v为已访问。
* 2.结点v入队列
* 3.当队列非空时,继续执行,否则算法结束。
* 4.出队列,取得队头结点u。
* 5.查找结点u的第一个邻接结点w。
* 6.若结点u的邻接结点w不存在,则转到步骤3;否则循环执行以下三个步骤:
* 1)若结点w尚未被访问,则访问结点w并标记为已访问。
* 2)结点w入队列
* 3)查找结点u的继w邻接结点后的下一个邻接结点w,转到步骤6。
* @param isVisited
* @param i
*/
private void broadFirstSearch(boolean[] isVisited, int i) {
int u, w;
// 借助辅助队列,记录访问顺序
LinkedList<Object> queue = new LinkedList<Object>();
// 访问结点i
System.out.print(getValueByIndex(i) + " ");
isVisited[i] = true;
// 结点入队列
queue.addLast(i);
while (!queue.isEmpty()) {
u = ((Integer)queue.removeFirst()).intValue();
w = getFirstNeighbor(u);
while(w != -1) {
if(!isVisited[w]) {
//访问该结点
System.out.print(getValueByIndex(w)+" ");
//标记已被访问
isVisited[w] = true;
//入队列
queue.addLast(w);
}
//寻找下一个邻接结点
w = getNextNeighbor(u, w);
}
}
}
//对外公开函数,广度优先遍历
public void broadFirstSearch() {
for(int i = 0; i < getNumOfVertex(); i++) {
if(!isVisited[i]) {
broadFirstSearch(isVisited, i);
}
}
}
}
Main.java
package cn.edu.ujn.graph;
public class Main {
public static void main(String args[]) {
int n = 8, e = 9; // 分别代表结点个数和边的数目
String labels[]={"1","2","3","4","5","6","7","8"}; // 结点的标识
DFS_BFS graph = new DFS_BFS(n);
for(String label : labels) {
graph.insertVertex(label); // 插入结点
}
//插入九条边
graph.insertEdge(0, 1, 1);
graph.insertEdge(0, 2, 1);
graph.insertEdge(1, 3, 1);
graph.insertEdge(1, 4, 1);
graph.insertEdge(3, 7, 1);
graph.insertEdge(4, 7, 1);
graph.insertEdge(2, 5, 1);
graph.insertEdge(2, 6, 1);
graph.insertEdge(5, 6, 1);
graph.insertEdge(1, 0, 1);
graph.insertEdge(2, 0, 1);
graph.insertEdge(3, 1, 1);
graph.insertEdge(4, 1, 1);
graph.insertEdge(7, 3, 1);
graph.insertEdge(7, 4, 1);
graph.insertEdge(6, 2, 1);
graph.insertEdge(5, 2, 1);
graph.insertEdge(6, 5, 1);
/* System.out.println("深度优先搜索序列为:");
graph.depthFirstSearch();
System.out.println();*/
System.out.println("广度优先搜索序列为:");
graph.broadFirstSearch();
}
}
剑指Offer--图的操作的更多相关文章
- 剑指Offer——Java实现栈和队列的互模拟操作
剑指Offer--Java实现栈和队列的互模拟操作 栈模拟队列 题目:JAVA实现用两个栈来实现一个队列,完成队列的Push和Pop操作.队列中的元素为int类型. 思路:其实就是把队列正常入 ...
- [剑指offer]09用两个栈实现队列插入和删除操作,C++实现
原创博文,转载请注明出处! # 本文为牛客网<剑指offer>刷题笔记 1.题目 # 用两个栈实现队列的插入和删除操作 2.思路 栈服从先入后出的原则处理数据,队列服从先入先出的原则处理数 ...
- 面试经典算法题集锦——《剑指 offer》小结
从今年 3 月份开始准备找实习,到现在校招结束,申请的工作均为机器学习/数据挖掘算法相关职位,也拿到了几个 sp offer.经历这半年的洗礼,自己的综合能力和素质都得到了一个质的提升. 实话说对于未 ...
- 剑指Offer——知识点储备--Linux基本命令+Makefile
剑指Offer--知识点储备–Linux基本命令 1.linux下查看进程占用cpu的情况(top): 格式 top [-] [d delay] [q] [c] [S] [s] [i] [n] 主要参 ...
- 剑指Offer——知识点储备-故障检测、性能调优与Java类加载机制
剑指Offer--知识点储备-故障检测.性能调优与Java类加载机制 故障检测.性能调优 用什么工具可以查出内存泄露 (1)MerroyAnalyzer:一个功能丰富的java堆转储文件分析工具,可以 ...
- 剑指Offer——知识点储备-J2EE基础
剑指Offer--知识点储备-J2EE基础 9.2 jdk 1.8的新特性(核心是Lambda 表达式) 参考链接:http://www.bubuko.com/infodetail-690646.ht ...
- 剑指Offer——迅雷笔试题+知识点总结
剑指Offer--迅雷笔试题+知识点总结 情景回顾 时间:2016.9.19 19:00-21:00 地点:山东省网络环境智能计算技术重点实验室 事件:迅雷笔试 总体来说,迅雷笔试内容体量不算多,主要 ...
- 剑指Offer——携程笔试题+知识点总结
剑指Offer--携程笔试题+知识点总结 情景回顾 时间:2016.9.17 19:10-21:10 地点:山东省网络环境智能计算技术重点实验室 事件:携程笔试 总体来说,携程笔试内容与其它企业笔试题 ...
- 剑指Offer——归并排序思想应用
剑指Offer--归并排序思想应用 前言 在学习排序算法时,初识归并排序,从其代码量上感觉这个排序怎么这么难啊.其实归并排序的思想很简单:将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列 ...
- 剑指Offer——巧妙使用sort(List<T>,Comparator<? super T>)比较器
剑指Offer--巧妙使用sort(List<T>,Comparator<? super T>)比较器 先入为主 package cn.edu.ujn.offersword; ...
随机推荐
- poj3728 商务旅行
[Description]小 T 要经常进行商务旅行,他所在的国家有 N 个城镇,标号为 1,2,3,...,N,这 N 个城镇构成一棵树.每个城镇可以买入和卖出货物,同一城镇买入和卖出的价格一样,小 ...
- BestCoder 1st Anniversary ——HDU5312(数学推导)
Today, Soda has learned a sequence whose n-th (n≥1) item is 3n(n−1)+1. Now he wants to know if an in ...
- POJ 3276 Face The Right Way
Description Farmer John has arranged his N (1 ≤ N ≤ 5,000) cows in a row and many of them are facing ...
- bzoj3825 NOI2017 游戏
题目背景 狂野飙车是小 L 最喜欢的游戏.与其他业余玩家不同的是,小 L 在玩游戏之余,还精于研究游戏的设计,因此他有着与众不同的游戏策略. 题目描述 小 L 计划进行nn 场游戏,每场游戏使用一张地 ...
- c语言的第四次作业
(一)改错题 输出三角形的面积和周长,输入三角形的三条边a.b.c,如果能构成一个三角形,输出面积area和周长perimeter(保留2位小数):否则,输出"These sides do ...
- 文件上传,服务端压缩文件方法,重点是png与gif图片的压缩,保证了透明度与动画
/// <summary> /// 上传文件帮助类 /// </summary> public class ImageUploadHelper { #region SaveVi ...
- python学习之路网络编程篇(第四篇)- 续
Memcache简介 Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速 ...
- Vue国际化处理 vue-i18n 以及项目自动切换中英文
1. 环境搭建 命令进入项目目录,执行以下命令安装vue 国际化插件vue-i18n npm install vue-i18n --save 2. 项目增加国际化翻译文件 在项目的src下添加lang ...
- JAVA中抽象类的使用
抽象类是从多个具体类中抽象出来的父类,它具有更高层次的抽象.抽象类体现的就是一种模板模式的设计,抽象父类可以只定义需要使用的某些方法,把不能实现的某些部分抽象成抽象方法,留给其子类去实现.具体来说,抽 ...
- Node.js C/C++ 插件
插件 Addons 是动态链接的共享对象.他提供了 C/C++ 类库能力.这些API比较复杂,他包以下几个类库: V8 JavaScript, C++ 类库.用来和 JavaScript 交互,比如创 ...