Java 数据结构总结:一

  当我们使用计算机来解决问题时,一般需要这几个步骤:首先从该具体问题抽象出一个数学模型,然后设计或者选择一个解决此数学模型的算法,然后编写出程序进行调试、测试,直到得到最终的解答。这是是将数学思维用计算机实现的一个普遍逻辑,然而,随着计算机的发展,并非所有的问题都可以用简单的数学方程式解决。因此,解决这类问题的关键不再是数学分析和计算方法,而是要设计出合适的数据结构,才能有效解决此类问题。

  下面来一个具体问题体现数据结构的重要作用:

  用运回溯算法求解八皇后问题,该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。

方法一: 定义皇后位置类来处理皇后位置数据的实现方式;

解题思路:已在代码中注明。

package algorithm;

import java.util.LinkedList;

/**
 *   回溯算法:八皇后问题
 *       该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:
 *   在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
 */
public class EightQueen {
    private static final int SIZE = 8;  //皇后的个数,此处设置8,表示8个皇后
    private static int count = 0;  //记录摆放的方式数

    /**
     *     定义位置的数列结构,用于表示皇后的摆放位置
     *
     */
    static class Location {
        int x;  //对应棋盘的列
        int y;  //对应棋盘的行

        Location(int x, int y) {
            this.x = x;
            this.y = y;
        }

        @Override
        public String toString() {
            return "(" + x + "," + y +")";
        }
    }
    /**
     *     主要回溯法函数
     * @param list
     * @param x    //对应棋盘的列
     * @param y    //对应棋盘的行
     */
    private static void eightQueen(LinkedList<Location> list, int x, int y) {
        if(list.size() == SIZE) {  //当list元素个数为8时,表示8个皇后都摆放完毕,打印后即可退出函数。
            printLocation(list);    //打印皇后摆放方式
            return ;
        }
        for (int i = x; i < SIZE; i++) {
            Location loc = new Location(i,y);
            if(isLegalLoc(list,loc)) {
                list.offer(loc);  //将第y行的皇后摆放好
                eightQueen(list,0,y+1);   //开始摆放y+1行的皇后,同样从第0列开始摆放
                list.pollLast();  //每次摆放完一个皇后后,都要将其撤回,再试探其它的摆法。(pollLast() 获取并移除此列表的最后一个元素)
            }
        }

    }
    /**
     * 判断位置为loc的皇后是否合法
     * @param list
     * @param loc
     * @return
     */
    private static boolean isLegalLoc(LinkedList<Location> list, Location loc) {
        for (Location each : list) {
            if(loc.x == each.x || loc.y == each.y) {  //判断是否在同一行或同一列
                return false;
            }else if(Math.abs(loc.x - each.x) == Math.abs(loc.y - each.y)) {  //判断是否在同一对角线或反对角线上
                return false;
            }
        }
        return true;
    }
    /**
     * 打印皇后摆放位置方式
     * @param list
     */
    private static void printLocation(LinkedList<Location> list) {
        for (Location each : list) {
            System.out.print(each.toString()+"	");
        }
        System.out.println();
        count ++;
    }

    public static void main (String[] args) {
        LinkedList<Location> list = new LinkedList<Location>();
        eightQueen(list,0,0);  //从棋盘的第0行第0列开始
        System.out.println("八皇后共有"+count+"种摆放方式");
    }
}

方法二: 以一维数组的方式来处理皇后位置数据的实现方式;

解题思路:已在代码中注明。

package algorithm;
/**
 * 回溯算法:八皇后问题
 * @author 86135
 *
 */
public class EightQueen2 {
    public static int num = 0;  //累计方案
    public static final int MAXQUEEN = 8;
    public static int[] cols = new int[MAXQUEEN];  //定义数组,表示8列棋子皇后摆放的位置

    /**
     * @param n 表示填第n列的皇后
     * */
    public void getCount(int n){
        boolean[] rows = new boolean[MAXQUEEN];

        for(int i = 0;i < n;i++){
            rows[cols[i]] = true;

            int d = n - i;  //计算差值

            //正斜方向
            if(cols[i] - d >= 0){
                rows[cols[i]- d] = true;
            }

            //反斜方向
            if(cols[i] + d <= (MAXQUEEN - 1)){
                rows[cols[i] + d] = true;
            }
        }

        for(int i = 0;i < MAXQUEEN;i++){
            if(rows[i]){
                continue;
            }
            cols[n] = i;

            if(n < MAXQUEEN - 1){
                getCount(n + 1);
            }else{
                //找到一套完整的方案
                num++;
                printQueen();
            }
        }
    }

    public void printQueen(){
        System.out.println("第" + num + "种方案");
        for(int i = 0;i < MAXQUEEN;i++){
            for(int j = 0;j < MAXQUEEN;j++){
                if(i == cols[j])
                    System.out.print("Q ");
                else
                    System.out.print("+ ");
            }
            System.out.println();
        }
    }

    public static void main(String[] args){
        EightQueen2 q = new EightQueen2();
        q.getCount(0);
    }

}

方法三: 以二维数组的方式来处理皇后位置数据的实现方式;

解题思路:由上往下依次向下遍历,那么我们只需要验证当前格子的上方,左斜上方和右斜上方的位置是否有皇后(因为如果由上往下遍历的时候,在当前行的下方是一定没有皇后的,所以我们只需要验证三个方向),如过三个方向都没有皇后,那么就可以确定当前位置可以放皇后

package algorithm;
/**
 *     回溯算法:八皇后问题
 * 
 *     解题思路:由上往下依次向下遍历,那么我们只需要验证当前格子的上方,左斜上方和右斜上方的位置是否有皇后
 *     (因为如果由上往下遍历的时候,在当前行的下方是一定没有皇后的,所以我们只需要验证三个方向),
 *     如过三个方向都没有皇后,那么就可以确定当前位置可以放皇后
 * @author 86135
 *
 */
public class EightQueen3 {
    //定义 8*8 矩阵(二维数组)
    public static int[][] map = new int[8][8];
    public static int count = 1;
    /**
     *     显示棋盘
     */
    public static void show() {
        System.out.println("第"+count+"中排列方式");
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 8; j++) {
                System.out.print(map[i][j] +" ");
            }
            System.out.println();
        }
        count++ ;
    }
    /**
     *     检验方法(验证该位置是否可以放皇后)
     * @param row
     * @param col
     * @return
     */
    public static boolean check(int row,int col) {
        //上面(行减小  列不变)
        for (int i = row-1; i >= 0; i--) {
            if(map[i][col] == 1) {
                return false;
            }
        }
        //左斜上 (行减小  列减小)
        for (int i = row-1,j = col-1; i >= 0 && j >= 0; i--,j--) {
            if (map[i][j] == 1) {
                return false;
            }
        }
        //右斜上 (行减小  列增加)
        for (int i = row-1,j = col+1; i >= 0 && j < 8; i--,j++) {
            if (map[i][j] == 1) {
                return false;
            }
        }
        return true;
    }
    /**
     * 皇后排列方法
     * @param row
     */
    public static void play(int row) {
        //遍历当前行的所有单元格
        for (int i = 0; i < 8; i++) {
            //判断本格是否可以放皇后
            if(check(row,i)) {
                map[row][i] = 1;
                //判断是否为最后一行
                if(row == 7) {
                    show();
                }else {
                    //接着走下一步
                    play(row + 1);
                }

                //取消当前落子  清空棋盘
                map[row][i] = 0;
            }

        }
    }
    public static void main(String[] args) {
        play(0);
    }
}
原文地址:https://www.cnblogs.com/zhaoKeju-bokeyuan/p/12157455.html