8皇后以及N皇后算法探究,回溯算法的JAVA實現,非遞歸,數據結構「棧」實現

接上一篇博客:html

8皇后以及N皇后算法探究,回溯算法的JAVA實現,遞歸方案java

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

可是算法效率仍然差強人意,由於使用遞歸函數的緣故安全

下面提供另外一種回溯算法的實現,使用數據結構」棧「來模擬,遞歸函數的手工實現,由於咱們知道計算機在處理遞歸時的本質就是棧數據結構

時間複雜度是同樣的,空間複雜度由於自定義了class,有所上升函數

通過測試其性能甚至低於上篇博客的遞歸實現性能

權當是使用數據結構」棧「,解決15皇后的代碼以下:測試

 

package com.newflypig.eightqueen;

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

/**
 * 使用數據結構「棧」,模擬遞歸函數
 * 實現非遞歸方案的回溯算法
 * @author newflydd@189.cn
 * 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?this

相關文章
相關標籤/搜索