20172309 《Java軟件結構與數據結構》實驗三報告

課程:《程序設計與數據結構(下)》
班級:1723
姓名: 王志偉
學號:20172309
實驗教師:王志強老師
實驗日期:2018年11月2日
必修/選修: 必修html

實驗內容:

實驗一:

實驗二:

實驗三:

實驗四:

實驗五:

實驗過程及結果:

實驗一:

  • 定義一個Searching和Sorting類,並在類中實現linearSearch(教材P162 ),SelectionSort方法(P169)。
    • Searching類的實現linearSearch方法。
    public static <T> boolean linearSearch(T[] data, int min, int max, T target)
     {
         int index = min;
         boolean found = false;
    
         while (!found && index <= max)
         {
             found = data[index].equals(target);
             index++;
         }
    
         return found;
     }//順序/線性查找
    這個算法的理念是一個一個查找,直到找到爲止。不過我的以爲這個算法的缺點是當有兩個目標值時,將不會查到第二個。好比:在數組{1,2,3,4, 5, 5,6 }中查找數字5時,將只能查找到索引爲4的數字5,而不會查找到索引值爲5的那個。
    • 測試代碼:
    • 測試結果:
    • Sorting的selectsort方法:
    public static <T extends Comparable<T>>//選擇排序
     String selectionSort(T[] data) {
         int min;
         T temp;
    
         for (int index = 0; index < data.length - 1; index++) {
             min = index;
             for (int scan = index + 1; scan < data.length; scan++)
                 if (data[scan].compareTo(data[min]) < 0)
                     min = scan;
    
             swap(data, min, index);
         }
    
         return Arrays.toString(data);
     }
    選擇排序的理念就是把一排數列中的東西中的最大(最小)放到最前面並與之交換位置,以後又從剩下的算法中選擇出最大(最小)的與第二個項目交換位置·····直至所有完成。這裏值得說的一個重點是Arrays.toString(data);這個方法,這個方法的用處是把一個數組自動ToString(),也就是不用本身寫toString方法。
    • 代碼截圖:
    • 結果截圖:
  • 要求很多於10個測試用例,提交測試用例設計狀況(正常,異常,邊界,正序,逆序),用例數據中要包含本身學號的後四位。
    • 這裏要求測試用例須要正常、異常、邊界、正序、逆序我感受有點錯誤,好比線性查找哪來的正序、逆序測試,選擇排序哪來的邊界測試。不是很懂,感受有問題~~~java

      實驗二:

  • 把Sorting.java,Searching.java放入cn.edu.besti.cs1723.(姓名首字母+四位學號)包中(例如:cn.edu.besti.cs1723.G2301)。並把測試代碼放test包中。

    android

    一開始並不知道cn.edu.besti.cs1723.什麼意思,其實到文件中去看就會發現他這並非一個文件夾,而是cn的文件夾下有edu,edu的文件夾下有besti....git

  • 從新編譯,運行代碼,提交編譯,運行的截圖(IDEA,命令行兩種)
    • 用IDEA測試結果與實驗一同樣,所以在這不放圖。
    • 用命令行進行測試:因爲老師沒有明確表達必須使用Junit測試,所以我選擇了使用main函數測試(由於虛擬機使用命令行還得安裝一個Junit.jar包~~~ 而安裝包的什麼命令都是上學期的事兒了,哪還記得 ?)。
      查找結果:

      排序結果:
  • 開心的是好像IDEA也有命令行模式,不過這是在我作完實驗以後才發現的o(╥﹏╥)o

    若是沒有顯示的話,能夠手動開啓:
    算法

實驗三:

  • 代碼詳情
  • 參考http://www.cnblogs.com/maybe2030/p/4715035.html 在Searching中補充查找算法並測試提交運行結果截圖。咱們將一個個講解下查找算法:之前在博客中講過的一筆帶過,沒講的是重點
    • 順序查找:
      • 主要思想:順序查找也稱爲線形查找,屬於無序查找算法。從數據結構線形表的一端開始,順序掃描,依次將掃描到的結點關鍵字與給定值k相比較,若相等則表示查找成功;若掃描結束仍沒有找到關鍵字等於k的結點,表示查找失敗。說明:順序查找適合於存儲結構爲順序存儲或連接存儲的線性表。
      • 時間複雜度爲:O(n)
      • 方法代碼:
        ```
        public static <T extends Comparable >
        boolean binarySearch(T[] data, int min, int max, T target)
        {
        boolean found = false;
        int midpoint = (min + max) / 2; // determine the midpoint
        shell

        if (data[midpoint].compareTo(target) == 0)
        found = true;數據庫

        else if (data[midpoint].compareTo(target) > 0)
        {
        if (min <= midpoint - 1)
        found = binarySearch(data, min, midpoint - 1, target);
        }數組

        else if (midpoint + 1 <= max)
        found = binarySearch(data, midpoint + 1, max, target);數據結構

        return found;app

    }//二分查找
    ```

    • 二分查找:
      • 主要思想:也稱爲是折半查找,屬於有序查找算法。用給定值k先與中間結點的關鍵字比較,中間結點把線形表分紅兩個子表,若相等則查找成功;若不相等,再根據k與該中間結點關鍵字的比較結果肯定下一步查找哪一個子表,這樣遞歸進行,直到查找到或查找結束髮現表中沒有這樣的結點。元素必須是有序的,若是是無序的則要先進行排序操做。
      • 時間複雜度:O(log2n)
      • 方法代碼:
        ```
        public static <T extends Comparable >
        boolean binarySearch(T[] data, int min, int max, T target)
        {
        boolean found = false;
        int midpoint = (min + max) / 2; // determine the midpoint

      if (data[midpoint].compareTo(target) == 0)
      found = true;

      else if (data[midpoint].compareTo(target) > 0)
      {
      if (min <= midpoint - 1)
      found = binarySearch(data, min, midpoint - 1, target);
      }

      else if (midpoint + 1 <= max)
      found = binarySearch(data, midpoint + 1, max, target);

      return found;

    }//二分查找

    ```

    • 插值查找:
      • 主要思想:
        1. 基於二分查找,屬於有序查找,相對於二分查找有時可以提高效率。
        2. 對於表長較大,而關鍵字分佈又比較均勻的查找表來講,插值查找算法的平均性能比折半查找要好的多反之,數組中若是分佈很是不均勻,那麼插值查找未必是很合適的選擇
        3. 我的以爲最重要的就是這個了:mid=low+(key-a[low])/(a[high]-a[low])*(high-low)爲何是這樣?在下面的的問題中講。
      • 時間複雜度:查找成功或者失敗的時間複雜度均爲O(log2(log2n))。
      • 方法代碼:
      public static   boolean interpolationSearch(int[] data,int low,int high,int target){
       while (low<high) {
           int mid=low+(high-low)*((target-data[low])/(data[high]-data[low]));
           if (target<data[mid]) {
               interpolationSearch(data, low, mid-1, target);
           }
           else if (target>data[mid]) {
               interpolationSearch(data, mid+1, high, target);
           }
           else {
               return data[mid]==target;
           }
       }
       return false;
       }//插值查找,不能使用泛型
    • 斐波那契查找:
      • 主要思想:也是二分查找的一種提高算法,經過運用黃金比例的概念在數列中選擇查找點進行查找,提升查找效率。一樣地,斐波那契查找也屬於一種有序查找算法
      • 斐波那契查找算法
      • 時間複雜度:O(log2n)
      • 方法代碼:
      public static boolean FibonacciSearch(int[] data,int target){
      int low = 0;
      int high = data.length - 1;
      int mid = 0;
      // 斐波那契分割數值下標
      int k = 0;
      // 序列元素個數
      int count = 0;
      // 獲取斐波那契數列
      int[] f = new int[20];
      int m = 0;
      f[0] = 1;
      f[1] = 1;
      for (m = 2; m < 20; m++) {
          f[m] = f[m - 1] + f[m - 2];
      }
      // 獲取斐波那契分割數值下標
      while (data.length > f[k] - 1) {
          k++;
      }
      // 建立臨時數組
      int[] temp = new int[f[k] - 1];
      for (int j = 0; j < data.length;j++){
          temp[j] = data[j];
      }
    • 二叉樹查找:
      • 主要思想:
        1. 二叉查找樹是先對待查找的數據進行生成樹,確保樹的左分支的值小於右分支的值,而後在就行和每一個節點的父節點比較大小,查找最適合的範圍。
        2. 這個算法的查找效率很高,可是若是使用這種查找方法要首先建立樹
        3. 對二叉查找樹進行中序遍歷,便可獲得有序的數列。
      • 時間複雜度:它和二分查找同樣,插入和查找的時間複雜度均爲O(logn),可是在最壞的狀況下仍然會有O(n)的時間複雜度。
      • 方法代碼:
      詳情看上面連接
    • 分塊查找:
      • 主要思想:將n個數據元素"按塊有序"劃分爲m塊(m ≤ n)。每一塊中的結點沒必要有序,但塊與塊之間必須"按塊有序";即第1塊中任一元素的關鍵字都必須小於第2塊中任一元素的關鍵字;而第2塊中任一元素又都必須小於第3塊中的任一元素,……
      • 算法步驟:
      1. 先選取各塊中的最大關鍵字構成一個索引表;
      2. 查找分兩個部分:先對索引表進行二分查找或順序查找,以肯定待查記錄在哪一塊中;而後,在已肯定的塊中用順序法進行查找。
      • 時間複雜度:
      • 方法代碼:
      //詳情看上面連接
    • 哈希查找:
      • 主要思想:哈希的思路很簡單,若是全部的鍵都是整數,那麼就可使用一個簡單的無序數組來實現:將鍵做爲索引,值即爲其對應的值,這樣就能夠快速訪問任意鍵的值。這是對於簡單的鍵的狀況,咱們將其擴展到能夠處理更加複雜的類型的鍵
      • 算法步驟:
        1. 用給定的哈希函數構造哈希表
        2. 根據選擇的衝突處理方法解決地址衝突;常見的解決衝突的方法:拉鍊法和線性探測法。詳細的介紹能夠參見:淺談算法和數據結構: 十一 哈希表。
        3. 在哈希表的基礎上執行哈希查找
      • 時間複雜度:O(1)
      • 方法代碼:
      //詳情看上面連接

      實驗四:

  • 補充實現課上講過的排序方法:希爾排序,堆排序,二叉樹排序等(至少3個),測試實現的算法(正常,異常,邊界)。
    • 希爾排序:
      • 主要思想:希爾排序是把記錄按下標的必定增量分組,對每組使用直接插入排序算法排序;隨着增量逐漸減小,每組包含的關鍵詞愈來愈多,當增量減至1時,整個文件恰被分紅一組,算法便終止。
      • 舉個例子:
    • 堆排序:
      • 這個由於之前就寫好了最小堆,每次把最小的頂堆取出來,就完成了從小到大的排序。
    • 二叉排序:
      • 和上面同樣,由於二叉查找樹的左子樹小於或等於父結點,父結點小於或等於右結點。因此使用中序遍歷就能夠完成從小到大的排序。
      • 代碼截圖:
      • 提交運行結果截圖。

實驗五:

  • 編寫Android程序對各類查找與排序算法進行測試
    • emmm·····原本看到這的時候就準備使用一個下拉列表的,可是作了四五個小時後發現出現了bug,因此爲了提交做業只好提交了一種比較low的方法。
    • 運行結果:
    • 測試結果:
    • 不過在這裏學到了一種比較好用的方法:
      • 在xml文件中編寫按鈕Button控件時,可使用onclick屬性。像這樣:
      <Button
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="建立數據庫"
       **android:onClick="creatDb"**<--這兒
       android:background="#ffbbff"
       />
      • 那麼這個方法有什麼用呢?
        我的總結就是當有不少按鈕時,咱們沒必要每一個按鈕都寫點擊事件了只要寫一個就OK了,例:
      public void onclick(View view){
      switch (條件){
       case R.id.button1:
       ···邏輯代碼···
       break;
       case R.id.button2:
       ···邏輯代碼···
       break;
       ·····
      }

試樣過程當中遇到的問題:

  • 問題一:如何進行Junit測試?
  • 問題一解決方案:如今本身來總結下吧。
    • emmm·····,首先選中要進行Junit測試的類名並右擊:Go to->Generate->Test
    • 以後點擊Create new Test
    • 以後選擇Junit4,其次選擇要進行測試的方法。
    • 以後會看到自動生成的方法:例:
    @Test
     public void shellSort() {
    
     }
    • 而後使用assertEquals(參數一,參數二)方法,例:
    @Test
    public void shellSort() {
       assertEquals(預約結果,測試的方法);
       //例:assertEquals("[2301, 2302, 2303, 2305, 2307, 2309]",Sorting.shellSort(list1,3));//正常
    }
  • 問題二:插值查找中的mid=low+(key-a[low])/(a[high]-a[low])*(high-low)是怎麼來的?
  • 問題而解決方案:
  • 先舉兩個例子
    • 打個比方,在英文字典裏面查「apple」,你下意識翻開字典是翻前面的書頁仍是後面的書頁呢?若是再讓你查「zoo」,你又怎麼查?很顯然,這裏你絕對不會是從中間開始查起,而是有必定目的的往前或日後翻。
    • 一樣的,好比要在取值範圍1 ~ 10000 之間 100 個元素從小到大均勻分佈的數組中查找5, 咱們天然會考慮從數組下標較小的開始查找。
  • 通過以上分析,折半查找這種查找方式,不是自適應的(也就是說是傻瓜式的)。二分查找中查找點計算以下:
      mid=(low+high)/2, 即mid=low+1/2(high-low);
    • 經過類比,咱們能夠將查找的點改進爲以下:
        mid=low+(key-a[low])/(a[high]-a[low])*(high-low),
    • 也就是將上述的比例參數1/2改進爲自適應的,也就是將1/2改進爲 (key-a[low])/(a[high]-a[low])。根據關鍵字在整個有序表中所處的位置,讓mid值的變化更靠近關鍵字key,這樣也就間接地減小了比較次數

收穫感悟:

補博客可真是麻煩,拿起了很久都沒動過的IDEA(由於最近在作實戰項目)。

參考文獻:

相關文章
相關標籤/搜索