1. 程式人生 > 其它 >HSP——雙向連結串列、稀疏陣列

HSP——雙向連結串列、稀疏陣列

雙向連結串列

雙向連結串列的基本用法(新增,刪除,修改)和單鏈表的相差不多。雙向連結串列中的節點,多了一個pre,也就是指向前一個節點。具體可以檢視程式碼。

連結:https://pan.baidu.com/s/1qD-4CQYYdpyeDHuUPy_qGg
提取碼:10yl

稀疏陣列

當一個數組中大部分元素為0,或者為同一個值的陣列時,可以使用稀疏陣列來儲存該陣列

稀疏陣列的處理方法

  1. 記錄陣列一共有幾行幾列,有多少個不同的值 。

  2. 把具有不同值的元素的行列及值記錄在一個小規模的陣列中,從而縮小程式的規模.

  3. 稀疏陣列列數只有3列。行數為原始二維陣列的有效資料個數+1。

稀疏陣列舉例說明

轉化思路

二維陣列 轉 稀疏陣列的思路

1.遍歷二維陣列,得到有效資料的個數sum。
2.根據sum可以建立稀疏陣列sparseArray in[sum+1][3]
3.將二維陣列的有效資料存入到稀疏陣列。

稀疏陣列 轉 原始的二維陣列

1.先讀取稀疏陣列的第一行,根據第一行的資料,能夠得到原始二維陣列的大小和其中的有效資料的個數。
2.再讀取稀疏陣列的下面幾行資料,並根據位置賦值給原始二維陣列。

程式碼實現

public class SparseArray {

  public static void main(String[] args) {
    //建立一個原始的二維陣列 11*11
    //0:表示沒有棋子,1:表示黑子,2:表示白子
    int chessArray1[][] = new int[11][11];
    chessArray1[1][2] = 1;
    chessArray1[2][3] = 2;
    //輸出原始的二維陣列
    System.out.println("原始的二維陣列--->");
    for (int[] row : chessArray1) {
      for (int data : row) {
        System.out.printf("%d\t", data);
      }
      System.out.println();
    }

    //將二維陣列轉化為稀疏陣列
    //1.先遍歷二維陣列,得到非0的資料的個數
    int sum = 0;
    for (int i = 0; i < 11; i++) {
      for (int j = 0; j < 11; j++) {
        if (chessArray1[i][j] != 0) {
          sum++;
        }
      }
    }
    //2.建立對應的稀疏陣列
    int sparseArray[][] = new int[sum + 1][3];
    //給稀疏陣列賦值
    sparseArray[0][0] = 11;
    sparseArray[0][1] = 11;
    sparseArray[0][2] = sum;
    //遍歷二維陣列,將非0的值存放到sparseArray稀疏陣列中
    int count = 0;
    for (int i = 0; i < 11; i++) {
      for (int j = 0; j < 11; j++) {
        if (chessArray1[i][j] != 0) {
          count++;
          sparseArray[count][0] = i;
          sparseArray[count][1] = j;
          sparseArray[count][2] = chessArray1[i][j];
        }
      }
    }
    //輸出稀疏陣列的形式
    System.out.println();
    System.out.println("稀疏陣列--->");
    for (int i = 0; i < sparseArray.length; i++) {
      System.out.printf("%d\t%d\t%d\n", sparseArray[i][0], sparseArray[i][1], sparseArray[i][2]);
    }

    //將稀疏陣列恢復成原始二維陣列
    //1.先讀取稀疏陣列的第一行,根據第一行的資料建立原始的二維陣列
    int chessArray2[][] = new int[sparseArray[0][0]][sparseArray[0][1]];
    //2.在讀取稀疏陣列後幾行的資料(從第二行開始),並賦值給原始的二維陣列
    for (int i = 1; i < sparseArray.length; i++) {
      chessArray2[sparseArray[i][0]][sparseArray[i][1]] = sparseArray[i][2];
    }
    //輸出恢復後的陣列
    System.out.println();
    System.out.println("恢復後的陣列--->");
    for (int[] row : chessArray2) {
      for (int data : row) {
        System.out.printf("%d\t", data);
      }
      System.out.println();
    }
      
  }   
}

要求:

​ 1) 在前面的基礎上,將稀疏陣列儲存到磁碟上,比如 map.data

​ 2) 恢復原來的陣列時,讀取 map.data 進行恢復

    System.out.println("-------------------------------------------------------------");
    System.out.println("-------------------------------------------------------------");

    File file = new File(
        "F:\\Code\\Java_Code\\structures-algorithms\\data\\src\\sparsearray\\map.data");

    //將稀疏陣列寫入到磁碟中的map.data
    try {
      FileOutputStream fos = new FileOutputStream(file);
      OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
      BufferedWriter bw = new BufferedWriter(osw);
      System.out.println("寫入磁碟中···");
      for (int i = 0; i < sparseArray.length; i++) {
        bw.write(sparseArray[i][0] + "," + sparseArray[i][1] + "," + sparseArray[i][2] + ",");
      }
      bw.close();
      osw.close();
      fos.close();
      System.out.println("寫入成功");
    } catch (IOException e) {
      e.printStackTrace();
    }

    //讀取磁碟中的map.data,恢復稀疏陣列。
    try {
      System.out.println("讀取中···");
      FileInputStream fis = new FileInputStream(file);//讀取檔案的資料到位元組流inputStream
      InputStreamReader isr = new InputStreamReader(fis, "UTF-8");//將位元組流inputStream轉換成字元流inputStreamReader
      StringBuffer sb = new StringBuffer();
      while (isr.ready()) { //read()返回的是讀取到的位元組
        sb.append((char) isr.read());
      }
      isr.close();
      fis.close();
      System.out.println("讀取成功");

      String ss = sb.toString();
      System.out.println("從磁碟中讀取的字串為:" + ss);
      System.out.println();

      String[] str = sb.toString().split(",");
      //恢復稀疏陣列
      int[][] sparseArray2 = new int[str.length / 3][3];
      //給稀疏陣列賦值
      int i = 0;
      for (String s : str) {
        sparseArray2[i / 3][i % 3] = Integer.parseInt(s);
        i++;
      }
      //輸出還原後的稀疏陣列
      System.out.println("還原後的稀疏陣列-->");
      for (int[] sa2 : sparseArray2) {
        for (int data : sa2) {
          System.out.printf("%d\t", data);
        }
        System.out.println();
      }
      System.out.println();

      //再恢復成二維陣列
      int array[][] = new int[sparseArray2[0][0]][sparseArray2[0][1]];
      //賦值給原始二維陣列
      for (i = 1; i < sparseArray2.length; i++) {
        array[sparseArray2[i][0]][sparseArray2[i][1]] = sparseArray2[i][2];
      }
      System.out.println("恢復成二維陣列-->");
      for (int[] row : array){
        for (int data:row){
          System.out.printf("%d\t",data);
        }
        System.out.println();
      }

    } catch (IOException e) {
      e.printStackTrace();
    }

我實驗中的問題

fileOutputStream、outputStreamWriter和bufferedWriter

FileOutputStream fileOutputStream = new FileOutputStream("d:/text.txt"); 
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream,"MS936"); 
BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);  

如果只用FileOutputStream fileOutputStream = new FileOutputStream("d:/text.txt");
不是也能輸出到"d:/text.txt"嗎?
為什麼要用其它兩個呢?能起到什麼作用呢?
 
FileOutputStream 是位元組流,它一個位元組一個位元組的向外邊送資料。
OutputStreamWrite 是字元流,它一個字元一個字元的向外邊送資料。

它們有什麼區別麼?
解析:
     因為英文字元佔一個位元組,而中文是一個字元,佔倆位元組。
     如果用stream,你讀出來的英語再倒也罷了,讀出來的中文可就是亂碼或者一個個“????”。
     如果用WRITER,就不會有亂碼了。

BufferedWriter  Buffer是一個緩衝區,為什麼要用BUFFER呢?
    如果你直接用stream或者writer,你的硬碟可能就是一個字元或者一個位元組讀寫硬碟一次,可是你用了Buffer,	  你的硬碟就是讀了一堆資料之後,讀寫一下硬碟。這樣對你硬碟有好處。

StringBuffer()的基本使用

  1. StringBuffer: 執行緒安全的可變字串
    • 我們如果對字串進行拼接操作,每次拼接都會構成一個新的String物件,既耗時,又浪費空間
    • StringBuffer可以解決這個問題。
    • StringBuffer和String的區別?前者長度和內容可變,後者不可變
  2. StringBuffer的新增功能
    • public StringBuffer append(String str)
      • 可以把任意型別資料新增到字串緩衝區裡面,並返回字串緩衝區本身
    • public StringBuffer insert(int offset,String str)
      • 在指定位置把任意型別的資料插入到字串緩衝區裡面,並返回字串緩衝區本身
  3. StringBuffer其他使用