8皇后以及N皇后算法探究,回溯算法的JAVA实现,非递归,数据结构“栈”实现
接上一篇博客:
《8皇后以及N皇后算法探究,回溯算法的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?
保持着对万物的好奇心。即使是玩游戏,也要停下来想想这是怎么实现的。