Java編程實(shí)現(xiàn)基于圖的深度優(yōu)先搜索和廣度優(yōu)先搜索完整代碼
為了解15puzzle問(wèn)題,了解了一下深度優(yōu)先搜索和廣度優(yōu)先搜索。先來(lái)討論一下深度優(yōu)先搜索(DFS),深度優(yōu)先的目的就是優(yōu)先搜索距離起始頂點(diǎn)最遠(yuǎn)的那些路徑,而廣度優(yōu)先搜索則是先搜索距離起始頂點(diǎn)最近的那些路徑。我想著深度優(yōu)先搜索和回溯有什么區(qū)別呢?百度一下,說(shuō)回溯是深搜的一種,區(qū)別在于回溯不保留搜索樹(shù)。那么廣度優(yōu)先搜索(BFS)呢?它有哪些應(yīng)用呢?答:最短路徑,分酒問(wèn)題,八數(shù)碼問(wèn)題等。言歸正傳,這里筆者用java簡(jiǎn)單實(shí)現(xiàn)了一下廣搜和深搜。其中深搜是用圖+棧實(shí)現(xiàn)的,廣搜使用圖+隊(duì)列實(shí)現(xiàn)的,代碼如下:
1.新建一個(gè)表示“無(wú)向圖”類NoDirectionGraph
package com.wly.algorithmbase.datastructure;
/** 
 * 無(wú)向圖 
 * @author wly 
 * 
 */
public class NoDirectionGraph {
	private int mMaxSize;
	//圖中包含的最大頂點(diǎn)數(shù) 
	private GraphVertex[] vertexList;
	//頂點(diǎn)數(shù)組 
	private int[][] indicatorMat;
	//指示頂點(diǎn)之間的連通關(guān)系的鄰接矩陣 
	private int nVertex;
	//當(dāng)前實(shí)際保存的頂點(diǎn)數(shù)目 
	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("---插入失敗,頂點(diǎn)數(shù)量已達(dá)上限!");
		}
	}
	/** 
   * 修改鄰接矩陣,添加新的邊 
   * @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();
		}
	}
	/** 
   * 深度優(yōu)先遍歷 
   * @param vertexIndex 表示要遍歷的起點(diǎn),即圖的鄰接矩陣中的行數(shù) 
   */
	public void DFS(int vertexIndex) {
		ArrayStack stack = new ArrayStack();
		//1.添加檢索元素到棧中 
		vertexList[vertexIndex].setVisited(true);
		stack.push(vertexIndex);
		int nextVertexIndex = getNextVertexIndex(vertexIndex);
		while(!stack.isEmpty()) {
			//不斷地壓棧、出棧,直到棧為空(檢索元素也沒(méi)彈出了棧)為止 
			if(nextVertexIndex != -1) {
				vertexList[nextVertexIndex].setVisited(true);
				stack.push(nextVertexIndex);
				stack.printElems();
			} else {
				stack.pop();
			}
			//檢索當(dāng)前棧頂元素是否包含其他未遍歷過(guò)的節(jié)點(diǎn) 
			if(!stack.isEmpty()) {
				nextVertexIndex = getNextVertexIndex(stack.peek());
			}
		}
	}
	/** 
   * 得到當(dāng)前頂點(diǎn)的下一個(gè)頂點(diǎn)所在行 
   * @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;
	}
	/** 
   * 廣度優(yōu)先遍歷 
   * @param vertexIndex 表示要遍歷的起點(diǎn),即圖的鄰接矩陣中的行數(shù) 
   */
	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.然后是一個(gè)用數(shù)組模擬的棧ArrayStack
package com.wly.algorithmbase.datastructure;
/** 
 * 使用數(shù)組實(shí)現(xiàn)棧結(jié)構(gòu) 
 * @author wly 
 * 
 */
public class ArrayStack {
	private int[] tArray;
	private int topIndex = -1;
	//表示當(dāng)前棧頂元素的索引位置 
	private int CAPACITY_STEP = 12;
	//數(shù)組容量擴(kuò)展步長(zhǎng) 
	public ArrayStack() {
		/***創(chuàng)建泛型數(shù)組的一種方法***/
		tArray = new int[CAPACITY_STEP];
	}
	/** 
   * 彈出棧頂元素方法 
   * @return 
   */
	public int pop() {
		if(isEmpty()) {
			System.out.println("錯(cuò)誤,棧中元素為空,不能pop");
			return -1;
		} else {
			int i = tArray[topIndex];
			tArray[topIndex--] = -1;
			//擦除pop元素 
			return i;
		}
	}
	/** 
   * 向棧中插入一個(gè)元素 
   * @param t 
   */
	public void push(int t) {
		//檢查棧是否已滿 
		if(topIndex == (tArray.length-1)) {
			//擴(kuò)展容量 
			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("錯(cuò)誤,棧中元素為空,不能peek");
			return -1;
		} else {
			return tArray[topIndex];
		}
	}
	/** 
   * 判斷當(dāng)前棧是否為空 
   * @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.在一個(gè)用鏈表模擬的隊(duì)列ChainQueue
package com.wly.algorithmbase.datastructure;
/** 
 * 使用鏈表實(shí)現(xiàn)隊(duì)列 
 * 
 * @author wly 
 * 
 */
public class ChainQueue {
	private QueueNode head;
	// 指向隊(duì)列頭節(jié)點(diǎn) 
	private QueueNode tail;
	// 指向隊(duì)列尾節(jié)點(diǎn) 
	private int size = 0;
	// 隊(duì)列尺寸 
	public ChainQueue() {
	}
	/** 
   * 插入新節(jié)點(diǎn)到隊(duì)列尾 
   */
	public void insert(QueueNode node) {
		// 當(dāng)然也可以這么寫(xiě),添加tail.prev = node 
		if (head == null) {
			head = node;
			tail = head;
		} else {
			node.next = tail;
			tail.prev = node;
			// 雙向連接,確保head.prev不為空 
			tail = node;
		}
		size++;
	}
	/** 
   * 移除隊(duì)列首節(jié)點(diǎn) 
   */
	public QueueNode remove() {
		if (!isEmpty()) {
			QueueNode temp = head;
			head = head.prev;
			size--;
			return temp;
		} else {
			System.out.println("異常操作,當(dāng)前隊(duì)列為空!");
			return null;
		}
	}
	/** 
   * 隊(duì)列是否為空 
   * 
   * @return 
   */
	public Boolean isEmpty() {
		if (size > 0) {
			return false;
		} else {
			return true;
		}
	}
	/** 
   * 返回隊(duì)列首節(jié)點(diǎn),但不移除 
   */
	public QueueNode peek() {
		if (!isEmpty()) {
			return head;
		} else {
			System.out.println();
			System.out.println("異常操作,當(dāng)前隊(duì)列為空!");
			return null;
		}
	}
	/** 
   * 返回隊(duì)列大小 
   * 
   * @return 
   */
	public int size() {
		return size;
	}
	/** 
   * 打印隊(duì)列中的元素 
   */
	public void printElems() {
		QueueNode tempNode = head;
		while(tempNode != null) {
			System.out.print(tempNode.data + " ");
			tempNode = tempNode.prev;
		}
		System.out.println();
	}
}
/** 
 * 節(jié)點(diǎn)類 
 * 
 * @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.測(cè)試一下Test_BFS_DFS
package com.wly.algorithmbase.search;
import com.wly.algorithmbase.datastructure.GraphVertex;
import com.wly.algorithmbase.datastructure.NoDirectionGraph;
/** 
 * 基于圖的深度優(yōu)先搜索 
 * @author wly 
 * 
 */
public class Test_BFS_DFS {
	public static void main(String[] args) {
		//初始化測(cè)試數(shù)據(jù) 
		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();
		//測(cè)試深搜 
		System.out.println("--深度優(yōu)先搜索--");
		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("--廣度優(yōu)先搜索--");
		graph.BFS(0);
	}
}
這里測(cè)試的圖結(jié)構(gòu)如下:
運(yùn)行結(jié)果如下:
--圖的鄰接矩陣-- 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 --深度優(yōu)先搜索-- 0 1 0 1 3 0 1 3 6 0 1 4 0 2 0 2 5 --廣度優(yōu)先搜索-- 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
這里需要說(shuō)明一下上面深搜和廣搜的運(yùn)行結(jié)果,其中0,1,2,3…分別對(duì)應(yīng)著A,B,C,D...有點(diǎn)繞哈,,見(jiàn)諒~~
O啦~~~
總結(jié)
以上就是本文關(guān)于Java編程實(shí)現(xiàn)基于圖的深度優(yōu)先搜索和廣度優(yōu)先搜索完整代碼的全部?jī)?nèi)容,希望對(duì)大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關(guān)專題,如有不足之處,歡迎留言指出。感謝朋友們對(duì)本站的支持!
欄 目:Java編程
下一篇:Java編程常見(jiàn)內(nèi)存溢出異常與代碼示例
本文標(biāo)題:Java編程實(shí)現(xiàn)基于圖的深度優(yōu)先搜索和廣度優(yōu)先搜索完整代碼
本文地址:http://www.jygsgssxh.com/a1/Javabiancheng/8374.html
您可能感興趣的文章
- 01-10Java咖啡館(1)——嘆咖啡
 - 01-10Java Socket編程(三) 服務(wù)器Sockets
 - 01-10Java進(jìn)階:Struts多模塊的技巧
 - 01-10Java Socket編程(一) Socket傳輸模式
 - 01-10Java Socket編程(二) Java面向連接的類
 - 01-10Java運(yùn)行時(shí)多態(tài)性的實(shí)現(xiàn)
 - 01-10Java經(jīng)驗(yàn)點(diǎn)滴:處理沒(méi)有被捕獲的異常
 - 01-10Java Socket編程(四) 重復(fù)和并發(fā)服務(wù)器
 - 01-10Java中的浮點(diǎn)數(shù)分析
 - 01-10面向?qū)ο缶幊?Java中的抽象數(shù)據(jù)類型
 


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
 - 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹(shù)的示例代碼(圣誕
 - 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
 - 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
 - 5c語(yǔ)言計(jì)算三角形面積代碼
 - 6什么是 WSH(腳本宿主)的詳細(xì)解釋
 - 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
 - 8正則表達(dá)式匹配各種特殊字符
 - 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
 - 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
 
本欄相關(guān)
- 01-10Java咖啡館(1)——嘆咖啡
 - 01-10JVM的垃圾回收機(jī)制詳解和調(diào)優(yōu)
 - 01-10Java Socket編程(三) 服務(wù)器Sockets
 - 01-10Java進(jìn)階:Struts多模塊的技巧
 - 01-10J2SE 1.5版本的新特性一覽
 - 01-10Java Socket編程(一) Socket傳輸模式
 - 01-10Java運(yùn)行時(shí)多態(tài)性的實(shí)現(xiàn)
 - 01-10Java Socket編程(二) Java面向連接的類
 - 01-10Java Socket編程(四) 重復(fù)和并發(fā)服務(wù)
 - 01-10Java經(jīng)驗(yàn)點(diǎn)滴:處理沒(méi)有被捕獲的異常
 
隨機(jī)閱讀
- 01-10SublimeText編譯C開(kāi)發(fā)環(huán)境設(shè)置
 - 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
 - 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
 - 04-02jquery與jsp,用jquery
 - 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
 - 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
 - 01-10delphi制作wav文件的方法
 - 01-10C#中split用法實(shí)例總結(jié)
 - 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
 - 01-11Mac OSX 打開(kāi)原生自帶讀寫(xiě)NTFS功能(圖文
 


