Java编程实现基于图的深度优先搜索和广度优先搜索完整代码

为了解15puzzle问题,了解了一下深度优先搜索和广度优先搜索。先来讨论一下深度优先搜索(DFS),深度优先的目的就是优先搜索距离起始顶点最远的那些路径,而广度优先搜索则是先搜索距离起始顶点最近的那些路径。我想着深度优先搜索和回溯有什么区别呢?百度一下,说回溯是深搜的一种,区别在于回溯不保留搜索树。那么广度优先搜索(BFS)呢?它有哪些应用呢?答:最短路径,分酒问题,八数码问题等。言归正传,这里笔者用java简单实现了一下广搜和深搜。其中深搜是用图+栈实现的,广搜使用图+队列实现的,代码如下:

1.新建一个表示“无向图”类NoDirectionGraph

package com.wly.algorithmbase.datastructure;
/**
 * 无向图
 * @author wly
 *
 */
public class NoDirectionGraph {
	private int mMaxSize;
	//图中包含的最大顶点数
	private GraphVertex[] vertexList;
	//顶点数组
	private int[][] indicatorMat;
	//指示顶点之间的连通关系的邻接矩阵
	private int nVertex;
	//当前实际保存的顶点数目
	public NoDirectionGraph(int maxSize) {
		mMaxSize = maxSize;
		vertexList = new GraphVertex[mMaxSize];
		indicatorMat = new int[mMaxSize][mMaxSize];
		nVertex = 0;
		//初始化邻接矩阵元素为0
		for (int j=0;j<mMaxSize;j++) {
			for (int k=0;k<mMaxSize;k++) {
				indicatorMat[j][k] = 0;
			}
		}
	}
	public void addVertex(GraphVertex v) {
		if(nVertex < mMaxSize) {
			vertexList[nVertex++] = v;
		} else {
			System.out.println("---插入失败,顶点数量已达上限!");
		}
	}
	/**
   * 修改邻接矩阵,添加新的边
   * @param start
   * @param end
   */
	public void addEdge(int start,int end) {
		indicatorMat[start][end] = 1;
		indicatorMat[end][start] = 1;
	}
	/**
   * 打印邻接矩阵
   */
	public void printIndicatorMat() {
		for (int[] line:indicatorMat) {
			for (int i:line) {
				System.out.print(i + " ");
			}
			System.out.println();
		}
	}
	/**
   * 深度优先遍历
   * @param vertexIndex 表示要遍历的起点,即图的邻接矩阵中的行数
   */
	public void DFS(int vertexIndex) {
		ArrayStack stack = new ArrayStack();
		//1.添加检索元素到栈中
		vertexList[vertexIndex].setVisited(true);
		stack.push(vertexIndex);
		int nextVertexIndex = getNextVertexIndex(vertexIndex);
		while(!stack.isEmpty()) {
			//不断地压栈、出栈,直到栈为空(检索元素也没弹出了栈)为止
			if(nextVertexIndex != -1) {
				vertexList[nextVertexIndex].setVisited(true);
				stack.push(nextVertexIndex);
				stack.printElems();
			} else {
				stack.pop();
			}
			//检索当前栈顶元素是否包含其他未遍历过的节点
			if(!stack.isEmpty()) {
				nextVertexIndex = getNextVertexIndex(stack.peek());
			}
		}
	}
	/**
   * 得到当前顶点的下一个顶点所在行
   * @param column
   * @return
   */
	public int getNextVertexIndex(int column) {
		for (int i=0;i<indicatorMat[column].length;i++) {
			if(indicatorMat[column][i] == 1 && !vertexList[i].isVisited()) {
				return i;
			}
		}
		return -1;
	}
	/**
   * 广度优先遍历
   * @param vertexIndex 表示要遍历的起点,即图的邻接矩阵中的行数
   */
	public void BFS(int vertexIndex) {
		ChainQueue queue = new ChainQueue();
		vertexList[vertexIndex].setVisited(true);
		queue.insert(new QueueNode(vertexIndex));
		int nextVertexIndex = getNextVertexIndex(vertexIndex);
		while(!queue.isEmpty()) {
			if(nextVertexIndex != -1) {
				vertexList[nextVertexIndex].setVisited(true);
				queue.insert(new QueueNode(nextVertexIndex));
			} else {
				queue.remove();
			}
			if(!queue.isEmpty()) {
				nextVertexIndex = getNextVertexIndex(queue.peek().data);
				queue.printElems();
			}
		}
	}
}

2.然后是一个用数组模拟的栈ArrayStack

package com.wly.algorithmbase.datastructure;
/**
 * 使用数组实现栈结构
 * @author wly
 *
 */
public class ArrayStack {
	private int[] tArray;
	private int topIndex = -1;
	//表示当前栈顶元素的索引位置
	private int CAPACITY_STEP = 12;
	//数组容量扩展步长
	public ArrayStack() {
		/***创建泛型数组的一种方法***/
		tArray = new int[CAPACITY_STEP];
	}
	/**
   * 弹出栈顶元素方法
   * @return
   */
	public int pop() {
		if(isEmpty()) {
			System.out.println("错误,栈中元素为空,不能pop");
			return -1;
		} else {
			int i = tArray[topIndex];
			tArray[topIndex--] = -1;
			//擦除pop元素
			return i;
		}
	}
	/**
   * 向栈中插入一个元素
   * @param t
   */
	public void push(int t) {
		//检查栈是否已满
		if(topIndex == (tArray.length-1)) {
			//扩展容量
			int[] tempArray = new int[tArray.length + CAPACITY_STEP];
			for (int i=0;i<tArray.length;i++) {
				tempArray[i] = tArray[i];
			}
			tArray = tempArray;
			tempArray = null;
		} else {
			topIndex ++;
			tArray[topIndex] = t;
		}
	}
	/**
   * 得到栈顶元素,但不弹出
   * @return
   */
	public int peek() {
		if(isEmpty()) {
			System.out.println("错误,栈中元素为空,不能peek");
			return -1;
		} else {
			return tArray[topIndex];
		}
	}
	/**
   * 判断当前栈是否为空
   * @return
   */
	public Boolean isEmpty() {
		return (topIndex < 0);
	}
	/**
   * 打印栈中元素
   */
	public void printElems() {
		for (int i=0;i<=topIndex;i++) {
			System.out.print(tArray[i] + " ");
		}
		System.out.println();
	}
}

3.在一个用链表模拟的队列ChainQueue

package com.wly.algorithmbase.datastructure;
/**
 * 使用链表实现队列
 *
 * @author wly
 *
 */
public class ChainQueue {
	private QueueNode head;
	// 指向队列头节点
	private QueueNode tail;
	// 指向队列尾节点
	private int size = 0;
	// 队列尺寸
	public ChainQueue() {
	}
	/**
   * 插入新节点到队列尾
   */
	public void insert(QueueNode node) {
		// 当然也可以这么写,添加tail.prev = node
		if (head == null) {
			head = node;
			tail = head;
		} else {
			node.next = tail;
			tail.prev = node;
			// 双向连接,确保head.prev不为空
			tail = node;
		}
		size++;
	}
	/**
   * 移除队列首节点
   */
	public QueueNode remove() {
		if (!isEmpty()) {
			QueueNode temp = head;
			head = head.prev;
			size--;
			return temp;
		} else {
			System.out.println("异常操作,当前队列为空!");
			return null;
		}
	}
	/**
   * 队列是否为空
   *
   * @return
   */
	public Boolean isEmpty() {
		if (size > 0) {
			return false;
		} else {
			return true;
		}
	}
	/**
   * 返回队列首节点,但不移除
   */
	public QueueNode peek() {
		if (!isEmpty()) {
			return head;
		} else {
			System.out.println();
			System.out.println("异常操作,当前队列为空!");
			return null;
		}
	}
	/**
   * 返回队列大小
   *
   * @return
   */
	public int size() {
		return size;
	}
	/**
   * 打印队列中的元素
   */
	public void printElems() {
		QueueNode tempNode = head;
		while(tempNode != null) {
			System.out.print(tempNode.data + " ");
			tempNode = tempNode.prev;
		}
		System.out.println();
	}
}
/**
 * 节点类
 *
 * @author wly
 *
 */
class QueueNode {
	QueueNode prev;
	QueueNode next;
	int data;
	public QueueNode(int data) {
		this.data = data;
	}
	public int getData() {
		return data;
	}
	public void setData(int data) {
		this.data = data;
	}
	@Override
	  public String toString() {
		// TODO Auto-generated method stub
		super.toString();
		return data + "";
	}
}

4.测试一下Test_BFS_DFS

package com.wly.algorithmbase.search;
import com.wly.algorithmbase.datastructure.GraphVertex;
import com.wly.algorithmbase.datastructure.NoDirectionGraph;
/**
 * 基于图的深度优先搜索
 * @author wly
 *
 */
public class Test_BFS_DFS {
	public static void main(String[] args) {
		//初始化测试数据
		NoDirectionGraph graph = new NoDirectionGraph(7);
		graph.addVertex(new GraphVertex("A"));
		graph.addVertex(new GraphVertex("B"));
		graph.addVertex(new GraphVertex("C"));
		graph.addVertex(new GraphVertex("D"));
		graph.addVertex(new GraphVertex("E"));
		graph.addVertex(new GraphVertex("F"));
		graph.addVertex(new GraphVertex("G"));
		graph.addEdge(0, 1);
		graph.addEdge(0, 2);
		graph.addEdge(1, 3);
		graph.addEdge(1, 4);
		graph.addEdge(3, 6);
		graph.addEdge(2, 5);
		System.out.println("--图的邻接矩阵--");
		graph.printIndicatorMat();
		//测试深搜
		System.out.println("--深度优先搜索--");
		graph.DFS(0);
		graph = new NoDirectionGraph(7);
		graph.addVertex(new GraphVertex("A"));
		graph.addVertex(new GraphVertex("B"));
		graph.addVertex(new GraphVertex("C"));
		graph.addVertex(new GraphVertex("D"));
		graph.addVertex(new GraphVertex("E"));
		graph.addVertex(new GraphVertex("F"));
		graph.addVertex(new GraphVertex("G"));
		graph.addEdge(0, 1);
		graph.addEdge(0, 2);
		graph.addEdge(1, 3);
		graph.addEdge(1, 4);
		graph.addEdge(3, 6);
		graph.addEdge(2, 5);
		System.out.println("--广度优先搜索--");
		graph.BFS(0);
	}
}

这里测试的图结构如下:

运行结果如下:

--图的邻接矩阵--
0 1 1 0 0 0 0
1 0 0 1 1 0 0
1 0 0 0 0 1 0
0 1 0 0 0 0 1
0 1 0 0 0 0 0
0 0 1 0 0 0 0
0 0 0 1 0 0 0
--深度优先搜索--
0 1
0 1 3
0 1 3 6
0 1 4
0 2
0 2 5
--广度优先搜索--
0 1
0 1 2
1 2
1 2 3
1 2 3 4
2 3 4
2 3 4 5
3 4 5
3 4 5 6
4 5 6
5 6
6  

这里需要说明一下上面深搜和广搜的运行结果,其中0,1,2,3…分别对应着A,B,C,D...有点绕哈,,见谅~~
O啦~~~

总结

以上就是本文关于Java编程实现基于图的深度优先搜索和广度优先搜索完整代码的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

(0)

相关推荐

  • java编程无向图结构的存储及DFS操作代码详解

    图的概念 图是算法中是树的拓展,树是从上向下的数据结构,结点都有一个父结点(根结点除外),从上向下排列.而图没有了父子结点的概念,图中的结点都是平等关系,结果更加复杂. 无向图                                                       有向图 图G=(V,E),其中V代表顶点Vertex,E代表边edge,一条边就是一个定点对(u,v),其中(u,v)∈V. 这两天遇到一个关于图的算法,在网上找了很久没有找到java版的关于数据结构中图的存储及其

  • 邻接表无向图的Java语言实现完整源码

    邻接表无向图的介绍 邻接表无向图是指通过邻接表表示的无向图. 上面的图G1包含了"A,B,C,D,E,F,G"共7个顶点,而且包含了"(A,C),(A,D),(A,F),(B,C),(C,D),(E,G),(F,G)"共7条边. 上图右边的矩阵是G1在内存中的邻接表示意图.每一个顶点都包含一条链表,该链表记录了"该顶点的邻接点的序号".例如,第2个顶点(顶点C)包含的链表所包含的节点的数据分别是"0,1,3":而这"

  • Java编程实现高斯模糊和图像的空间卷积详解

    高斯模糊 高斯模糊(英语:Gaussian Blur),也叫高斯平滑,是在Adobe Photoshop.GIMP以及Paint.NET等图像处理软件中广泛使用的处理效果,通常用它来减少图像杂讯以及降低细节层次.这种模糊技术生成的图像,其视觉效果就像是经过一个半透明屏幕在观察图像,这与镜头焦外成像效果散景以及普通照明阴影中的效果都明显不同.高斯平滑也用于计算机视觉算法中的预先处理阶段,以增强图像在不同比例大小下的图像效果. 从数学的角度来看,图像的高斯模糊过程就是图像与正态分布做卷积.由于正态分

  • Java编程实现邻接矩阵表示稠密图代码示例

    我们知道,要表示结点,我们可以用一个一维数组来表示,然而对于结点和结点之间的关系,则无法简单地用一维数组来表示了,我们可以用二维数组来表示,也就是一个矩阵形式的表示方法. 我们假设A是这个二维数组,那么A中的一个元素aij不仅体现出了结点vi和结点vj的关系,而且aij的值正可以表示权值的大小. 邻接矩阵模型类 邻接矩阵模型类的类名为AMWGraph.java,能够通过该类构造一个邻接矩阵表示的图,且提供插入结点,插入边,取得某一结点的第一个邻接结点和下一个邻接结点. import java.u

  • Java实现的图片高质量缩放类定义与用法示例

    本文实例讲述了Java实现的图片高质量缩放类定义与用法.分享给大家供大家参考,具体如下: 找了很多都不理想,最后找个到老外写的,不得不承认老外写的确实牛B. package com.test; import com.sun.image.codec.jpeg.JPEGImageEncoder; import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGEncodeParam; import java

  • Java实现的微信图片处理工具类【裁剪,合并,等比例缩放等】

    本文实例讲述了Java实现的微信图片处理工具类.分享给大家供大家参考,具体如下: 现在 外面核心,图片文章比较少,看了拷贝代码,而用不了,用相应jar包处理,很多等比例缩放,达不到 想要的给予的期望:本工具类,是之前做微信打印机写的 基于java自带的类,基于rgb. package com.zjpz.util; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt

  • Java编程实现基于图的深度优先搜索和广度优先搜索完整代码

    为了解15puzzle问题,了解了一下深度优先搜索和广度优先搜索.先来讨论一下深度优先搜索(DFS),深度优先的目的就是优先搜索距离起始顶点最远的那些路径,而广度优先搜索则是先搜索距离起始顶点最近的那些路径.我想着深度优先搜索和回溯有什么区别呢?百度一下,说回溯是深搜的一种,区别在于回溯不保留搜索树.那么广度优先搜索(BFS)呢?它有哪些应用呢?答:最短路径,分酒问题,八数码问题等.言归正传,这里笔者用java简单实现了一下广搜和深搜.其中深搜是用图+栈实现的,广搜使用图+队列实现的,代码如下:

  • java编程实现基于UDP协议传输数据的方法

    本文实例讲述了java编程实现基于UDP协议传输数据的方法.分享给大家供大家参考,具体如下: UDP协议(User Datagram Protocol,用户数据报协议)不同于TCP协议,它是不可能靠的,但是它比TCP协议具有更快的传输速度,UDP发送的数据单元称为数据报,当网络传输UDP传输UDP数据报是无法保证数据能够到达目的地,也无法保证按发送的顺序到达目的地,也就是说先发送了"hello",再发送了"world",但接收方可能会先收到"world&q

  • Java编程实现基于用户的协同过滤推荐算法代码示例

    协同过滤简单来说是利用某兴趣相投.拥有共同经验之群体的喜好来推荐用户感兴趣的信息,个人通过合作的机制给予信息相当程度的回应(如评分)并记录下来以达到过滤的目的进而帮助别人筛选信息,回应不一定局限于特别感兴趣的,特别不感兴趣信息的纪录也相当重要. 协同过滤又可分为评比(rating)或者群体过滤(social filtering)协同过滤以其出色的速度和健壮性,在全球互联网领域炙手可热 UserCF的核心思想即为根据用户数据模拟向量相似度,我们根据这个相似度,来找出指定用户的相似用户,然后将相似用

  • Java编程实现基于TCP协议的Socket聊天室示例

    本文实例讲述了Java编程实现基于TCP协议的Socket聊天室.分享给大家供大家参考,具体如下: 这里使用Socket套接字进行编程,完成的是基于TCP可靠服务实现服务器与客户端的双通信. Server服务器端: package com.han; import java.awt.Container; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.Win

  • PHP实现基于图的深度优先遍历输出1,2,3...n的全排列功能

    本文实例讲述了PHP实现基于图的深度优先遍历输出1,2,3...n的全排列功能.分享给大家供大家参考,具体如下: <?php $n=$_REQUEST["n"]; if($n>8) { echo "{$n}太大了,影响服务器性能"; return; } define("N",$n); $d=array(); $v=array(); for($i=0;$i<=N;$i++){ $d[$i]=$v[$i]=0; } function

  • 基于JavaScript实现网红太空人表盘的完整代码

    一.效果展示 用javascript写的一个太空人表盘. http://xiazai.jb51.net/202103/yuanma/Watch_jb51.rar 二.源代码 html代码 <html> <head> <title>太空人表盘</title> <meta charset="UTF-8"> <link href="./assets/css/style.css" rel="exte

  • 基于Json序列化和反序列化通用的封装完整代码

    1. 最近项目已经上线了 ,闲暇了几天 想将JSON的序列化以及反序列化进行重新的封装一下本人定义为JSONHelp,虽然Microsoft 已经做的很好了.但是我想封装一套为自己开发的项目使用.方便后期的扩展以及开发使用. 2. 什么是 JSON ? JSON:JavaScript 对象表示法(JavaScript Object Notation).JSON 是存储和交换文本信息的语法.类似 XML.JSON 比 XML 更小.更快,更易解析.  现在开发Web应用程序 JSON 是 必不可少

  • java编程之基于SpringBoot框架实现扫码登录

    目录 项目简介 实现思路 二次认证的原因 实现步骤 用户访问网页端,选择扫码登录 使用手机扫码,二维码状态改变 手机确认登录 效果演示 完整代码已上传到GitHub. Web端体验地址:http://47.116.72.33/(只剩一个月有效期) apk下载地址:https://github.com/zhangjiwei1221/qrscan/releases/tag/0.0.1. 用户名:非空即可,密码:123456,效果见文末,整体实现如有不妥之处,欢迎交流讨论 实现部分参考二维码扫码登录是

  • python深度优先搜索和广度优先搜索

    1. 深度优先搜索介绍 图的深度优先搜索(Depth First Search),和树的先序遍历比较类似. 它的思想:假设初始状态是图中所有顶点均未被访问,则从某个顶点v出发,首先访问该顶点,然后依次从它的各个未被访问的邻接点出发深度优先搜索遍历图,直至图中所有和v有路径相通的顶点都被访问到. 若此时尚有其他顶点未被访问到,则另选一个未被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止. 显然,深度优先搜索是一个递归的过程. 2. 广度优先搜索介绍 广度优先搜索算法(Breadt

  • ajax结合豆瓣搜索结果进行分页完整代码

    使用豆瓣api,得到分页结果.相当于从后台数据库获得的结果一样.所不同的是,没法事先知道页数.虽然通过请求api可以获得总页数,但由于ajax是异步的,所以对于分页一开始就要给出总页数来说,这是没有意义的.我使用了一个固定总页数65(正是搜索javascript书籍返回的总页数).所以其他书籍是并不是65页,会出现多页或者少页的情况,这并不是bug. 特点 1,全程不需要接触后台,前端独立就可以(我找过好长时间都没找过完整的例子). 2,使用了bootstrap的pagination制作页码和p

随机推荐