稀疏陣列原理基礎_Java語言實現

2020-08-11 22:26:17

稀疏陣列

稀疏陣列(SparseArray)
當一個二維陣列中大部分元素爲 0 或同一個值的二維陣列時,稀疏陣列可對該二維陣列進行壓縮
儲存。

壓縮儲存的好處
當原陣列中存在大量的無效數據佔用大量的儲存空間時,壓縮儲存可以節省儲存空間,以避
免資源的不必要的浪費 。
處理方法:
記錄原陣列共幾行幾列,有多少個非零值
把每個值的行和列的索引值記錄在一個小規模的陣列中,從而縮小程式規模

二維轉稀疏的思路:
遍歷原始二維陣列,得到非零數值的個數 sum
根據 sum 建立稀疏陣列 sparseArr = new int[sum +1][3]
說明:sum 大小的陣列只能記錄sum條數據,须增添一行來記錄原陣列大小
再次遍歷原始二維陣列,將每個非零數值所對應的行列索引與值,記錄在稀疏陣列中

稀疏轉二維的思路:
讀取稀疏陣列第一行陣列,獲取原陣列的大小,建立新的二維陣列
遍歷稀疏陣列,讀取每行的數據,並將數據恢復到對應的二維陣列中

/* 壓縮前的原始二維陣列
	 0 1 2 3 4 5 6 7 8 9	<- 行索引
0	 0 0 0 0 0 0 0 0 0 0 		此時展示的是一個 二維陣列 new Array[7][10]
1	 0 0 1 0 0 0 0 0 0 0 		該陣列大部分都被同樣的值進行填充
2	 0 0 0 0 0 2 0 0 0 0 		此時該陣列對浪費了大量的儲存空間
3	 0 0 0 8 0 0 0 0 0 0 		此等情況下 我們可以使用 稀疏陣列
4	 0 0 0 0 0 0 5 0 0 0 		進行對該二陣列的壓縮 
5	 0 0 0 0 0 0 0 0 0 0 		
6	 0 0 0 0 0 0 0 0 0 0 		
^_ 列索引*/
/* 壓縮後的稀疏陣列
	 0   1   2 	  <- 行索引
	row	col	val					該陣列是上述二維陣列的壓縮形式
0	 7   10  4					arr[0]中陣列表示:new Array[7][10] 共有 4 個有效數值
1	 1   2   1 					其中第一個值得位置:在 Array[1][2] 的位置 數值爲 1
2	 2   5   2					其中第二個值得位置:在 Array[2][5] 的位置 數值爲 2
3	 3   3   8					稀疏陣列用 第一個陣列記錄原陣列的大小和有效值個數
4	 4   6   5					後續陣列記錄原陣列有效值的橫縱索引和其值
^_ 列索引*/

程式碼:

package com.DataStructure.sparseArray;
import java.lang.reflect.Array;
public class SparseArray {
    public static void main(String[] args) {
        SparseArray spar = new SparseArray();       // 建立此類 用以呼叫類中方法
        int[][] arr1 = spar.createArray(11, 11);    // 獲得一個 縱橫都是 11大小的二維陣列
        arr1[1][2] = 1;                             // 爲陣列增加值
        arr1[2][3] = 2;
        spar.printArr(arr1);                        // 列印初始二維陣列
        int[][] sparse = spar.getSparse(arr1);      // 將初始二維陣列轉換成稀疏陣列
        spar.printArr(sparse);                      // 列印稀疏陣列
        int[][] arr2 = spar.parseSparse(sparse);    // 將稀疏陣列轉換成二維陣列
        spar.printArr(arr2);                        // 列印轉換出的二維陣列
    }
    
    
    // 建立一個二維陣列並新增預設數據
    public int[][] createArray(int row, int col) {
        return new int[row][col];                   // 傳入參數 返回建立陣列
    }
    
    
    // 將二維陣列解析爲稀疏陣列
    public int[][] getSparse(int[][] arr) {      // 傳入一個二維陣列
        int [][] spsArr = null;                  // 建立一個稀疏陣列變數
        int count = getNotZero(arr);             // 得到傳入陣列中非零值的個數用以記錄
        int counter = 0;                         // 用以記錄稀疏陣列已經記錄了第幾個二維陣列有效值
        if (arr != null) {                       // 判空若爲空則不使用 防止報錯
            spsArr = new int[count + 1][3];  // 建立稀疏陣列 多一行要記錄二維陣列的大小與有效值個數
            spsArr[0][0] = arr.length;           // 第一行第一個數據記錄二維陣列的行數
            spsArr[0][1] = arr[0].length;        // 第一行第二個數據記錄二維陣列的列數
            spsArr[0][2] = count;                // 第一行第三個數據記錄二維陣列的有效值個數
            for (int i = 0; i < arr.length; i++) {          // 回圈變數二維陣列的值
                for (int j = 0; j < arr[i].length; j++) {
                    if (arr[i][j] != 0) {        // 檢視每個非零的值將其資訊記錄在稀疏陣列中
                        counter++;       // 記錄數據已經寫入第幾行  第幾行數據正好與稀疏陣列下標對應
                        spsArr[counter][0] = i;  // 記錄數值所在原二維陣列行的下標
                        spsArr[counter][1] = j;  // 記錄數值所在原二維陣列列的下標
                        spsArr[counter][2] = arr[i][j];// 記錄原二維陣列中以上行列下標所對應的值
                    }
                }
            }
        }
        return spsArr;                           // 若陣列存在返回稀疏陣列,不存在則返回 null
    }
    
    
    // 將稀疏陣列解析爲二維陣列
    public int[][] parseSparse(int[][] sparseArr){
        int[][] arr = null;                     // 建立一個二維陣列變數
        if (sparseArr != null && 3 == sparseArr[0].length){
            									// 判空,並且判斷傳入陣列是否爲稀疏陣列
            arr = new int[sparseArr[0][0]][sparseArr[0][1]];
            								// 將稀疏陣列第一行的二維陣列大小值取出恢復二維陣列大小
            for (int i = 1; i < sparseArr.length; i++) {
                		   // 將稀疏陣列的每行有效值數據取出,稀疏數據第一行記錄陣列大小 所以從第二行取
                arr[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2]; 	
                						   	// 取出行列對應的索引值,找的陣列對應位置,將原值賦回
            }
        }
        return arr;              // 若稀疏陣列存在返回二維陣列,不存在則返回 null
    }
    
    
    // 獲得陣列中非零數據個數
    public int getNotZero(int[][] arr) {
        int count = -1;                       // 當傳入陣列爲 null 時,有效數據個數返回 -1
        if (arr != null) {                    // 判空
            count = 0;                        // 當陣列存在但是沒有有效值時候,個數爲0
            for (int[] row : arr) {           // 遍歷陣列
                for (int data : row) {
                    if (data != 0) {          // 判斷陣列中數值是否爲有效值
                        count++;              // 當此次數值有效,個數增長 1
                    }
                }
            }
        }
        return count;
    }
    
    
    // 列印二維陣列
    public void printArr(int[][] arr) {              // 傳入二維陣列
        if (arr != null){                           // 判空,若爲空則不呼叫列印 否則報錯
            for (int[] row : arr) {                // 使用 ForEach 回圈得到二維陣列中的一維陣列
                for (int data : row) {             // 使用 ForEach 回圈得到一維陣列中的每一個值
                    System.out.printf("%d\t", data);  // 將值列印並在每個值後面增加一個製表符
                }
                System.out.println();                //每一個數組輸出一行後換行進行輸出下一個陣列
            }
        } else {
            System.out.println("陣列不存在!");         // 若陣列爲空,則輸出陣列不存在
        }
    }
}

筆記博文,該博文用於私下交流,若有問題請各位大神提點。謝謝!!!