從一個場景來分析,爲什麼需要稀疏數組!
二維數組
我們以一個二維數組模擬五子棋爲例,用二維數組模擬創建一個棋盤,數字1代表黑子,二代表白子。在某些場景下,我們需要保存遊戲的進度,如果採用原始的二維數組的方式進行保存的話,我們可以看見存儲量是非常大的。
所以,當我們採用稀疏數組進行存儲後是這個樣子的:
我們可以看出稀疏數組給我們節約了相當一部分的空間。
定義
稀疏數組也是一個數組,可以把它看成是一個普通數組的壓縮。(一般情況下我們認爲如果一個數組的無效數據量遠大於有效數據的情況下,對數組進行壓縮)
稀疏數組的存儲
第一列 | 第二列 | 第三列 |
---|---|---|
原始數組的行數 | 原始數組的列數 | 原始數組有效數據的個數 |
原始數組非零位所作在行索引 | 原始數組非零位所在列索引 | 原始數組非零位的值 |
拿上述五子棋的例子來說:
原始二維數組,一共擁有11行,11列,有效數據的個數爲2個
原始數組的第二行,第三列有一個有效數據1,它所對應的行索引爲1,列索引爲2,值爲1。所以在稀疏數組中的存儲爲
11 | 11 | 2 |
---|---|---|
1 | 2 | 1 |
2 | 3 | 2 |
這樣就將原始的二維數組壓縮成了一個稀疏數組!
代碼實現
1、創建一個二維數組
//創建一個原始的二維數組 11*11
//0:沒有棋子,1:表示黑子,2:白子
int chessArr1[][]=new int[11][11];
chessArr1[1][2]=1;
chessArr1[2][3]=2;
System.out.println("原始的二維數組");
for(int[] row: chessArr1){
for (int data:row){
System.out.printf("%d\t",data);
}
System.out.println();
}
執行後的結果:
2、將二維數組轉換成稀疏數組
2.1 遍歷二維數組,獲得有效數據的個數
//1、先遍歷二維數組,得到非0數據的個數
int sum=0;
for (int i = 0; i <chessArr1.length ; i++) {
for (int j = 0; j < chessArr1.length; j++) {
if(chessArr1[i][j]!=0){
sum++;
}
}
}
System.out.println("sum="+sum);
得到的結果:
2.2創建對應的稀疏數組
//2、創建對應的稀疏數組
int sparseArray[][]=new int[sum+1][3];
//給稀疏數組賦值
sparseArray[0][0]=11;
sparseArray[0][1]=11;
sparseArray[0][2]=sum;
2.3向稀疏數組中存入數據
//遍歷二維數組,將非0的值存放到稀疏數組中
int count=0; //count用於記錄是第幾個非零數據
for (int i = 0; i <chessArr1.length ; i++) {
for (int j = 0; j < chessArr1.length; j++) {
if(chessArr1[i][j]!=0){
count++;
sparseArray[count][0]=i;
sparseArray[count][1]=j;
sparseArray[count][2]=chessArr1[i][j];
}
}
得到的稀疏數組爲:
3、將稀疏數組還原成爲二維數組
3.1思路
- 從稀疏數組的第一行可以得到原始數組的行數和列數,創建一個二維數組
- 遍歷稀疏數組,從其後幾行的數據,可以得到原始數組有效數據的所在行所在列以及值,將其放入原始數組即可
//1、先讀取稀疏數組的第一行,根據第一行的數據,創建原始的二維數組
int chessArr2[][]=new int[sparseArray[0][0]][sparseArray[0][1]];
//2、讀取稀疏數組的後幾行的數據(從第二行開始),並賦值給原始的二維數組
for (int i = 1; i <sparseArray.length; i++) {
chessArr2[sparseArray[i][0]][sparseArray[i][1]]=sparseArray[i][2];
}