Java数据结构与算法1 稀疏数组

稀疏数组及其应用举例

假设我们有这样一个需求,对于一个10x7的棋盘(如下图),我们需要存储每个棋子的具体坐标位置信息,尽可能少的占用内存。如果不采用稀疏数组的存储方式,那么我们需要一个int[10][8] 的内存空间约10x8x4 共320个字节。为了尽可能的减少存储空间,我们采用稀疏数组的方式来存储必要的信息即可。
在这里插入图片描述
采用的稀疏数组形如以下的格式:

行数 列数 需要记录的个数n
行1 列1 值1
行2 列2 值2
行n 列n 值n

这里,需要记录的个数代表有棋子的地方的个数。对于一个稀疏矩阵,需要记录的个数则是矩阵中非零元素(或其他指定的数值)的个数。稀疏矩阵指的是矩阵中大多数值都相同,对于这样的矩阵,我们只需要以稀疏数组的形式记录矩阵中不同的值,就可以大大的节省存储空间,特别是对于超大型矩阵。

一个很简单的例子,对于上图的棋盘,我们可以将其转换为以下的稀疏矩阵。我们用0代表大多数没有棋子的地方,用1代表白棋,用2代表黑棋。

10 8 11
2 2 1
2 5 1
2 7 1
4 4 1
6 2 1
6 5 1
6 7 2
8 2 2
8 5 2
9 4 2
9 7 2

以上,我们用了一个int[n+1][3]的稀疏数组,这里n=11。共占用约11x3x4 = 132个字节。相比非稀疏存储(320字节),大大节省了存储空间。
下面,我们考虑一个原始的二维数组对应稀疏数组 的相互转换。

二维数组->稀疏数组

根据以上棋盘数组的分析,我们很容易的知道需要以下转换步骤:

  1. 遍历原二维数组得到需要记录的非零元素个数N
  2. 根据得到的N来分配需要返回的稀疏数组的空间为int[N+1][3]
  3. 再次遍历原二维数组,对于非零元素,记录对应的行,列,值并存储到稀疏数组中。

Java代码

package com.like.java.data_structure.sparseArray;

// 原始二维数组转化为稀疏数组
public class Raw2Sparse {
	
	/**
	 * 
	 * @param rawArr 原始的二维数组
	 * @return sparseArr 对应的稀疏数组
	 */
	public static int[][] transfer(int [][] rawArr)
	{
		// 记录非零元素个数
		int count = 0;
		// 1. 遍历得到非零元素个数
		for(int[] eachRow: rawArr)
		{
			for(int val:eachRow)
			{
				if(val != 0)
				{
					count ++;
				}
			}
		}
		// 2. 为稀疏数组分配内存空间
		int[][] sparseArr = new int[count+1][3];
		sparseArr[0][0] = rawArr.length;
		sparseArr[0][1] = rawArr[0].length;
		sparseArr[0][2] = count;
		// 3. 再次遍历非零元素并记录到稀疏数组
		int n = 0;
		for(int i=0;i<rawArr.length;i++)
		{
			for(int j=0;j<rawArr[0].length;j++)
			{
				if(rawArr[i][j] !=0)
				{
					n ++;
					sparseArr[n][0] = i;
					sparseArr[n][1] = j;
					sparseArr[n][2] = rawArr[i][j];
				}
			}
		}
		
		return sparseArr;
	}
}

稀疏数组->原始二维数组

  1. 读取稀疏数组的第一行,获取原始二维数组的行数rowCount,列数colCount,非零元素个数
  2. 为原始的二维数组分配内存空间 rawArr = int[rowCount][colCount]
  3. 遍历稀疏数组剩余的记录,对应存储到rawArr 中。
    Java代码
package com.like.java.data_structure.sparseArray;

// 稀疏数组转换为原始的二维数组
public class Spare2Raw {
	
	/**
	 * 
	 * @param spareArr 稀疏数组
	 * @return rawArr  原始的二维数组
	 */
	public static int[][] transfer(int[][] spareArr)
	{
		// 1. 获取行数,列数,非零元素个数
		int row = spareArr[0][0];
		int col = spareArr[0][1];
		int count = spareArr[0][2];
		// 2. 为原始二维数组分配内存空间
		int[][] rawArr = new int[row][col];
		// 3. 遍历稀疏数组,存储对应的值到原始二维数组中
		for(int i=0;i<count;i++)
		{
			rawArr[spareArr[i+1][0]][spareArr[i+1][1]] = spareArr[i+1][2];
		}
		return rawArr;
	}
	
}

测试用例Java

package com.like.java.data_structure.sparseArray;


import java.util.*;
import java.io.*;

public class Tester {
	public static void main(String[] args) {
		int[][] chessArr = new int[10][8];
		for(int i=0;i<10;i++)
		{
			int row = (int)(Math.random()*chessArr.length);
			int col = (int)(Math.random()*chessArr[0].length);
			int val = (int)(Math.random()*10);
			chessArr[row][col] = val;
		}
		
		// 原始数组转换为稀疏数组
		int[][] sparseArr = Raw2Sparse.transfer(chessArr);
		
		for(int i=0;i<sparseArr.length;i++)
		{
			System.out.println(Arrays.toString(sparseArr[i]));
		}
		
		// 稀疏数组转换为二位数组
		int[][] rawArr1 = Spare2Raw.transfer(sparseArr);
		System.out.println(Arrays.deepToString(rawArr1));
		
	}
}
发布了80 篇原创文章 · 获赞 332 · 访问量 70万+

猜你喜欢

转载自blog.csdn.net/qq_40527086/article/details/104338623