數據結構與算法 稀疏數組

稀疏數組

  • 當一個數組中大部分元素爲0或者爲同一個值時,可以使用稀疏數組來保存該數組。

  • 把一個大部分元素爲0的數組轉化爲稀疏數組的方法:

  1. 記錄數組一共有幾行幾列,有多少個不同的值
  2. 把具有不同值的元素的行列及值記錄在一個小規模的數組中,從而縮小程序的規模
    在這裏插入圖片描述

在這裏插入圖片描述

  • 稀疏數組的本質就是元素爲三元組的數組。

  • 稀疏數組應用:

  1. 在科學與工程領域中求解線性模型時經常出現大型的稀疏矩陣。在使用計算機存儲和操作稀疏矩陣時,經常需要修改標準算法以利用矩陣的稀疏結構。由於其自身的稀疏特性,通過壓縮可以大大節省稀疏矩陣的內存代價。更爲重要的是,由於過大的尺寸,標準的算法經常無法操作這些稀疏矩陣。

  2. 從描述我們可以知道,稀疏數組主要應用有壓縮數據和優化數據結構。

  • 原數組轉爲稀疏數組的思路:
    因爲我們需要知道要用多大的空間去存儲原數組中的非0元素,並且在逆過程中重構原數組,所以我們應該知道原數組的行列,每個非0數組元素的行列位置以及值。
  1. 遍歷原數組得到非0元素的個數n。
  2. 構造n + 1 (第一行儲存原數組的行列和非0元素的個數)行,3 列的數組。
  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();
        }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章