数据结构-稀疏数组& 环形队列

数据结构

  • 数据结构分为2种, 线性结构和非线性结构
  • 线性结构
    (1) 数据元素之间是一对一的线性关系. 常见有数组, 队列, 链表和栈等
    (2) 存储结构有两种:
  1. 顺序存储结构: 顺序存储的线性表称为顺序表, 顺序表中的存储元素是连续的
  2. 链式存储结构: 链式存储的线性表称为链表, 链表中的存储元素不一定是连续的(元素节点中存放的数据包括:元素和相邻元素的地址), 所以链式存储结构可以利用内存碎片空间来存储数据
  • 非线性结构
    (-) 数据元素之间不是一对一的关系. 常见有二维数组, 多维数组, 广义表, 树结构, 图结构等

稀疏数组(Sparse Array)

  • 当一个数组中大部分元素为0或者同一个相同的值时, 便可以使用稀疏数组
  • 稀疏数组的元素结构:
  1. 记录指定数组一共有几行几列及有多少个不同的值(有效值)
  2. 将具有不同值的元素的行列及值记录在一个小规模的数组中, 从而缩小数据来达到压缩的目的(压缩后的数据可用于存取等功能)
  • 二维数组(原始数据)转换稀疏数组的思路:
  1. 遍历原数组, 获取有效值个数 sum
  2. 根据 sum, 锁定稀疏数组的行数 int sparseArr[][] = new int[sum + 1][3]; 其中+1是因为多一行用于记录原数组的行列及有效值个数
  3. 将有效值存到稀疏数组
  • 稀疏数组转换原数组的思路:
  1. 读取稀疏数组的第一行, 创建原数组 int[][] chessArr2 = new int[sparseArr[0][0]][sparseArr[0][1]];
  2. 再将稀疏数组的其它数据, 赋值给原数组 chessArr2
  • 实例代码:

public class SparseArrayApp {
    public static void main(String[] args) {
        /** 锁定原数组的行数与列数*/
        int rows = 4;
        int columns = 5;

        /** 创建二维数组(原始数据)*/
        int[][] chessArray1 = new int[rows][columns];
        /** 原数据, 插入几个有效值*/
        chessArray1[1][1] = 1;
        chessArray1[1][2] = 2;
        chessArray1[2][2] = 4;
        /** 输出原数组*/
        System.out.println("原数组:");
        for (int[] row : chessArray1) {
            for (int data : row) {
                System.out.print(data + " ");
            }
            System.out.println();
        }

        /** 1. 遍历原数组, 获取有效值个数 sum*/
        int sum = 0;
        for (int i = 0; i < chessArray1.length; i++) {
            for (int j = 0; j < chessArray1[i].length; j++) {
                if (chessArray1[i][j] != 0) {
                    sum++;
                }
            }
        }
        System.out.println("有效值个数: " + sum);
        System.out.println();

        /** 2. 根据 sum, 创建稀疏数组*/
        int sparseArr[][] = new int[sum + 1][3];
        /** 第一行设定原数组的行数列数及有效值个数*/
        sparseArr[0][0] = rows;
        sparseArr[0][1] = columns;
        sparseArr[0][2] = sum;
        /** 遍历二维数组,将非0的值存放到稀疏数组中*/
        int count = 0;
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < columns; j++) {
                if (chessArray1[i][j] != 0) {
                    count++;
                    sparseArr[count][0] = i;
                    sparseArr[count][1] = j;
                    sparseArr[count][2] = chessArray1[i][j];
                }
            }
        }
        /** 输出稀疏数组的存储形式*/
        System.out.println("稀疏数组:");
        for (int i = 0; i < sparseArr.length; i++) {
            System.out.printf("%d\t%d\t%d\t\n", sparseArr[i][0], sparseArr[i][1], sparseArr[i][2]);
        }

        /** 稀疏数组转换原数组*/
        /** 1. 读取稀疏数组的第一行, 创建原数组*/
        int[][] chessArr2 = new int[sparseArr[0][0]][sparseArr[0][1]];
        /** 2. 再将稀疏数组的其它数据, 赋值给原数组 chessArr2*/
        for (int i = 1; i < sparseArr.length; i++) {
            chessArr2[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];
        }
        /** 输出新创建的原数组 chessArr2*/
        System.out.println();
        System.out.println("新的原数组:");
        for (int[] row : chessArr2) {
            for (int data : row) {
                System.out.print(data + " ");
            }
            System.out.println();
        }
    }

}
> 原数组:
> 0 0 0 0 0 
> 0 1 2 0 0 
> 0 0 4 0 0 
> 0 0 0 0 0 
> 有效值个数: 3
> 
> 稀疏数组:
> 4	5	3	
> 1	1	1	
> 1	2	2	
> 2	2	4	
> 
> 新的原数组:
> 0 0 0 0 0 
> 0 1 2 0 0 
> 0 0 4 0 0 
> 0 0 0 0 0 

环形队列(CircularQueue)

  • 遵循先入先出的原则, 所谓环形意思为用过的元素可以重复使用
  1. front指向队列的第一个元素, 初始值为0
  2. rear指向队列的最后一个元素的后一个位置, 此元素不为存值. rear的初始值为0
  3. 队列满的条件: (rear + 1) % maxSize == front
  4. 队列空的条件: rear == front
  5. 队列中的有效数据个数: (rear + maxSize - front) % maxSize
  • 实例代码:

public class CircularQueueApp {
    public static void main(String[] args) {
        System.out.println("s(show): 显示队列");
        System.out.println("e(exit): 退出队列");
        System.out.println("a(add): 添加数据到队列");
        System.out.println("g(get): 从队列中取出数据");
        System.out.println("h(head): 查看队列头的数据");
        /** 创建长度为3的环形队列*/
        CircularQueue circularQueue = new CircularQueue(3);
        Scanner sc = new Scanner(System.in);
        boolean bLoop = true;
        while (bLoop) {
            String next = sc.next();
            switch (next) {
                case "s":
                    circularQueue.showQueue();
                    break;
                case "a":
                    System.out.println("请输入一个数值");
                    int i = sc.nextInt();
                    circularQueue.addQueue(i);
                    break;
                case "g":
                    try {
                        int res = circularQueue.removeQueue();
                        System.out.println("取出的数据是 " + res);
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case "h":
                    try {
                        int res = circularQueue.headQueue();
                        System.out.println("队列头数据是 " + res);
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case "e":
                    sc.close();
                    bLoop = false;
                    break;
            }
        }
        System.out.println("程序退出");
    }
}

class CircularQueue {
    private int front;
    private int rear;
    private int maxSize;
    private int arr[];

    public CircularQueue(int maxSize) {
        this.maxSize = maxSize;
        arr = new int[maxSize];
    }

    public boolean isFull() {
        return (rear + 1) % maxSize == front;
    }

    public boolean isEmpty() {
        return rear == front;
    }

    public void addQueue(int value) {
        if (isFull()) {
            System.out.println("队列为满,不能添加");
            return;
        }
        arr[rear] = value;
        rear = (rear + 1) % maxSize;
    }

    public int removeQueue() throws Exception {
        if (isEmpty()) {
            throw new Exception("队列为空,没有可以取的数据");
        }
        int value = arr[front];
        front = (front + 1) % maxSize;
        return value;
    }

    public void showQueue() {
        if (isEmpty()) {
            System.out.println("队列为空, 没有数据");
        }
        int len = front + ((rear + maxSize - front) % maxSize);
        for (int i = front; i < len; i++) {
            System.out.printf("arr[%d]=%d\n", i % maxSize, arr[i % maxSize]);
        }
    }

    public int headQueue() throws Exception {
        if (isEmpty()) {
            throw new Exception("队列为空, 没有数据");
        }
        return arr[front];
    }

}

如果您觉得有帮助,欢迎点赞哦 ~ 谢谢!!

猜你喜欢

转载自blog.csdn.net/qcl108/article/details/108986177