數據結構與算法-稀疏數組詳解

1.背景

1.1.假設讓你開發一個五子棋,你會如何存儲棋盤

1.2.數組保存棋盤

假設:

0-白表示空白位置(即沒有走過的位置)

1-表示白棋

2-表示黑棋

如果是數組保存棋盤,你會發現很多數據都是零,如下圖:

 

上面,我們通過二維數組的方法,將棋盤數據保存在了一個二維數組中,整個數組我們用了 16 × 16(共 256)個點來保存數據,其中有 254 個點都是空的。

實際來說,我們只需要將有價值的黑白子保存起來即可,因爲只要我們知道黑白子數據,以及棋盤的大小,那麼這 254 個空點是可以不用進行保存的。

把這樣沒有價值的數據起來,不但會浪費存儲空間的大小,如果寫入到磁盤中,還會增大 IO 的讀寫量,影響性能,這就是用普通二維數組來表示棋盤數據的不足之處。

那麼,針對以上情況,我們該如何將我們的數據格式進行優化呢?於是就引出了我們接下來的稀疏數組的概念。

1.3.稀疏數組

稀疏數組本質上也是數組,只是存儲數據時只存在元數據的規模和數據兩部分

稀疏數組

列是固定的3列,分別爲原數組的(行,列,值)

行,第一行表示數據規模,即表示原來的數組(有多少行,有多少列,有多少個值)

如下圖所示:

2.普通數組與稀疏數組互轉

package com.ldp.course.structure.demo02sparsearray;

import com.ldp.course.common.MyArrayUtil;
import org.junit.Test;

import java.util.LinkedList;

/**
 * @create 06/29 7:23
 * @description <P>
 * 數據結構之稀疏數組
 * 課件:https://www.cnblogs.com/newAndHui/p/16421898.html
 * </P>
 */
public class Test01 {
    /**
     * 二維數組保存棋盤演示
     */
    @Test
    public void test01() {
        // 建立一個16*16的棋盤
        int[][] array = new int[16][16];
        // 設置2個棋子的位置
        array[8][7] = 1;
        array[9][8] = 2;
        System.out.println("顯示棋盤");
        MyArrayUtil.showArray(array);
        System.out.println("二維數組轉爲稀疏數組");
        int[][] sparse = arrayToSparse(array);
        MyArrayUtil.showArray(sparse);
        System.out.println("稀疏數組轉二維數組");
        int[][] array2 = sparseToArray(sparse);
        MyArrayUtil.showArray(array2);
    }

    /**
     * 1.確定稀疏數組的行:遍歷數組得到數組的值個數n,n+1作爲稀疏數組的行
     * 2.稀疏數組的列爲固定值3
     * 二維數組轉爲稀疏數組
     *
     * @param array 二維數組
     * @return 稀疏數組
     */
    public int[][] arrayToSparse(int[][] array) {
        // 確定數組有效值個數
        int row = 0, col = 0, n = 0;
        // 記錄二維數組每個值的行列值,格式(行,列,值)
        LinkedList<String> arrayStrList = new LinkedList<>();
        for (int[] ints : array) {
            row++;
            col = 0;
            for (int anInt : ints) {
                col++;
                if (anInt != 0) {
                    n++;
                    // 行,列,值
                    String str = "" + (row - 1) + "," + (col - 1) + "," + anInt;
                    arrayStrList.addLast(str);
                }
            }
        }
        // 第一行是 行,列,個數
        String strFirst = "" + row + "," + col + "," + n;
        arrayStrList.addFirst(strFirst);
        // 創建稀疏數組對象
        int[][] sparseArray = new int[n + 1][3];
        for (int i = 0; i < (n + 1); i++) {
            String s = arrayStrList.get(i);
            // System.out.println(s);
            String[] rowStr = s.split(",");
            sparseArray[i][0] = Integer.valueOf(rowStr[0]);
            sparseArray[i][1] = Integer.valueOf(rowStr[1]);
            sparseArray[i][2] = Integer.valueOf(rowStr[2]);
        }
        return sparseArray;
    }

    /**
     * 稀疏數組轉二維數組
     *
     * @param sparseArray 稀疏數組
     * @return 二維數組
     */
    public int[][] sparseToArray(int[][] sparseArray) {
        int row = sparseArray[0][0];
        int col = sparseArray[0][1];
        int n = sparseArray[0][2];
        int[][] array = new int[row][col];
        // 注意這裏循環i<n+1,原因是第一行是數據規模,順然只有2個值,但是實際是3行,如下
        // [16, 16, 2]
        // [8, 7, 1]
        //[9, 8, 2]
        for (int i = 1; i < n + 1; i++) {
            int row_ = sparseArray[i][0];
            int col_ = sparseArray[i][1];
            int value_ = sparseArray[i][2];
            array[row_][col_] = value_;
        }
        return array;
    }
}

 

4.總結

在存儲數組數據的時候,如果存在許多默認值的數據,可以考慮使用稀疏數組來進行存儲,

這樣數據相對來說就會瘦小很多,不但可以節省磁盤空間,還可以優化磁盤讀寫時性能。

完美

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章