稀疏數組
-
當一個數組中大部分元素爲0或者爲同一個值時,可以使用稀疏數組來保存該數組。
-
把一個大部分元素爲0的數組轉化爲稀疏數組的方法:
- 記錄數組一共有幾行幾列,有多少個不同的值
- 把具有不同值的元素的行列及值記錄在一個小規模的數組中,從而縮小程序的規模
-
稀疏數組的本質就是元素爲三元組的數組。
-
稀疏數組應用:
-
在科學與工程領域中求解線性模型時經常出現大型的稀疏矩陣。在使用計算機存儲和操作稀疏矩陣時,經常需要修改標準算法以利用矩陣的稀疏結構。由於其自身的稀疏特性,通過壓縮可以大大節省稀疏矩陣的內存代價。更爲重要的是,由於過大的尺寸,標準的算法經常無法操作這些稀疏矩陣。
-
從描述我們可以知道,稀疏數組主要應用有壓縮數據和優化數據結構。
- 原數組轉爲稀疏數組的思路:
因爲我們需要知道要用多大的空間去存儲原數組中的非0元素,並且在逆過程中重構原數組,所以我們應該知道原數組的行列,每個非0數組元素的行列位置以及值。
- 遍歷原數組得到非0元素的個數n。
- 構造n + 1 (第一行儲存原數組的行列和非0元素的個數)行,3 列的數組。
- 遍歷將非0元素存入稀疏數組。
*代碼實現:
public class SparseArrayDemo {
/**
* return a sparse array,but the array just have the first nonempty line which contains
* the row and column number of original array and a number of nonempty elements.
* @param originalArray
* @return
*/
static int [][] returnSEmptySparseArray(int [][] originalArray){
//traverse the original array to get the number of nonempty value.
int numberOfNonemptyValue = 0;
for (int i = 0;i < originalArray.length;i ++){
for(int j = 0;j < originalArray[0].length;j ++){
if(originalArray[i][j] != 0){
++ numberOfNonemptyValue;
}
}
}
int [][] emptySparseArray = new int[numberOfNonemptyValue + 1][3];
emptySparseArray[0][0] = originalArray.length;
emptySparseArray[0][1] = originalArray[0].length;
emptySparseArray[0][2] = numberOfNonemptyValue;
return emptySparseArray;
}
/**
* return the sparse array
* @param originalArray
* @return
*/
public static int [][] returnSparseArray(int [][] originalArray){
int [][] emptySparseArray = returnSEmptySparseArray(originalArray);
int count = 1;
for(int i = 0;i < originalArray.length;i ++){
for (int j = 0;j < originalArray[0].length;j ++){
if(originalArray[i][j] != 0){
//read nonempty element into empty sparse array from original array.
emptySparseArray[count][0] = i;
emptySparseArray[count][1] = j;
emptySparseArray[count][2] = originalArray[i][j];
++ count;
}
}
}
return emptySparseArray;
}
/**
* convert the sparse array back to original array
* @param sparseArray
* @return
*/
public static int [][] returnOriginalArray(int [][] sparseArray){
if(sparseArray == null){
return null;
}
int [][] originalArray = new int[sparseArray[0][0]][sparseArray[0][1]];
for(int i = 1;i <= sparseArray[0][2];i ++){
originalArray[sparseArray[i][0]][sparseArray[i][1]] = sparseArray[i][2];
}
return originalArray;
}
}
- 測試代碼:
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class SparseArrayTest {
private int [][] array = new int[10][10];
@BeforeEach
public void setUp(){
array[1][1] = 1;
array[7][8] = 1;
array[2][1] = 1;
array[9][9] = 1;
array[7][7] = 1;
array[2][9] = 1;
}
@Test
public void testReturnSEmptySparseArray(){
int [][] sparseArray = SparseArrayDemo.returnSEmptySparseArray(array);
for(int i = 0; i < sparseArray.length;i ++){
for(int j = 0;j < 3;j ++){
System.out.print(sparseArray[i][j] + " ");
}
System.out.println();
}
}
@Test
public void testReturnSparseArray(){
int [][] sparseArray = SparseArrayDemo.returnSparseArray(array);
for(int i = 0; i < sparseArray.length;i ++){
for(int j = 0;j < 3;j ++){
System.out.print(sparseArray[i][j] + " ");
}
System.out.println();
}
}
@Test
public void testReturnOriginalArray(){
int [][] sparseArray = SparseArrayDemo.returnSparseArray(array);
int [][] originalArray = SparseArrayDemo.returnOriginalArray(sparseArray);
for(int i = 0;i < originalArray.length;i ++){
for(int j = 0;j < originalArray[0].length;j ++){
System.out.print(originalArray[i][j] + " ");
}
System.out.println();
}
}
}
- 輸出:
10 10 6
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
10 10 6
1 1 1
2 1 1
2 9 1
7 7 1
7 8 1
9 9 1
0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 1 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1
注意,稀疏數組元素的行列值是數組下標。
- 這裏我們添加一個測試把稀疏數組存入文件中,再讀出來轉換爲原數組:
@Test
public void testSaveSparseArrayInFileAndReverse() throws IOException, ClassNotFoundException {
int [][] sparseArray = SparseArrayDemo.returnSparseArray(array);
File file = new File("./test.txt");
if(!file.exists()){
file.createNewFile();
}
//write the sparse array into a file.
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(file));
objectOutputStream.writeObject(sparseArray);
//read the sparse array from the file
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(file));
sparseArray = (int[][]) objectInputStream.readObject();
int [][] originalArray = SparseArrayDemo.returnOriginalArray(sparseArray);
for(int i = 0;i < originalArray.length;i ++){
for(int j = 0;j < originalArray[0].length;j ++){
System.out.print(originalArray[i][j] + " ");
}
System.out.println();
}