数据结构实践(二)——代码实现

数据结构实践(二)——代码实现

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();
            }
}

实现

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值