1. 程式人生 > >20172301 《Java軟體結構與資料結構》實驗三報告

20172301 《Java軟體結構與資料結構》實驗三報告

20172301 《Java軟體結構與資料結構》實驗三報告

課程:《Java軟體結構與資料結構》
班級: 1723
姓名: 郭愷
學號:20172301
實驗教師:王志強老師
實驗日期:2018年11月20日
必修/選修: 必修

一.實驗內容

實驗一

實驗二

實驗三

實驗四

實驗五

二.實驗過程及結果

實驗一:

實驗一是比較簡單的,程式碼是書上的程式碼。主要是Junit測試因為好久沒有用過,總是會有一些錯誤,類似junit測試方法前沒有新增test,或者junit測試的assert方法實現。
測試用例設計情況(正常,異常,邊界,正序,逆序),關於測試用例,對於排序的異常,是ClassCastException

,是轉換髮生了錯誤。具體是例如1234ab是不可以比的,也就是不能排序。

排序應該是沒有邊界測試的。

對於查詢的異常,是ArrayIndexOutOfBoundsException,是陣列越界。即查詢範圍超過了陣列範圍。

查詢應該是沒有逆序測試的。

  • 實驗一測試結果截圖:
    查詢測試:

    排序測試:

  • 藍墨雲連結

實驗二:

實驗二首先要移到包裡面,需要注意的是測試類的位置,需要放在專案的test資料夾中,並且變更目錄為Test Sources Root

實驗三:

七種查詢演算法分別是:線性查詢、二分查詢、插值查詢、斐波那契查詢、樹表查詢、分塊查詢、雜湊查詢。之前的學過的查詢方式,這裡就不再多說了。
需要注意的是,插值查詢

斐波那契查詢都是二分查詢的優化,所以他們所查詢的序列應該也是有序的。

我重點解釋一下分塊查詢。
在之前的學習中,我們學習過分塊排序。那麼類比推理一下,分塊查詢的原理應該也是類似的。分塊查詢的最大特點就應該是塊內無序,塊間有序。 通過這個特點,我們可以首先可以確定目標元素在哪個塊裡面,然後通過順序查詢確定其位置。
可以說,是一種折半查詢和順序查詢的優化改進的方法。

那麼這裡,我直接用了之前的分塊方法。

    private static <T extends Comparable<? super T>> int partition(T[] data, int min, int max)
    {
        T partitionelement;
        int left, right;
        int middle = (min + max) / 2;

        //使用中間資料值作為分割槽元素
        partitionelement = data[middle];
        // 暫時把它移開
        swap(data, middle, min);

        left = min;
        right = max;

        while (left < right)
        {
            // 搜尋一個元素,它是>分割槽元素
            while (left < right && data[left].compareTo(partitionelement) <= 0)
                left++;

            // 搜尋一個元素,它是<分割槽元素
            while (data[right].compareTo(partitionelement) > 0)
                right--;

            // 交換元素
            if (left < right)
                swap(data, left, right);
        }

        // 將分割槽元素移動到適當的位置
        swap(data, min, right);

        return right;
    }

然後,在分塊查詢裡劃分為幾個部分。

  int partition = partition(data,min,max); 
  int leftPartition = partition(data,min,partition-1);
  int rightPartition = partition(data,partition+1,max);

判斷具體位置後,進行線性查詢。

實驗四:

這裡的排序演算法是希爾排序,堆排序,二叉樹排序。

這裡還是重點介紹一下希爾排序。因為有關第八週的測試,希爾排序學長提出了一點問題。

這裡我先放出我當時的答案。

學長說這裡應該是4插入到13的前面。

我們這裡就應該注意希爾排序的基本思想:

希爾排序是把記錄按下標的一定增量分組,對每組使用直接插入排序演算法排序;隨著增量逐漸減少,每組包含的關鍵詞越來越多,當增量減至1時,整個檔案恰被分成一組,演算法便終止。

希爾排序也是插入排序,對簡單插入排序的改進方法。

所以,對於這道題來說,最後4應該直接插入到13的前面。

實驗五:

基於安卓實現查詢和排序功能。是之前實驗的一個整合。

三. 實驗過程中遇到的問題和解決過程

  • 問題1:實驗三中七種查詢演算法中的斐波那契查詢,對於其中擴充套件陣列的操作,C++實現:
  int  * temp;//將陣列a擴充套件到F[k]-1的長度
  temp=new int [F[k]-1];
  memcpy(temp,a,n*sizeof(int));

int * temp是宣告一個int型別的陣列。
memcpy()方法應該是有關複製的操作,在java中應該如何實現。

  • 問題1解決方案:
    • memcpy()函式
      • 函式原型:void *memcpy (voiddest, const void src, size_t n);
      • 功能:由src指向地址為起始地址的連續n個位元組的資料複製到以destin指向地址為起始地址的空間內。
    • 由此,這個功能應該就是複製原陣列到一個新陣列中。
    • 在java上有多種實現方式:
      • for迴圈程式碼可以說是很直觀,靈活並且便於理解,但是效率有時候不高。
      // 通過for迴圈
        int[] array2 = new int[5];
        for(int i = 0;i < array1.length;i++) {
           array2[i] = array1[i];
       }
       for(int i = 0;i < array2.length;i++) {
           System.out.print(array2[i]);
       }
       System.out.println();
      • System.arraycopy()方法通過原始碼可以觀察到native,是原生態方法,效率自然更高。
       public static native void arraycopy(Object src,  int  srcPos,
                                           Object dest, int destPos,
                                          int length);
      • Arrays.copyOf()方法在原始碼上是基於System.arraycopy(),所以效率自然低於System.arraycpoy()。
      // 通過Arrays.copyOf()
      int[] array4 = new int[5];
       array4 = Arrays.copyOf(array1, 5);
       for (int i = 0; i < array4.length; i++) {
           System.out.print(array4[i]);
       }
      • Object.clone()方法從原始碼來看也是native方法,但返回為Object型別,所以賦值時將發生強轉,所以效率不如之前兩種。
      // 通過Object.clone()
       int[] array5 = new int[5];
       array5 = array4.clone();
       for (int i = 0; i < array5.length; i++) {
           System.out.print(array5[i]);
       }

其他(感悟、思考等)

  • 這周做完實驗沒有及時總結,因為時間比較久遠,導致有一些錯誤和解決方法都有所遺忘。部分參考資料還是在瀏覽器的歷史記錄中淘到的。以後要對錯誤及時總結,養成良好的學習習慣。

參考資料