基于图的深度优先搜索和广度优先搜索java实现

来源:互联网 发布:教师资格证网络课程 编辑:程序博客网 时间:2024/06/08 06:46

       为了解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;//初始化邻接矩阵元素为0for(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 = nodeif (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;}@Overridepublic String toString() {// TODO Auto-generated method stubsuper.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啦~~~

       转载请保留出处:http://blog.csdn.net/u011638883/article/details/17169071

       谢谢!!


原创粉丝点击