1. 什么是稀疏数组?
-
介绍:
当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组
-
稀疏数组的处理方法是:
- 记录数组一共有几行几列,有多少个不同的值
- 把具有不同值的元素的行列及值记录在一个小规模的数组(稀疏数组)中,从而缩小程序的规模
-
作用:
主要是用来压缩数据的,在开发中也会用到,比如将二维数组的数据存到磁盘中,数据会特别多,可能还会有些意义不大的数据。这时候,选用稀疏数组就可以很大程度上在IO过程中提高效率
2. 二维数组对应的稀疏数组
-
转换示例:
-
转换规则:
-
首先看二维数组的有用信息:
5 行 5 列,8 个有效数字
第 1 个有效数字,第 1 行第 3 列
第 2 个有效数字,第 1 行第 5 列
第 3 个有效数字,第 2 行第 1 列
第 4 个有效数字,第 2 行第 4 列
第 5 个有效数字,第 3 行第 1 列
第 6 个有效数字,第 4 行第 1 列
第 7 个有效数字,第 4 行第 2 列
第 8 个有效数字,第 5 行第 3 列
-
怎么创建稀疏数组?
-
设二维数组有效数字个数为 sum
int sum = 8
-
定义稀疏数组,行数为:有效数字个数+1;列数为:3
int[][] sparseArr = new int[sum+1][3];
-
-
稀疏数组赋值规律
-
稀疏数组的3列分别表示:row(行)、col(列)和 val(值)
-
上图稀疏数组
第一行的 5 5 8表示:所转换的二维数组有5行5列,8个有效数字
第二行的 0 2 3表示:第 1 个有效数字在二维数组的第 1 行,第 3 列,值为 3
第三行的 0 4 2表示:第 2 个有效数字在二维数组的第 1 行,第 5 列,值为 2
第四行的 1 0 1表示:第 3 个有效数字在二维数组的第 2 行,第 1 列,值为 1
第五行的 1 3 4表示:第 4 个有效数字在二维数组的第 2 行,第 4 列,值为 4
第六行的 2 0 2表示:第 5 个有效数字在二维数组的第 3 行,第 1 列,值为 2
第七行的 3 0 4表示:第 6 个有效数字在二维数组的第 4 行,第 1 列,值为 4
第八行的 3 1 5表示:第 7 个有效数字在二维数组的第 4 行,第 2 列,值为 5
第九行的 4 2 1表示:第 8 个有效数字在二维数组的第 5 行,第 3 列,值为 1
-
总结一下:
稀疏数组第一行的 第一个数 = 二维数组的行数、第二个数 = 二维数组列数、第三个数 = 二维数组的有效数字个数
稀疏数组的总行数 = (二维数组有效个数+1),总列数 = 3
稀疏数组的第二行起,第一个数 = (该有效数字在二维数组中的行数-1)、第二个数 = (该有效数字在二维数组中的列数-1)、第三个数 = 该有效数字的值
-
-
3. 二维数组和稀疏数组的互相转换
- 二维数组转稀疏数组思路:
- 遍历 原始的二维数组,得到有效数据
- 根据有效数据的个数,创建稀疏数组
- 将二维数组的有效数据存入到稀疏数组中
- 稀疏数组转原始二维数组的思路
- 先读取稀疏数组的第一行,根据第一行的数据,创建原始二维数组
- 再依次读取后几行的数据,并赋给 原始二维数组 即可
4. 应用实例(代码实现)
-
实际需求:
实现二维数组与稀疏数组的互相转换
-
代码:
public class SparseArr { public static void main(String[] args) { //初始二维数组 int rowSize=11; int colSize=11; //定义一个 11*11 的棋盘(二维数组),黑棋的值为1,白旗的值为2,空白部分的值为0(默认值) int[][] chessBoard = new int[rowSize][colSize]; //棋盘的第二行第三列为黑棋(1) chessBoard[1][2]=1; //棋盘的第三行第四列为蓝棋(2) chessBoard[2][3]=2; System.out.println("这是原始的二维数组..."); //增强 for 循环遍历原始的二维数组 for (int[] rows : chessBoard) { for (int qi : rows) { System.out.print(qi+"\t"); } System.out.println(); } //获得转换后的稀疏数组 int[][] sparseArr = getSparse(chessBoard,rowSize,colSize); System.out.println("---------------------------------------------------------"); System.out.println("这是转换后的稀疏数组..."); for (int[] rows : sparseArr) { for (int qi : rows) { System.out.print(qi+"\t"); } System.out.println(); } System.out.println(); System.out.println(); System.out.println(); //模拟一个稀疏数组 int[][] arr = new int[2][3]; arr[0][0]=4; arr[0][1]=3; arr[0][2]=1; arr[1][0]=2; arr[1][1]=1; arr[1][2]=7; System.out.println("这是原始的稀疏数组..."); for (int[] rows : arr) { for (int qi : rows) { System.out.print(qi+"\t"); } System.out.println(); } System.out.println("---------------------------------------------------------"); //获得转换后的二维数组 int[][] doubleArr= getDouble(arr); System.out.println("这是转换后的二维数组..."); for (int[] rows : doubleArr) { for (int qi : rows) { System.out.print(qi+"\t"); } System.out.println(); } } /** * 将稀疏数组转换为二维数组 * @param arr 稀疏数组 * @return 返回转换后的二维数组 */ private static int[][] getDouble(int[][] arr) { //获得二维数组的行、列 int rowSize=arr[0][0]; int colSize=arr[0][1]; int[][] doubleArr = new int[rowSize][colSize]; //给二维数组赋值 for (int i = 1; i < arr.length; i++) { int row = arr[i][0]; int col = arr[i][1]; int value = arr[i][2]; doubleArr[row][col]=value; } return doubleArr; } /** * 将二维数组转换为稀疏数组 * @param chessBoard 原始二维数组 * @param rowSize 原始二维数组的行数 * @param colSize 原始二维数组的列数 * @return 返回转换后的稀疏数组 */ private static int[][] getSparse(int[][] chessBoard,int rowSize,int colSize) { //获得二维数组的有效数字个数 int sum = getSum(chessBoard); //创建稀疏数组 int[][] sparseArr = new int[sum+1][3]; //给稀疏数组第一行赋值 sparseArr[0][0]=rowSize; sparseArr[0][1]=colSize; sparseArr[0][2]=sum; //count 用于记录二维数组的有效数字,是有效数字,则 count++,也便于给稀疏数组赋值 int count = 0; //遍历二维数组,将非0的值存到稀疏数组中 for (int i = 0; i < chessBoard.length; i++) { for (int j = chessBoard[i].length - 1; j >= 0; j--) { if(chessBoard[i][j]>0){ //稀疏数组的赋值 sparseArr[++count][0]=i; sparseArr[count][1]=j; sparseArr[count][2]=chessBoard[i][j]; } } } return sparseArr; } /** * 获得二维数组的有效数字个数 * @param chessBoard 二维数组 * @return 返回有效数字个数 */ private static int getSum(int[][] chessBoard) { int sum = 0; for (int[] rows : chessBoard) { for (int qi : rows) { if(qi>0) sum++; } } return sum; } }
-
运行结果: