概述
稀疏数组是指那些零元个数远大于非零元个数的数组,而稀疏数组的零元分布往往没有规律可循。最经典的例子就是棋盘,在保存棋局时,棋盘上棋子的数目往往不会布满整个棋盘。以中国象棋为例,棋盘为10*9,而棋子数为32,而且在走棋过程中还会减少棋子数。所以如果用整个数组来保存棋盘就会花费太多空间。这时就要对稀疏数组进行压缩存储。
压缩存储的处理方法是:
1. 创建一个小规模的二维数组,其列数为3,分别记录行、列、值。
2. 第一行记录原数组的行数、列数,以及非零元个数。
3. 之后每一行记录每一个非零元在原数组中的行位标、列位标和值。
以这个棋盘为例:

用两位数表示一个棋子:
1. 个位数:1表示兵、卒;2表示炮、砲;3表示车;4表示马;5表示相、象;6表示仕、士;7表示帅、将。
2. 十位数:1表示红方;2表示黑方。
比如,黑方用2表示,将用7表示,所以黑方的将用27表示;红方用1表示,兵用1表示,所以红方的兵用11表示。
用一个10*9的二维数组存储棋盘,则这个棋盘可以表示为:

即二维数组board中,board[1][3]=27,board[1][4]=26,board[1][5]=11,board[2][2]=11,board[2][5]=26,board[8][4]=17。
对该二维数组进行压缩:
1. 一共需要存储6个棋子,所以压缩后数组为sparseBoard[7][3]。
2. 第一行存储二维数组的行数、列数和棋子数,即sparseBoard[0]=10,sparseBoard[1]=9,sparseBoard[2]=6。
3. 之后6条记录分别存取棋子。
最终得到的结果为:

代码实现
压缩稀疏数组:

1 public static int[][] compress(int[][] arr) {
2 if (arr == null) return null;
3 // 行数
4 int m = arr.length;
5 // 列数
6 int n = arr[0].length;
7 // 非零元个数
8 int num = 0;
9 for (int i = 0; i < m; i++) {
10 for (int j = 0; j < n; j++) {
11 if (arr[i][j] != 0) {
12 num++;
13 }
14 }
15 }
16 // 创建压缩后的数组,列数为3,行数为1+非零元个数
17 int[][] cArr = new int[1 + num][3];
18 // 第一行记录原数组的行数、列数,以及非零元个数
19 cArr[0][0] = m;
20 cArr[0][1] = n;
21 cArr[0][2] = num;
22 // 每一行记录每一个非零元在原数组中的行位标、列位标和值
23 for (int i = 0, k = 1; i < m; i++) {
24 for (int j = 0; j < n; j++) {
25 if (arr[i][j] != 0) {
26 cArr[k][0] = i;
27 cArr[k][1] = j;
28 cArr[k][2] = arr[i][j];
29 k++;
30 }
31 }
32 }
33 return cArr;
34 }
将压缩后的数组还原为稀疏数组:

1 public static int[][] recovery(int[][] cArr) {
2 if (cArr == null || cArr[0].length != 3) return null;
3 // 第一行的前两个单元存储了原二维数组的行数和列数
4 int[][] arr = new int[cArr[0][0]][cArr[0][1]];
5 // 将除第一行外每一行还原到二维数组中,每一行的前两个单元为行位标和列位标,第三个单元为元素值
6 for (int i = 1; i <= cArr[0][2]; i++) {
7 arr[cArr[i][0]][cArr[i][1]] = cArr[i][2];
8 }
9 return arr;
10 }
测试:



来源:https://www.cnblogs.com/lqkStudy/p/11505790.html
