1. 程式人生 > >8皇后以及N皇后演算法探究,回溯演算法的JAVA實現,非遞迴,資料結構“棧”實現

8皇后以及N皇后演算法探究,回溯演算法的JAVA實現,非遞迴,資料結構“棧”實現

是使用遞迴方法實現回溯演算法的,在第一次使用二維矩陣的情況下,又做了一次改一維的優化

但是演算法效率仍然差強人意,因為使用遞迴函式的緣故

下面提供另一種回溯演算法的實現,使用資料結構”棧“來模擬,遞迴函式的手工實現,因為我們知道計算機在處理遞迴時的本質就是棧

時間複雜度是一樣的,空間複雜度因為自定義了class,有所上升

經過測試其效能甚至低於上篇部落格的遞迴實現

權當是使用資料結構”棧“,解決15皇后的程式碼如下:

 

複製程式碼

package com.newflypig.eightqueen;

import java.util.Date;
import java.util.Stack;

/**
 * 使用資料結構“棧”,模擬遞迴函式
 * 實現非遞迴方案的回溯演算法
 * @author 
[email protected]
* Time: 2015年12月31日 下午6:13:05 */ public class EightQueen3 { private static final short N=15; public static void main(String[] args){ Date begin =new Date(); long count=0; /** * 初始化棧和棋盤,並向棧中壓入第一張初始化的棋盤 */ Stack<Chess> stack=new Stack<Chess>(); short[] chessData=new short[N]; for(short i=1;i<N;i++){ chessData[i]=-1; //初始化棋盤,所有行沒有皇后,賦值-1 } Chess initChess=new Chess(chessData); stack.push(initChess); //對棧進行操作,直到棧為空,程式計算完畢 EMPTY:while(!stack.isEmpty()){ /** * 訪問出口處的棋盤,判斷是否訪問過 * 如果沒有訪問過,訪問標誌改為true,構建下層資料 * 如果訪問過,嘗試對此棋盤col++尋找此行的合法解 * 尋找直至溢位邊界,pop掉,在尋找過程中如果發現合法解: * 修改col,訪問量狀態恢復到false,跳出isEmpty迴圈去訪問他 */ Chess chess=stack.peek(); if(chess.visited){ while(chess.moveCol()){ if( isSafety(chess) ){ chess.visited=false; continue EMPTY; } } stack.pop(); }else{ chess.visited=true; /** * 構建下層資料: * 構建棧頂元素的克隆,訪問狀態設為false * row下移一層,如果溢位邊界丟棄,這種情況不應該發生 * col:0->N尋找第一個合法解,如果row達到邊界count+1,否則push進棧 */ Chess chessTemp=chess.clone(); if(chessTemp.moveRow()){ while(chessTemp.moveCol()){ if( isSafety(chessTemp) ){ if( chessTemp.currentRow==N-1 ){ count++; continue; }else{ stack.push(chessTemp); continue EMPTY; } } } } } } Date end =new Date(); System.out.println("解決 " +N+ "皇后問題,用時:" +String.valueOf(end.getTime()-begin.getTime())+ "毫秒,計算結果:"+count); } private static boolean isSafety(Chess chess) { // 判斷中上、左上、右上是否安全 short step = 1; for (short i = (short) (chess.currentRow - 1); i >= 0; i--) { if (chess.chess[i] == chess.currentCol) // 中上 return false; if (chess.chess[i] == chess.currentCol - step) // 左上 return false; if (chess.chess[i] == chess.currentCol + step) // 右上 return false; step++; } return true; } } class Chess implements Cloneable{ public short[] chess; //棋盤資料 public short currentRow=0; //當前行 public short currentCol=0; //當前列 public boolean visited=false; //是否訪問過 public Chess(short[] chess){ this.chess=chess; } public boolean moveCol(){ this.currentCol++; if(this.currentCol>=chess.length) return false; else{ this.chess[currentRow]=currentCol; return true; } } public boolean moveRow(){ this.currentRow++; if(this.currentRow>=chess.length) return false; else return true; } public Chess clone() { short[] chessData=this.chess.clone(); Chess chess=new Chess(chessData); chess.currentCol=-1; chess.currentRow=this.currentRow; chess.visited=false; return chess; } }

複製程式碼

 

執行結果:

 

 

博主會繼續思考其他演算法優化方案,直至100秒跑16皇后,OK?