数据结构与算法————稀疏数组
引言
數據壓縮方面,我們往往可以通過稀疏數組來保存有效數據,節省存儲空間。
一、稀疏數組的概念
當一個數組中大部分元素是0,或為同一個值的時候,可以使用稀疏數組來保存數組。
它是一個十分有效的存儲結構,便于節省存儲空間。
它的處理方式是:
1、記錄數組一共有幾行幾列,有多少不同的值;
2、把具有不同值的元素的行、列及值記錄在一個小規模二維數組中(稀疏數組),從而縮存儲數據的規模。
二、稀疏數組的存儲結構
稀疏數組實際上是一個典型的二維數組,它描述的是一個標準二維數組的有效數據,如果標準二維數組的內容如下所示的話:
那么這個標準二維數組對應的稀疏數組的結構就如下圖所示:
如上圖所示。
稀疏數組有固定的三列,分別代表原始二維數組的行、列和值,但是第一行具有特殊的含義:稀疏數組的第一行存儲原始數組的行數、列數和有效數據個數,這三個信息。而從第二行(也就是[1]行)開始,才是真正的原始二維數組的有效數據。
【擴展】稀疏數組可以描述二維數組,但同時,我認為它也可以描述更高維的數組,比如三維空間數組,那么相應稀疏數組結構也會有所變化。所以稀疏數組并不是只能描述一個二維數組,凡是可以只保存原始數組有效數據的都可以是稀疏數組,只不過二維數組對應的稀疏數組更有代表性。
三、五子棋盤的保存與復盤
五子棋可能沒有幾個人沒玩過,那么在線上的五子棋游戲中,后臺實際上并沒有保存整個棋盤,而是利用稀疏數組保存有效數據,下面我們就看看如何通過Java 編寫利用稀疏數組對五子棋局的保存與復盤吧。
3.1 五子棋盤的保存
假設在五子棋游戲中,數字1 代表黑子、2 代表白子,0 代表沒有任何棋子,棋盤是一個可容納 11 × 11 個棋子的正方形。黑子先行,雙方都下了兩步,形成了下面的局勢:
public static void main(String[] args) {int[][] chessArr = new int[11][11];chessArr[1][2] = 1;chessArr[2][3] = 2;chessArr[1][4] = 1;chessArr[1][3] = 2;// 輸出原始二維數組printArr(chessArr, "原始的二維數組······"); }其中 printArr()是一個輸出二維數組的靜態工具方法:
/*** 輸出二維數組數組工具方法*/ private static void printArr(int[][] arr, String msg) {System.out.println(msg);for (int[] row : arr) {for (int data : row) {System.out.printf("%d ", data);}System.out.println();} }那么這個11 × 11 的二維數組,根據上面介紹的稀疏數組的結構,進行保存,代碼如下:
/*** 二維數組轉稀疏數組* @param chessArr* @return*/ private static int[][] getSparseArr(int[][] chessArr) {// 將二維數組轉為稀疏數組// 1、先遍歷二維數組,得到非 0 數據的個數int sum = 0;// 二維數組的 length 取的是行數for (int i = 0; i < chessArr.length; i++) {for (int j = 0; j < chessArr[0].length; j++) {if (chessArr[i][j] != 0) {sum++;}}} // System.out.println("sum = " + sum);// 2. 創建對應的稀疏數組int[][] sparseArr = new int[sum + 1][3];// 給稀疏數組賦值sparseArr[0][0] = chessArr.length;sparseArr[0][1] = chessArr[0].length;sparseArr[0][2] = sum;// 將原始數組中的非 0 數據存放到稀疏數組中int sparseArrRow = 1;for (int i = 0; i < chessArr.length; i++) {for (int j = 0; j < chessArr[0].length; j++) {if (chessArr[i][j] != 0) {sparseArr[sparseArrRow][0] = i;sparseArr[sparseArrRow][1] = j;sparseArr[sparseArrRow][2] = chessArr[i][j];sparseArrRow++;}}}return sparseArr; }獲得稀疏數組后輸出:
int[][] sparseArr = getSparseArr(chessArr); printArr(sparseArr, "輸出稀疏數組······");3.2 稀疏數組復盤五子棋
其實復盤的邏輯要更為簡單,首先通過稀疏數組的第一行,初始化一個11 × 11 的二維數組,然后循環后面的行,取出每個數據放入到二維數組中去即可,代碼如下:
/*** 復盤,稀疏數組轉二維數組* @return*/ private static int[][] getReplayArr(int[][] sparseArr) {int[][] chessArr = new int[sparseArr[0][0]][sparseArr[0][1]];for (int i = 1; i < sparseArr.length; i++) {chessArr[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];}return chessArr; }通過上面的內容,我們重新復盤,并輸出:
int[][] replayArr = getReplayArr(sparseArr); printArr(replayArr, "復盤后的二維數組......");可以看到,復盤后的棋盤與原始棋盤一模一樣,這樣就達到了利用稀疏數組節省存儲空間的效果。
總結
稀疏數組總體來說還是比較簡單的一個數據結構的利用,其中并未涉及任何算法,唯一的難點,可能就是二維數組轉稀疏數組時的一些數組下標的思考和轉化,不過通過畫圖也可以輕易地找出準確值。
?
總結
以上是生活随笔為你收集整理的数据结构与算法————稀疏数组的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一篇博客读懂设计模式之---单例模式
- 下一篇: 利用Aria2高速下载网盘文件