N皇后算法实现
共有三个类,其中一个类Stack可以由LinkedList代替
用做存放临时解的类
import java.util.LinkedList;
public class Stack<E> {
private LinkedList<E> storage = null;
public Stack() {
storage = new LinkedList<E>();
}
public int size() {
return storage.size();
}
public boolean empty() {
return storage.isEmpty();
}
/**
* LinkedList中于栈相关的源码可以看出Java官方的栈底是first,栈顶是last。
* 将对象压入栈
* */
public void push(E e) {
storage.addFirst(e);
}
/**
* 返回并删除栈顶对象
* */
public E pop() {
return storage.removeFirst();
}
/**
* 引用栈顶对象但是不删除
* */
public E top() {
return storage.getFirst();
}
/**
* 根据索引查询栈元素
* */
public E get(int index) {
return storage.get(index);
}
public String toString() {
StringBuffer sb = new StringBuffer();
int n = size();
sb.append("有效解:");
for(int i = 0 ; i < n ; i++) {
sb.append(pop().toString());
}
return sb.toString();
}
}
皇后类
public class Queen {
private int x,y;
public Queen(int x,int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public boolean equals(Queen q) {
return (this.x == q.getX()) //行冲突
|| (this.y == q.getY()) //列冲突
|| ((this.x + this.y) == (q.getX()) + q.getY()) //正对角线冲突
|| ((this.x - this.y) == (q.getX() - q.getY()));//反对角线冲突
}
@Override
public String toString() {
return "[x=" + this.x + ", y=" + this.y + "]"+",";
}
}
算法实现类
public class QueenAlgorithm {
/**
* N皇后算法
* 此版本只能找出一个解,但也因此拥有更快的效率
* */
public void placeQueens(int n) {
Stack<Queen> solu = new Stack<Queen>(); //存放(部分)解的栈
Queen q = new Queen(0,0);//从原点出发
do {
/**
* 如果冲突,回溯上一个皇后
* n <= solu.size() 表示当前已是全局解,回溯上一步尝试找到不同解
* n <= q.getY() 表示当前行无解,需要回溯上一步
* */
if(n <= q.getY()) {
q = solu.pop();
q.setY(q.getY() + 1);
} else {
//通过已有皇后比较,尝试找到下一个皇后的位置
while((q.getY() < n) && (find(solu,q))) {
q.setY(q.getY() + 1);
}
//若存在可摆位置,摆上皇后
if(q.getY() < n) {
solu.push(q);
//找到全局解,将全局解打印出来
if(n <= solu.size()) {
System.out.println(solu.toString());
}
/**
* 转入下一行,从第0列开始
* q.setX(q.getX() + 1);
* q.setY(0);
* 不能通过这种方式改变q的值,会影响栈里的Queen对象的值
* 因为q跟栈里的元素指向同一个地址
* 必须通过新建Queen对象,将q指向与栈里对象的地址.
*/
q = new Queen(q.getX() + 1, 0);
}
}
}while(q.getX() < n);//用此条件结束循环无法找到所有解
}
private boolean find(Stack<Queen> solu,Queen q) {
Queen temp;
if(!solu.empty()) { //此处判断防止在第一次尝试时访问null引发异常
for(int i = 0 ; i < solu.size() ; i++) {
temp = solu.get(i);
if(temp.equals(q)) {
return true;
}
}
}
return false;
}
}