20172314 2018-2019-1《程序設計與數據結構》查找與排序實驗報告

課程:《程序設計與數據結構》html

班級: 1723java

姓名: 方藝雯算法

學號:20172314shell

實驗教師:王志強數組

實驗日期:2018年12月3日數據結構

必修/選修: 必修ide

一、實驗內容及要求

  • 實驗查找與排序-1學習

    定義一個Searching和Sorting類,並在類中實現linearSearch(教材P162 ),SelectionSort方法(P169),最後完成測試。
    要求很多於10個測試用例,提交測試用例設計狀況(正常,異常,邊界,正序,逆序),用例數據中要包含本身學號的後四位
    提交運行結果圖。測試

  • 實驗查找與排序-2網站

    重構你的代碼
    把Sorting.java Searching.java放入 cn.edu.besti.cs1723.(姓名首字母+四位學號) 包中(例如:cn.edu.besti.cs1723.G2301)
    把測試代碼放test包中
    從新編譯,運行代碼,提交編譯,運行的截圖(IDEA,命令行兩種)

  • 查找與排序-3

    參考http://www.cnblogs.com/maybe2030/p/4715035.html 在Searching中補充查找算法並測試
    提交運行結果截圖

  • 查找與排序-4

    補充實現課上講過的排序方法:希爾排序,堆排序,二叉樹排序等(至少3個)
    測試實現的算法(正常,異常,邊界)
    提交運行結果截圖
    (3分,若是編寫多個排序算法,即便其中三個排序程序有瑕疵,也能夠酌情得滿分)

  • 查找與排序-5

    編寫Android程序對各類查找與排序算法進行測試
    提交運行結果截圖
    推送代碼到碼雲

實驗過程及結果

實驗3-1

  • 本實驗只須要把之前實現過的Sorting和Searching方法運行一下,並用Junit測試正常,異常,邊界,正序,逆序是否正確便可。這個實驗開始一直搞不清楚異常和邊界是如何斷定的,那種算異常狀況,最後詢問同窗以後解決了。異常測試是查找數組中沒有的目標,因此Junit測試不經過;邊界測試是查找數組中是否有邊界的元素存在,若Junit測試經過,則邊界測試經過。
  • 實驗結果






實驗3-2

  • 本實驗只須要運行一下Sorting和Searching程序就行。因爲虛擬機不能用了,須要從新下,老師說用idea也能夠,因此只有idea的測試。
  • 實驗結果



實驗3-3

  • 在提供的網站中有現成的部分查找算法,也有其餘算法的精細講解,而後按照提供思路實現。主要的問題是斐波那契法,以前沒有學習過,在查找了相關解釋後,理解爲:斐波那契法與折半查找法的思路基本一致,可是區別在於斐波那契法須要構建一個數列提供分割點,其分割點的最初設置是mid = low + F[k-1] -1,緣由是「斐波那契數列的後一項是前兩項之和,這兩項對應查找表的左右兩部分,這時分割點的方式,還有一個問題就是查找表的長度是F(K)-1,緣由是爲了格式上的統一,以方便遞歸或者循環程序的編寫。表中的數據是F(k)-1個,使用mid值進行分割又用掉一個,那麼剩下F(k)-2個。正好分給兩個子序列,每一個子序列的個數分別是F(k-1)-1與F(k-2)-1個,格式上與以前是統一的。否則的話,每一個子序列的元素個數有多是F(k-1),F(k-1)-1,F(k-2),F(k-2)-1個,寫程序會很是麻煩。」
  • 新增的算法,如下是在網上查找到的詳細解釋:
    • 斐波那契查找與折半查找很類似,他是根據斐波那契序列的特色對有序表進行分割的。他要求開始表中記錄的個數爲某個斐波那契數小1,及n=F(k)-1;開始將k值與第F(k-1)位置的記錄進行比較(及mid=low+F(k-1)-1),比較結果也分爲三種:
      • 相等,mid位置的元素即爲所求
      • 大於,low=mid+1,k-=2; (low=mid+1說明待查找的元素在[mid+1,high]範圍內,k-=2 說明範圍[mid+1,high]內的元素個數爲n-(F(k-1))= Fk-1-F(k-1)=Fk-F(k-1)-1=F(k-2)-1個,因此能夠遞歸的應用斐波那契查找。)
      • 小於,high=mid-1,k-=1。(low=mid+1說明待查找的元素在[low,mid-1]範圍內,k-=1說明範圍[low,mid-1]內的元素個數爲F(k-1)-1個,因此能夠遞歸 的應用斐波那契查找。
    • 複雜度分析:最壞狀況下,時間複雜度爲O(log2n),且其指望複雜度也爲O(log2n)。)

    • 代碼

    /*定義斐波那契查找法*/
    public static int FibonacciSearch(int[] a, int n, int key)
    {
        int low = 0;
        int high = n - 1;
        //定義一個斐波那契數組
        int max = 20;
        int[] F = new int[max];
        F[0] = 1;
        F[1] = 1;
        for (int i = 2; i < max; i++) {
            F[i] = F[i - 1] + F[i - 2];
        }
        int k = 0;
        while (n > F[k] - 1)//計算n位於斐波那契數列的位置
            k++;
        int[] temp;//將數組a擴展到F[k]-1的長度
        temp = new int[F[k] - 1];
        for (int x = 0; x < a.length; x++) {
            temp[x] = a[x];
        }
        for (int i = n; i < F[k] - 1; ++i)
            temp[i] = a[n - 1];
        while (low <= high) {
            int mid = low + F[k - 1] - 1;
            if (key < temp[mid]) {
                high = mid - 1;
                k -= 1;
            } else if (key > temp[mid]) {
                low = mid + 1;
                k -= 2;
            } else {
                if (mid < n)
                    return mid; //若相等則說明mid即爲查找到的位置
                else
                    return n - 1; //若mid>=n則說明是擴展的數值,返回n-1
            }
        }
        return -1;
    }
  • 實驗結果

實驗3-4

  • 實現希爾排序,堆排序,二叉樹排序,而後編寫測試類測試正常,異常,邊界,希爾排序和堆排序有寫博客分析過,而二叉樹排序是之前沒有學習過的,但也較好理解。

  • 希爾排序基本思想:假設序列中有n個元素,首先選擇一個間隔gap,將所有的序列分爲gap個子序列,而後分別在子序列內部進行簡單插入排序,獲得一個新的主序列;然後縮小gap,再獲得子序列,對子序列進行簡單插入排序,又再次獲得新的主序列,直到gap=1爲止。在算法中,排序前期,因爲gap值比較大,插入排序的元素個數少,排序快,到了排序後期,因爲前面的排序致使序列已經基本有序,插入排序對於有序的序列效率很高。
//希爾排序
    public static <T extends Comparable<T>> void shellSort(T[] data) {
        if (data == null || data.length <= 1) {
            return;
        }
        int gap = data.length / 2;
        while (gap >= 1) {
            for (int a = 0; a < data.length; a++) {
                for (int b = a; b < data.length - gap; b = b + gap) {
                    if (data[b].compareTo(data[b + gap]) > 0) {
                        T temple = data[b];
                        data[b] = data[b + gap];
                        data[b + gap] = temple;
                    }
                }
            }
            gap = gap / 2;
        }
        String result = "";
        for (int i = 0; i < data.length; i++) {
            result += data[i] + " ";
        }
        System.out.println(result);
    }
  • 堆排序基本思想:把待排序的元素按照大小在二叉樹位置上排列,排序好的元素要知足:父節點的元素要大於等於其子節點;這個過程叫作堆化過程,若是根節點存放的是最大的數,則叫作大根堆;若是是最小的數,天然就叫作小根堆了。根據這個特性(大根堆根最大,小根堆根最小),就能夠把根節點拿出來,而後再堆化下,再把根節點拿出來,,,,循環到最後一個節點,就排序好了。整個排序主要核心就是堆化過程,堆化過程通常是用父節點和他的孩子節點進行比較,取最大的孩子節點和其進行交換;可是要注意這應該是個逆序的,先排序好子樹的順序,而後再一步步往上,到排序根節點上。而後又相反(由於根節點也多是很小的)的,從根節點往子樹上排序。最後才能把全部元素排序好。
//堆排序
    public static <T extends Comparable<T>> void heapSort(T[] data) {
        ArrayHeap<T> temp = new ArrayHeap<T>();
        for (int i = 0; i < data.length; i++)
            temp.addElement(data[i]);
        int num = 0;
        while (!(temp.isEmpty())) {
            data[num] = temp.removeMin();
            num++;
        }
    }
  • 二叉樹排序基本思想:使用第一個元素做爲根節點,若是以後的元素比第一個小,則放到左子樹,不然放到右子樹,以後按中序遍歷。
//二叉樹排序
    public static <T extends Comparable<T>> void binarytreeSort(T[] data) {
        AVLTree tree = new AVLTree();
        for (int i = 0; i < data.length; i++) {
            tree.addElement(data[i]);
        }
        tree.printTree2();
    }
  • 實驗結果




實驗3-5

  • 因爲這兩個算法牽扯到好多類,差很少移到AS上幾十個類,而後對方法進行測試,添加查找和排序兩個按鈕,並有一個顯示框顯示用不一樣方法的結果。
  • 實驗結果




遇到的問題及解決

  • 問題一:在編寫測試類時,測試用的數組定義int型的就顯示:須要Integer類型,找到int類型。
  • 問題一解決:我原本覺得這兩種類型是差很少的,雖然一直不知道這兩個的具體區別而後上網查找了兩者區別,參考完全讓你明白 Integer 類和 int 基本數據類型的區別,其基本API爲:




  • 兩者區別
    • Integer是int的包裝類,int則是java的一種基本數據類型
    • Integer變量必須實例化後才能使用,而int變量不須要
    • Integer實際是對象的引用,當new一個Integer時,其實是生成一個指針指向此對象;而int則是直接存儲數據值
    • Integer的默認值是null,int的默認值是0

因此我把數組定義類型統一爲Integer類型就能夠了。

其餘

此次實驗的實驗五記得是比較麻煩的一個,主要牽扯的類太多,常常出現錯誤要從不少以前的類裏排查,會比較麻煩。但在修改過程當中也學習到了新的知識。此次實驗主要是關於排序和查找。也學會了更多的算法,溫習了Junit的使用。

參考

相關文章
相關標籤/搜索