20172323 2018-2019-1 《程序設計與數據結構》實驗三報告

課程:《程序設計與數據結構》
班級: 1723
姓名: 王禹涵
學號:20172323
實驗教師:王志強
實驗日期:2018年11月20日
必修/選修: 必修html

1.實驗內容

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


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


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


查找與排序-4
補充實現課上講過的排序方法:希爾排序,堆排序,二叉樹排序等(至少3個)
測試實現的算法(正常,異常,邊界)
提交運行結果截圖數組


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

2. 實驗過程及結果

查找與排序-1

  • 第一部分代碼類不太難,直接書上的代碼copy一會兒就行了。難點在於測試類的編寫,JUnit測試確實是好久沒有寫過了,可是依葫蘆畫瓢仍是差很少解決了
    測試時須要考慮題目要求的正常,異常,邊界,正序,逆序五種狀況,因此在數組的賦值上包含了正整數、負整數、小數和字母幾種狀況的數組。在查找和排序方面都測試了查找邊界值和查找不存在的值,正序的一串數和逆序的一串數的排序。
    測試結果以下

測試的代碼(參照上學期的資源)性能

public void testSearch1() {
                assertEquals(true, SearchingSorting.linearSearch(search1, 0, 6, 2323));
        }

左下角反映了測試經過與否單元測試


查找與排序-2

第二部分看似簡單,其實花費了我很多時間。
首先把代碼類放在一個新的包內,另外一個測試類其實應該放在專門的test包內,而不該該隨便就在src下建一個test包,這點在單元測試的講解中有提到過,即學習

test目錄中放的也是Java代碼,但IDEA不知道test中放的是源代碼。在命令行中咱們知道要設置SOURCEPATH環境變量,在IDEA中咱們右鍵單擊test目錄,在彈出的菜單中選擇Mark Directory as->Test Sources Root就能夠了測試

另外一個在命令行上測試,我重寫了測試方法,沒有再用JUnit測試,由於屢次使用cmd運行都提示找不到或沒法加載主類,重寫以後,找到編譯文件所在的位置java SSTest1。特別奇怪的一個地方是,我只能在編譯文件所在的包外運行該代碼,若是是在包內又會報錯。

查找與排序-3

須要理解幾種查找算法,這部分比較困難,可是須要本身作的地方不難,由於代碼基本都給了出來。重點須要新學的是斐波拉契查找和插值查找

  • [插值查找] 基於二分查找算法,將查找點的選擇改進爲自適應選擇,能夠提升查找效率。對於表長較大,而關鍵字分佈又比較均勻的查找表來講,插值查找算法的平均性能比折半查找要好的多。反之,數組中若是分佈很是不均勻,那麼插值查找未必是很合適的選擇。
    代碼分析
int InsertionSearch(int a[], int value, int low, int high)
{
    int mid = low+(value-a[low])/(a[high]-a[low])*(high-low);
    if(a[mid]==value)
        return mid;
    if(a[mid]>value)
        return InsertionSearch(a, value, low, mid-1);
    if(a[mid]<value)
        return InsertionSearch(a, value, mid+1, high);
}

其餘地方都和折半查找相似,主要是定位查找點的方法int mid = low+(value-a[low])/(a[high]-a[low])*(high-low);很差理解

  • 由於插值查找適合分佈較爲均勻的數組,因此就假定有一個存儲值1-20的數組,對應索引值分別爲0~19.如今要查找2這個值,對應索引值爲1,適合插值查找這種方法。此時
value = 2;
low = 0;
high = 19;
mid = 1;

此時a[mid] = a[1] = 2,就查找到了須要的元素。
我想這個算法的核心在於(high - low)反映了要查找的數組的長度,(value-a[low])/(a[high]-a[low])定位了查找點大體在數組幾分之幾的位置上(由於數組內的元素分佈是比較均勻的)。

  • [斐波那契查找] 二分查找的一種提高算法,經過運用黃金比例的概念在數列中選擇查找點進行查找,提升查找效率。
  • 斐波那契查找與折半查找很類似,他是根據斐波那契序列的特色對有序表進行分割的。他要求開始表中記錄的個數爲某個斐波那契數小1,及n=F(k)-1;。
  • 代碼分析
    寫出這代碼的核心思想是什麼我還沒法理解,只能跟着代碼走一遍。首先他須要將數組內的元素複製到一個斐波那契數長度的數組中,多出來的位置所有填充原數組的最後一位。而後經過變換mid的值不斷縮小查找的範圍,若是查找值小於temp[mid]的值,說明待查找的元素在[low,mid-1]範圍內,反之說明待查找的元素在[mid+1,high]範圍內。這裏恰好前面一部分與後面一部分的比值約爲0.618,將數組擴展到F[k]-1長度也是出於此考慮,以後相似於二分查找不斷縮小範圍逼近查找值。但最後的值有可能在擴展的數組中,須要返回n-1(爲何最多隻會找到擴展數組的第一個位置尚未弄明白)

  • 代碼
  • 測試


查找與排序-4

題目給出的三種排序算法,堆排序在以前的項目中已經有了實現的方法,二叉樹排序也不困難,只須要將數組內的元素依次序添加進二叉樹中,而後按照中序輸出的方法也能達到排序的效果。主要是希爾排序沒有遇到過

  • 希爾排序是把記錄按下標的必定增量分組,對每組使用直接插入排序算法排序;隨着增量逐漸減小,每組包含的關鍵詞愈來愈多,當增量減至1時,整個文件恰被分紅一組,算法便終止。
  • 實例講解,從網上找到的圖示,比我瞎講應該要有用得多

代碼實現

public static void sort(Integer[] data){
        if(data == null || data.length <= 1){
            return;
        }
        //增量
        int incrementNum = data.length/2;
        while(incrementNum >=1){
            for(int i=0;i<data.length;i++){
                //進行插入排序
                for(int j=i;j<data.length-incrementNum;j=j+incrementNum){
                    if(data[j]>data[j+incrementNum]){
                        int temple = data[j];
                        data[j] = data[j+incrementNum];
                        data[j+incrementNum] = temple;
                    }
                }
            }
            //設置新的增量
            incrementNum = incrementNum / 2;
        }
        String str = "";
        for (int n = 0; n < data.length; n++){
            str += data[n] + " ";
        }
        System.out.println(str);
    }

從算法的實現能夠看出,希爾排序是有些相似與間隔排序的,它經過設置增量,將相同間隔的元素放在一堆而後排好序,再將增量擴大,直至全部元素都在一個數組中且進行排序,這時即排序完成


查找與排序-5

這部分還算比較簡單,就把以前的代碼移動到AS裏,不過同時還須要移動一大堆的相關文件過去。我比較省事地只添加了兩個按鈕,一鍵就調用全部的排序或者查找方法。而後textview.setView()中輸出一大堆返回信息,如圖

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

問題1:進行插值查找時,查找一個數組中不存在的數,出現以下的錯誤

問題1解決方案:debug以後發如今進行分區域的時候,會出現low>high的狀況,而程序沒有能處理這種狀況的能力。參照斐波那契查找代碼中對於出現low>high狀況的處理,在外部加上一個while循環,當出現low>high時,直接return -1這樣一來錯誤狀況就處理掉了。


問題2:int型與Interger型的區別
問題2解決方案:之前歷來沒有考慮到過這個問題(多是沒有認真學習的緣由),總之到此次實驗時才發覺他倆好像是有點小小的區別,由於第一部分的實驗新創的數組都是Comparable型的,但後來由於實驗須要有一些方法有須要轉換成int型,因此數值的比較方法也須要大改。按理說data[min].compareTo(data[j]) > 0就須要改爲data[min] > data[j]可是改爲Interger型這些都不須要改變。因此查了一下他倆的一些區別
Integer 類和 int 的區別

  ①、Integer 是 int 包裝類,int 是八大基本數據類型之一(byte,char,short,int,long,float,double,boolean)

  ②、Integer 是類,默認值爲null,int是基本數據類型,默認值爲0;

  ③、Integer 表示的是對象,用一個引用指向這個對象,而int是基本數據類型,直接存儲數值。

Interger型至關因而一個包裝盒,裏面包含的是int型的對象,因此可使用CompareTo的方法。

4.其餘

此次實驗相對來講理論的學習很重要,要優於本身動手寫代碼。經過此次實驗,我對幾種查找和排序算法都有了更深入的瞭解,同時還了解了一些沒有接觸過的查找算法。比較意外的一個收穫是,我對一些數據類型的瞭解也更加深入了

5.參考資料

相關文章
相關標籤/搜索