1. 程式人生 > 實用技巧 >資料結構和演算法基礎

資料結構和演算法基礎

線性結構和非線性結構

線性結構

  • 線性結構作為最常用的資料結構,其特點是資料元素之間存在一對一的線性關係。
  • 線性結構有兩種不同的儲存結構,即順序儲存結構以及鏈式儲存結構。順序儲存結構的線性表被稱之為順序表,順序表中儲存的元素是連續的。鏈式儲存結構的線性表被稱之為連結串列,連結串列中儲存的元素不一定是連續的,元素節點中存放資料元素以及相鄰元素的地址資訊。
  • 線性結構常見的有:陣列、佇列、連結串列和棧。

非線性結構

  • 非線性結構包括:二維陣列,多維陣列,廣義表,樹結構,圖結構。

稀疏陣列

首先思考一個實際的程式問題,現在有一個五子棋遊戲,遊戲需要一個存檔退出和續上盤的功能。這個功能就要求我們需要將棋局的資訊儲存下來,記錄下哪一方在哪個位置下了棋。
如下圖所示,為完成功能,可以採用二維陣列來表示棋盤資料:

預設棋盤的每一個點都是用0來代表,黑色方下的棋用數字1代表,藍色方用數字2。
如此,我們就可以通過二維陣列來完成功能。但是這樣也會有一個問題,就是我們將太多的預設的0記錄了下來,產生了大量的冗餘資料,這個問題就可以使用稀疏陣列來解決。

稀疏陣列和二維陣列對比


由上圖可以看出,原二維陣列一共有六行七列42個數據,轉換為稀疏陣列之後為三行九列27個數據,避免了儲存大量的冗餘的預設資料。
稀疏陣列第一行用來儲存表示原二維陣列一共是幾行幾列的二維陣列以及陣列中有多少個有用的資料,剩下的行分別用來橫縱座標和資料的值,達到表示各個值在原二維陣列中位置的功能。

二維陣列和稀疏陣列轉換實現

package com.xsh.demo.datastructure;

/**
 * 稀疏陣列
 * @author xiashihua
 */
public class SparseArray {
    /**
     * 編碼實現使用二維陣列模擬棋盤資料,並使用稀疏陣列優化資料結構,然後實現稀疏陣列和二維陣列之間的轉換
     * @param args
     */
    public static void main(String[] args) {
        //建立一個二維陣列,表示棋盤,預設無棋子的資料是0,黑子是1,藍子是2
        int chessArray[][] =new int [11][11];
        //放置一個黑子和一個藍子
        chessArray[1][2]=1;
        chessArray[2][3]=2;
        chessArray[5][5]=2;
        //遍歷二維陣列
        System.out.println("原二維陣列為:");
        for (int[] ints : chessArray) {
            for (int anInt : ints) {
                System.out.print(anInt+"   ");
            }
            System.out.println();
        }

        //根據原二維陣列建立稀疏陣列
        int sum=0;
        for (int[] ints : chessArray) {
            for (int anInt : ints) {
                if(anInt != 0){
                    sum++;
                }
            }
        }
        int sparseArray[][]=new int[sum+1][3];
        sparseArray[0][0]=chessArray.length;
        sparseArray[0][1]=chessArray.length;
        sparseArray[0][2]=sum;
        //獲取原二維陣列中的非零元素,儲存到稀疏陣列中
        int count=0;
        for (int i = 0; i < chessArray.length; i++) {
            for (int j = 0; j < chessArray.length; j++) {
                if(chessArray[i][j] != 0){
                    count++;
                    sparseArray[count][0]=i;
                    sparseArray[count][1]=j;
                    sparseArray[count][2]=chessArray[i][j];
                }
            }
        }
        System.out.println("根據原二維陣列建立的稀疏陣列為:");
        for (int[] ints : sparseArray) {
            for (int anInt : ints) {
                System.out.print(anInt+"   ");
            }
            System.out.println();
        }
        //根據得到的稀疏陣列還原二維陣列
        int chhessArray2[][] =new int[sparseArray[0][0]][sparseArray[0][1]];
        //資料填充
        for (int i = 1; i <= sum; i++) {
            chhessArray2[sparseArray[i][0]][sparseArray[i][1]] = sparseArray[i][2];
        }
        System.out.println("還原之後的二維陣列為:");
        for (int[] ints : chhessArray2) {
            for (int anInt : ints) {
                System.out.print(anInt+"   ");
            }
            System.out.println();
        }
    }
}

如上程式碼就實現了二維陣列和稀疏陣列之間的轉換,完成了有大量冗餘資料時進行資料壓縮的功能。

佇列

佇列是一個有序列表,可以使用陣列或者連結串列來實現。
佇列必須遵循先入先出的原則。即:先存入佇列的資料要先取出,後存入佇列的資料後去除。

使用陣列模擬佇列

使用陣列模擬佇列的示意圖:

佇列本身是有序列表,若使用陣列的結構來儲存佇列的資料,則佇列的宣告如上圖所示,其中maxSize表示為佇列的最大容量。
因為佇列的輸入和輸出分別是從前後端來處理,因此需要兩個變數指標frontrear分別指向佇列的最前端和最後端,front會隨佇列資料的輸出而改變,rear會隨佇列資料的輸入而改變。