数据结构实践(二)——代码实现
A*算法实现九宫重排
astar算法实现类
用于定义结点运动产生的效果以及将open表以及close表的使用
代码:`
/**
* @author 莉莉安
* @ClassName: IntelliJ IDEA
* @Description: ${TODO}
* @date 2021/3/10 13:35
* ${tags}
*/
import java.util.*;
public class Astar {
private Eight First;
private Eight goal;
private List<Eight> open=new ArrayList<>();//open与close表
private List<Eight>close=new ArrayList<>();
int x,y;
/**
* 构造函数并于用户交互
*/
public Astar(){
Scanner scanner=new Scanner(System.in);
System.out.println("请输入初始九宫格:");
int [][]first=new int[3][3];
int [][]goal=new int[3][3];
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
{
int t;
t=scanner.nextInt();
if(t>=10||t<0)
{
System.out.println("输入无效");
return;
}
first[i][j]=t;
}
System.out.println("请输入目标九宫格:");
for(int i=0;i<3;i++)
for (int j = 0; j < 3; j++)
{
int s;
s=scanner.nextInt();
if(s>=10||s<0)
{
System.out.println("输入无效");
return;
}
goal[i][j]=s;
}
this.First=new Eight(first,0,null);
this.goal=new Eight(goal,0,null);
}
/**
* 执行方法
*/
public void astar(){
open.add(First);
Eight p=null;
while(open!=null){
p=open.get(0);
if(Equal(p, goal))
break;
open.remove(0);
close.add(p);
addState(p);
sort();
}
if(Equal(p, goal)){
List<Eight>father=new ArrayList<>();
while(p.getParent()!=null){
father.add(p);
p=p.getParent();
}
System.out.println("运行步骤:");
for(int i=father.size()-1;i>=0;i--){
System.out.println(father.size()-i+":");
show(father.get(i));
}
}
}
/**
* 空格移动并加入open表
* @param p
*/
public void addState(Eight p){
Eight q;
int [][]a;
//对上移操作
a=new int[3][3];
for(int i=0;i<p.getCurrentstate().length;i++){
for(int j=0;j<p.getCurrentstate()[i].length;j++){
a[i][j]=p.getCurrentstate()[i][j];
}
}
getblank(p);
if(x-1>=0){
int tmp=a[x][y];
a[x][y]=a[x-1][y];
a[x-1][y]=tmp;
q=new Eight(a,p.getH()+1,p);
if(!chongfu(q)){
q.setF(geth(q,goal));
open.add(q);
}
}
//对下移操作
a=new int[3][3];
for(int i=0;i<p.getCurrentstate().length;i++){
for(int j=0;j<p.getCurrentstate()[i].length;j++){
a[i][j]=p.getCurrentstate()[i][j];
}
}
getblank(p);
if(x+1<=2){
int tmp=a[x][y];
a[x][y]=a[x+1][y];
a[x+1][y]=tmp;
q=new Eight(a,p.getH()+1,p);
if(!chongfu(q)){
q.setF(geth(q,goal));
open.add(q);
}
}
//对左移操作
a=new int[3][3];
for(int i=0;i<p.getCurrentstate().length;i++){
for(int j=0;j<p.getCurrentstate()[i].length;j++){
a[i][j]=p.getCurrentstate()[i][j];
}
}
getblank(p);
if(y-1>=0){
int tmp=a[x][y];
a[x][y]=a[x][y-1];
a[x][y-1]=tmp;
q=new Eight(a,p.getH()+1,p);
if(!chongfu(q)){
q.setF(geth(q,goal));
open.add(q);
}
}
//对右移操作
a=new int[3][3];
for(int i=0;i<p.getCurrentstate().length;i++){
for(int j=0;j<p.getCurrentstate()[i].length;j++){
a[i][j]=p.getCurrentstate()[i][j];
}
}
getblank(p);
if(y+1<=2){
int tmp=a[x][y];
a[x][y]=a[x][y+1];
a[x][y+1]=tmp;
q=new Eight(a,p.getH()+1,p);
if(!chongfu(q)){
q.setF(geth(q,goal));
open.add(q);
}
}
}
/**
* 计算代价即不在位个数
* @param p
* @param q
* @return
*/
public int geth(Eight p, Eight q){//计算H值
int num=0;
for(int i = 0; i<p.getCurrentstate().length; i++){
for(int j = 0; j<p.getCurrentstate()[i].length; j++){
if(p.getCurrentstate()[i][j]!=q.getCurrentstate()[i][j])
num++;
}
}
return num;
}
/**
* 判断节点是否相等
* @param p
* @param q
* @return
*/
public boolean Equal(Eight p, Eight q){
for(int i = 0; i<p.getCurrentstate().length; i++){
for(int j = 0; j<p.getCurrentstate()[i].length; j++){
if(p.getCurrentstate()[i][j]!=q.getCurrentstate()[i][j])
return false;
}
}
return true;
}
/**
* 获取空格位置
* @param p
*/
public void getblank(Eight p){
for(int i = 0; i<p.getCurrentstate().length; i++){
for(int j = 0; j<p.getCurrentstate()[i].length; j++){
if(p.getCurrentstate()[i][j]==0){
x=i;y=j;
}
}
}
}
/**
* 希尔排序
*/
public void sort(){
Eight t;
// 空链表 或 只有一个元素的链表,则什么都不做。
if (open == null || open.size() <= 1) return;
// 定义希尔增量。
for (int gap = open.size() / 2; gap > 0; gap /= 2) {
for (int i = gap; i < open.size(); i++) {
for (int j = i - gap; j >= 0; j -= gap) {
if (open.get(j).getF() > open.get(j + gap).getF()) {
t = open.get(j);
open.set(j, open.get(j + gap));
open.set(j + gap, t);
}
}
}
}
}
/**
* 判断是否重复即是否到过此状态
* @param p
* @return
*/
public boolean chongfu(Eight p){
for(int i=0;i<close.size();i++){
if(Equal(p,close.get(i)))
return true;
}
return false;
}
/**
* 以九宫格形式输出
* @param p
*/
public void show(Eight p){
for(int i = 0; i<p.getCurrentstate().length; i++){
for(int j = 0; j<p.getCurrentstate()[i].length; j++){
System.out.print(p.getCurrentstate()[i][j]+" ");
}
System.out.println();
}
}
}
结点类
定义结点内容包括父节点和当前状态
代码::
/**
* @author 莉莉安
* @ClassName: IntelliJ IDEA
* @Description: ${TODO}
* @date 2021/3/10 13:35
* ${tags}
*/
public class Eight {
private int[][] currentstate;//当前九宫格状态
private int f;//总价值函数
private int h;//不在位数
private Eight parent;//父节点便于输出时的查找
public Eight(int [][] currentstate, int h, Eight parent){
this.currentstate = currentstate;
this.h=h;
this.parent=parent;
}
public int getF() {
return f;
}
public void setF(int g) {
this.f=g+h;
}
public int[][] getCurrentstate() {
return currentstate;
}
public void setCurrentstate(int[][] currentstate) {
this.currentstate = currentstate;
}
public Eight getParent() {
return parent;
}
public void setParent(Eight parent) {
this.parent = parent;
}
public int getH() {
return h;
}
public void setH(int h) {
this.h = h;
}
}
测试类
代码:
/**
* @author 莉莉安
* @ClassName: IntelliJ IDEA
* @Description: ${TODO}
* @date 2021/3/10 13:34
* ${tags}
*/
/**
* 主类
*/
public class Test {
public static void main(String[] args) {
Astar a =new Astar();
a.astar();
}
}