Java数据结构之稀疏数组和队列

稀疏数组:

应用场景,实际的需求:

编写五子棋程序中,有存档退出和保存上一句的功能。

实现:

用0代表还没有下的位置,用1代表黑子,用2代表白子。使用二维数组记录棋盘。

分析问题:

因为该二维数组的很多值默认值是0,因此记录了很多没有意义的数据->稀疏数组。

介绍:当一个数组中大部分元素为0,或者同一个值的数组时,可以使用稀疏数组来保存该数组。

稀疏数组的处理方法是:

1、记录数组一共有几行几列,有多少个不同的值。

2、把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程序的规模。

二维数组转稀疏数组的思路:

1、遍历原始的二维数组,得到有效数据个数sum

2、根据sum就可以创建稀疏数组spareseArr intsum+1

3、将二维数组的有效数据存入到稀疏数组中

棋盘的稀疏数组:
row col val
0 11 11 2
1 1 2 1
2 2 3 2

第一行代表:棋盘的大小,11*11的二维数组,有2个有效位置。

第二行代表:row代表有效位置的行,col代表有效位置的列,val代表该位置的数:

第三行代表:第二个有效数字的位置和它的值。

//稀疏数组和五子棋盘
public class test01 {
    public static void main(String[] args) {
        //创建一个原始的二维数组11*11棋盘
        //0表示该位置没有棋子,1代表白棋,2代表黑棋
        int chessArr[][] = new int[11][11];
        //代表该棋盘第二行第三列含有一颗白棋
        chessArr[1][2] = 1;
        //代表该棋盘第三行第三列含有一颗黑棋
        chessArr[2][3] = 2;
        System.out.println("原始的二维数组~~");
        for(int row[]:chessArr) {
            for(int data: row) {
                System.out.printf("%d\t",data);
            }
            System.out.println();
        }
        //将二维数组转化成稀疏数组的思想
        //先遍历二维数组,获得非0数据的个数
        int sum = 0;
        for(int i =0 ; i < 11 ; i++) {
            for(int j = 0 ; j < 11 ; j++) {
                if(chessArr[i][j] != 0) {
                    sum++;
                }
            }
        }
        System.out.println("原始二维数组的有效数字个数"+sum);
        //创建稀疏数组,遍历原始二维数组的数据,存入稀疏数组中
        int xishuArr[][] = new int[sum+1][3];
        //存入稀疏数组的第一行
        xishuArr[0][0] = 11;
        xishuArr[0][1] = 11;
        xishuArr[0][2] = sum;
        int count = 0;
        for(int i =0 ; i < 11 ; i++) {
            for(int j = 0 ; j < 11 ; j++) {
                if(chessArr[i][j] != 0) {
                    count++;
                    //有效数据从稀疏数组的第二行开始存放
                    xishuArr[count][0] = i;
                    xishuArr[count][1] = j;
                    xishuArr[count][2] = chessArr[i][j];
                }
            }
        }
        //输出稀疏数组
        for(int chess[]:xishuArr) {
            for(int a:chess) {
                System.out.printf("%d\t",a);
            }
            System.out.println();
        }
        /*  稀疏数组转二维数组的思路:
            1、先读取稀疏数组的第一行,根据第一行的数据,创建原始的二维数组。
            2、再读取稀疏数组后几行数据,并赋予原始二维数组即可。
        */
        int chessArr2[][] = new int[xishuArr[0][0]][xishuArr[0][1]];
        //注意这里的xishuArr.length计算的就是稀疏数组的行数
        for(int i=1;i

循环队列

介绍

​ 队列是一个有序列表,可以用数组或是链表来实现。

​ 遵循先入先出的原则。先存入的队列的数据,要先取出,后存入的要后取出。

数组模拟队列:

​ 因为队列的输出,输入分别是从前后端来处理,因此需要两个变量front以及rear分别记录队列前后端的下标,front会随着数据输出而改变,而rear则使随着数据输入而改变。注意先存先取原则。

循环队列思路分析:

​ 注意循环队列是为了区分队列是否为空,是否为满,做了一个解决办法,将循环队列的空间空出一个位置。

队列为空的判断条件是:rear=front。

队列为满的判断条件是:(rear+1)%maxSize = front

以下是百度百科给出的解释:

  • 在循环队列中,当队列为空时,有front=rear,而当所有队列空间全占满时,也有front=rear。为了区别这两种情况,规定循环队列最多只能有MaxSize-1个队列元素,当循环队列中只剩下一个空存储单元时,队列就已经满了。因此,队列判空的条件是front=rear,而队列判满的条件是front=(rear+1)%MaxSize。

代码实现:

package queue;

import java.util.Scanner;

public class CircleArrayQueue {

    public static void main(String[] args) {
        // 测试
        System.out.println("测试数组环形队列~~");
        CircleArray queue = new CircleArray(4); //设置值为4,其队列的有效数据最大为3,原因已经在上面讲过了。
        char key = ' ';//接受用户的输入
        Scanner scanner =  new Scanner(System.in);
        boolean loop = true;
        while(loop) {
            System.out.println("s(show):显示队列");
            System.out.println("e(exit):显示队列");
            System.out.println("a(add):添加数据");
            System.out.println("g(git):获取数据");
            System.out.println("h(head):显示队列头部");
            key = scanner.next().charAt(0);
            switch (key) {
            case 's':
                    queue.showQueue();
                    break;
            case 'a':
                    System.out.println("输入一个数");
                    int value = scanner.nextInt();
                    queue.addQueue(value);
                    break;
            case 'g'://取出数据
                    try {
                        int res = queue.getQueue();
                        System.out.printf("取出的数据是%d\n",res);
                    } catch (Exception e) {
                        // TODO: handle exception
                        System.out.println(e.getMessage());
                    }
                break;
            case 'h'://查看队列头的数据 
                try {
                    int res = queue.headQueue();
                    System.out.printf("取出的数据是%d\n",res);
                } catch (Exception e) {
                    System.out.println(e.getMessage());
                }
                
                break;
            case 'e':
                scanner.close();
                loop =false;
                break;
            default:
                break;
            }
        }
        System.out.println("程序退出~~");
    }

}
class CircleArray{
    private int maxSize;        //表示数组的最大容量
    private int front;          //队列头
    private int rear;           //队列尾
    private int[] arr;          //该数组用于存放数据,模拟队列
    
    //构造器
    public CircleArray(int arrMaxsize) {
        maxSize = arrMaxsize;
        arr = new int[maxSize];
    }
    
    //判断队列是否满
    public Boolean isFull() {
        return (rear+1) % maxSize == front;
    }
    
    //判断队列是否为空
    public Boolean isEmpty() {
        return rear == front;
    }
    
    //添加数据
    public void addQueue(int n) {
        //判断队列是否为满
        if(isFull()) {
            System.out.println("队列已满,无法添加~~");
            return;
        }
        //将数据加入
        arr[rear] = n;
        //将rear后移,这里必须考虑取模
        rear = (rear+1)%maxSize;
    }
    
    //获取队列的数据
    public int getQueue(){
        //先判断队列是否为空
        if(isEmpty()) {
            //通过抛出异常来处理
            throw new RuntimeException("队列为空,不能取数据~~");
            //这里不能写return,throw已经终止了程序。
        }
        /* 
         * 这里需要分析出front是指向队列的第一个元素
         * 1、先把front对应的值保留到一个临时变量中
         * 2、将front后移考虑取模
         * 3、将临时保存的变量返回
         */
         int value = arr[front];
         front = (front+1)%maxSize;
         return value;
    }
    
    //显示队列的所有数据
    public void showQueue() {
        //先判断是否为空
        if(isEmpty()) {
            System.out.println("队列是空的,无法输出~~");
            return;
        }
        /*
         * 思路:从front开始遍历了,遍历多少元素
         */
        for(int i = front;i < front+size();i++) {
            System.out.printf("arr[%d]=%d\n",i%maxSize,arr[i%maxSize]);
        }
    }
    
    //求出当前队列有效数据的个数
    public int size() {
        //这里再加上一个maxSize的原因就是怕rear比front小的情况
        return (rear+maxSize-front) % maxSize;
    }
    
    //显示队列的头部
    public int headQueue() {
        //判断是否为空
        if(isEmpty()) {
            throw new RuntimeException("队列时空的,无法输出~~");
        }
        return arr[front];
    }
}

你可能感兴趣的:(Java数据结构之稀疏数组和队列)