java数据结构之稀疏数组
写在前面:
想了很久到底要不要花时间去整理一下数据结构,查了很多资料,看到各个前辈都一再强调要学好数据结构与算法,不然只有当码农的份,好吧那就学吧,毕竟不听老人言吃亏在眼前呀。
什么时候需要使用稀疏数组
首先要知道,稀疏数组他不是一种算法,而是一种特殊数据结构,是根据实际需求来使用的。
稀疏数组使用案例:
当一个数组的大部分元素为零,或者为同一个值时,可以使用稀疏数组来保存该数组,以达到缩小程序规模的效果。
由此看来,稀疏数组的很大一个用处就是节省空间。
稀疏数组的具体实例
就以这个棋盘为例,我们可以把这个棋盘看成是一个二维数组,有棋子的地方可以看成是有数据的地方,没棋子的地方可以看成是0。
就像是这样,构建成了一个二维数组,这样看起来,那些没有数值默认为零的地方显得有些多余,而且还占着存储空间,所以有没有一种方法可以将不需要的数据给去除掉?
这就可以用到稀疏数组了。
稀疏数组的样子
row | col | val |
---|---|---|
11 | 11 | 2 |
1 | 2 | 1 |
2 | 3 | 3 |
就如同上面的表格一样,是一个N行3列的数组,N的大小取决于有多少有效数据。
row:代表这个数据位于原二维数组的第几行
col:代表这个数据位于原二维数组的第几列
val:代表着这个数据值的大小
需要注意的是在稀疏数组中第一行数据保存的是原来二维数组的行列数,val 保存的有效数值的总数,之所以是这样设计是因为为了好恢复成原来的二维数组。
具体实现思路及代码
将二维数组转换成稀疏数组
具体思路:
- 遍历原始的二维数组,得到有效数据的总个数 sum
- 根据 sum 构建稀疏数组
- 将二维数组的有效数据存入到稀疏数组中
代码实现
//创建大小为 11*11 原始二维数组
int chessArray[][] = new int[11][11];
//给对应的位置赋值(用于测试,实际使用时并不知道值在那里)
//数组值为 0 则表示不是有效值
chessArray[1][2] = 1;
chessArray[2][3] = 2;
chessArray[3][4] = 6;
//打印查看对应值
System.out.println("打印原始二维数组的值:");
for(int []row: chessArray) {
for(int data: row) {
System.out.printf("%d\t",data);
}
System.out.println();
}
// sum 用于记录有效数据的总个数
int sum=0;
//1.遍历原始二维数组,得到有效数据的总个数
for(int i=0;i<11;i++) {
for(int j=0;j<11;j++) {
if(chessArray[i][j] != 0) {
sum++;
}
}
}
//查看 sum 值是否符合预期
System.out.println("总有效数据个数:"+sum);
//2.根据 sum 创建稀疏数组 sparseArr
/**
* 行数为 sum+1 是由于稀疏数组的第一行存储的数据
* 是原二维数组的大小,及有效个数的总个数
*/
int sparseArr[][] = new int[sum+1][3] ;
//给稀疏数组赋已知初值
sparseArr[0][0] = 11;
sparseArr[0][1] = 11;
sparseArr[0][2] = sum;
//3.通过遍历将二维数组的有效数据存入到 稀疏数组中
int count = 0;//用来记录稀疏数组的第一列
for(int i=0; i<11; i++){
for(int j=0; j<11; j++) {
if(chessArray[i][j] != 0) {
count++;
sparseArr[count][0] = i;
sparseArr[count][1] = j;
sparseArr[count][2] = chessArray[i][j];
}
}
}
//4.打印查看 稀疏数组对应值
System.out.println("打印稀疏数组中的值:");
for(int i=0; i<sparseArr.length; i++) {
System.out.printf("%d\t%d\t%d\t",sparseArr[i][0],sparseArr[i][1],sparseArr[i][2]);
System.out.println();
}
有时不仅需要把二维数组存储到稀疏数组中,还要会把稀疏数组中的值返还到二维数组中。
将稀疏数组转换成二维数组
具体思路:
- 先读取稀疏数组的第一行数据,因为稀疏数组的第一行存储了原始二维数组的行列数
- 再读取稀疏数组的后几行数据,并赋值给原始二维数组的对应位置即可
代码实现
//1.读取稀疏数组的第一行,根据第一行的数据创建原始的二维数组
int [][]primArray = new int[sparseArr[0][0]][sparseArr[0][1]];
//查看原始数组是否创建成功
System.out.println("原始数组:");
for(int i=0; i<11; i++) {
for(int j=0; j<11; j++) {
System.out.printf("%d\t", primArray[i][j]);
}
System.out.println();
}
//2.读取稀疏数组的后面数据,赋值给原始二维数组的对应位置
for(int i=1; i<sparseArr.length; i++) {
primArray[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];
}
//输出转化后的原始二维数组
System.out.println("转化后的二维数组:");
for(int []row: primArray) {
for(int data: row) {
System.out.printf("%d\t", data);
}
System.out.println();
}
这样就完成了从二维数组到系数数组再到二维数组的转换。
写的不对的地方,可以参看一下上面的学习链接,我也是跟着这个视频学习。
坚持者赢!!!