20162320劉先潤大二 實驗三 查找與排序

實驗涉及代碼

SearchingBSTNodeSortingLinkedBinarySearchTreeSearchingtestSortTestphp


查找與排序-1

實驗目的:測試·SearchingSorting.的方法,要求各類狀況測試,排序須要正序和逆序

測試過程:

  • 1.首先測試Searching在數組依次中添加三、八、十二、3四、5四、8四、9一、1十、一、0十個元素
Comparable[] comparables = {1,0,3, 8, 12, 34, 54, 84, 91, 81,110};
  • 2.測試二分查找的各類狀況,首先測試數組中並未存在的45,而後測試數組中的54,即正常和異常的狀況。因爲該查找方法是返回值,因此預測結果應該爲null與54,測試結果以下,測試成功。
Comparable result1 = Searching.binarySearch(comparables, 45);
        System.out.println(result1);  
 Comparable result2 = Searching.binarySearch(comparables, 54);
            System.out.println(result2 );

  • 3.而後測試Sorting方法,一樣建立數字3, 12, 8, 34, 54, 84, 110, 91順序不一樣的數組
Comparable[] lxr = {3, 12, 8, 34, 54, 84, 110, 91};
  • 4.利用快速排序,每次比較都要把數據跟個成兩個部分,將每次比較交換到左邊的元素利用循環的Comparable方法提取出來,獲得正序。利用冒泡排序,修改其中一部分源碼爲if (data[scan].compareTo(data[scan + 1]) < 0),即經過比較將小的值放到右邊,獲得逆序。測試截圖以下。
Sorting.quickSort(lxr, 0, lxr.length - 1);
     for (Comparable lxrs : lxr) {
            System.out.print(lxrs + " ");
        }


查找與排序-2

實驗目的:重構代碼,在Idea和命令行兩種方式運行

實驗過程:

  • 1.把SortingSearching放入 cn.edu.besti.cs1623.劉先潤2320包中,從新編譯並運行。
  • 2.實驗結果見結果連接

查找與排序-3

實驗目的:補充Searching的查找算法,並進行測試

實驗過程:

  • 0.全部查找算法都會測試正常和異常狀況,查找所針對的數組是包含三、八、十二、3四、5四、8四、9一、1十、一、0十個元素的。備註:樹表查找是在二叉查找樹中已經實現,不在贅述,能夠參見個人代碼LinkedBinarySearchTreeLinkedBinarySearchTreeTest
  • 1.插值查找(Interpolation Search)算法,是根據要查找的元素 key 與查找表中最大最小記錄的關鍵字比較後的查找方法,其核心就在於插值的計算公式(key - a[low])/(a[high] - a[low])。個人實現思路是插值時將插入值比較數組中的中位數,若是比中位數小則繼續比較中位數左邊的數內部的中位數,依次查找,最後返回查找的值在數組中的下標。若是數組中沒有此元素則返回不表明下標的值-1。
public static int interpolationSearch(int[] a, int key) {
        int low, mid, high;
        low = 0;// 最小下標
        high = a.length - 1;// 最大小標
        while (low < high) {
            mid = low + (high - low) * (key - a[low]) / (a[high] - a[low]);
            // mid = (high + low) / 2;// 折半下標
            if (key > a[mid]) {
                low = mid + 1; // 關鍵字比 折半值 大,則最小下標 調成 折半下標的下一位
            } else if (key < a[mid]) {
                high = mid - 1;// 關鍵字比 折半值 小,則最大下標 調成 折半下標的前一位
            } else {
                return mid; // 當 key == a[mid] 返回 折半下標
            }
        }
        return -1;
    }

  • 2.斐波那契查找(Fibonacci Search)算法,該算法和二分查找有些相似,不過二分查找是對半拆分進行查找,而斐波那契查找是根據黃金分割比例拆分的,而此處主要是用到了它的一條性質:前一個數除以相鄰的後一個數,比值無限接近黃金分割。個人算法實現思路是當查找的元素key小於黃金分割位置元素,則繼續查找前半部分,指針往大移動。令k爲黃金分割值下標 ,f[k] = f[k-1] + f[k-2]((所有元素) = (前半部分)+(後半部分)),由於前半部分有f[k-1]個元素,則繼續拆分f[k-1] = f[k-2] + f[k-3]成立 ,即在f[k-1]個元素的前半部分f[k-2]中繼續查找,因此k = k - 1, 則下次循環mid = low + f[k - 1 - 1] - 1; 當查找的元素key大於黃金分割位置元素時,則查找後半部分,指針往小移動,由於後半部分有f[k-2]個元素, 則繼續拆分f[k-2] = f[k-3] + f[k-4]成立,即在f[k-2]個元素的前半部分f[k-3]繼續查找,因此k = k - 2,則下次循環mid = low + f[k - 2 - 1] - 1。如圖所示
public static int fibonaciSearch(int[] b, int key) {
     int[] f = {-1,0,3, 8, 12, 34, 54, 84, 91, 110};
    int low1, mid1, high1, k;
    low1 = 0;
    high1 = b.length - 1;
    k = 0;
    while (high1 > f[k] - 1)
        k++;
    b = Arrays.copyOf(b, f[k]);
    for (int i = high1 + 1; i < f[k]; i++) {
        b[i] = b[high1];
    }
    while (low1 <=high1) {
        mid1 = low1 + f[k - 1] - 1;

        if (key < b[mid1]) {
            high1 = mid1 - 1;
            k = k - 1;
        } else if (key > b[mid1]) {
            low1 = mid1 + 1;
            k = k - 2;
        } else {
            if (mid1 <= high1)
                return mid1;
            else
                return high1;

        }
    }
    return -1;
}

  • 3.分塊查找(BlockSearch)算法,分塊查找是改進自折半查找和順序查找的方法,把一個數據分爲若干個塊(通常按照大小區間來分),按照元素大小無序地放入塊中,第n塊中的每一個元素必定比第n-1塊中的任意元素大。個人實現思路:建立一個數組分爲12個塊容器,定義每一個塊的範圍值,總塊的範圍值必須包含數組最大與最小值所包含的範圍,利用二分查找的方法將元素進行比較並放入不一樣的塊中。最後定義一個打印方法,根據分好的塊,打印出每一個塊的元素及塊索引,並打印出查找的元素在哪一個塊已經在塊中的索引。
public static class BlockSearch {


        private int[] index; //創建索引
        private ArrayList[] list;


        public BlockSearch(int[] index) {
            if (index != null && index.length != 0) {
                this.index = index;
                this.list = new ArrayList[index.length];

                for (int i = 0; i < list.length; i++) {
                    list[i] = new ArrayList();//初始化容器
                }
            } else {
                throw new Error("index cannot be null or empty");
            }
        }
        public void insert(int value) {

            int i = binarysearch(value);
            list[i].add(value);
        }


        private int binarysearch(int value) {
            int start = 0;
            int end = index.length;
            int mid = -1;
            while (start <= end) {
                mid = (start + end) / 2;
                if (index[mid] > value) {
                    end = mid - 1;
                } else {
                    start = mid + 1;
                }
            }

            return start;
        }

        public String search(int data) {
            int i = binarysearch(data);
            String q1="查無此數";
            String q2="成功找到";
            for (int j = 0; j < list[i].size(); j++) {
                if (data == (int) list[i].get(j)) {
                    System.out.println(String.format("查找元素爲第: %d塊  第%d個 元素", i + 1, j + 1));
                    return q2;
                }
            }
            return q1;
        }

        public void printAll() {
            for (int i = 0; i < list.length; i++) {
                ArrayList l = list[i];
                System.out.print("塊" + i + ":");

                for (int j = 0; j < l.size(); j++) {
                    System.out.print(l.get(j) + "  ");
                }
            }
        }
    }

  • 4.哈希查找(HashSearch),是經過計算數據元素的存儲地址進行查找的一種方法。哈希查找的本質是先將數據映射成它的哈希值,其主要難點在於構建一個哈希表。個人代碼實現思路:首先利用給定的數組建立哈希表,經過創建函數將其元素保存在對應的地址中,在查找哈希表的過程當中,當查找到這鏈表時,採用線性查找方法。若是兩個元素通過計算所獲得的哈希值相同,則在哈希表中爲後插入的數據元素另外選擇一個表項。當查找哈希表時,若是沒有在第一個哈希表中找到該元素,程序就會繼續日後查找,直到找到一個符合查找要求的數據元素,或者遇到一個空的表項。最後返回該元素在哈希表中的索引。  
public static int searchHash(int[] hash, int hashLength, int key) {
        int hashAddress = key % hashLength;

        while (hash[hashAddress] != 0 && hash[hashAddress] != key) {
            hashAddress = (++hashAddress) % hashLength;
        }
        if (hash[hashAddress] == 0)
            return -1;
        return hashAddress;}


    public static void insertHash(int[] hash, int hashLength, int data) {

        int hashAddress = data % hashLength;
        while (hash[hashAddress] != 0) {
            hashAddress = (++hashAddress) % hashLength;
        }
        hash[hashAddress] = data;
    }


查找與排序-4

實驗目的:補充實現希爾排序,堆排序,桶排序,二叉樹排序並測試實現的算法(正常,異常,邊界)

實驗過程:

  • 1.堆排序的排序於二叉樹排序相似,利用堆頂記錄的是堆中的最大這一特質,使得每次從無序中選擇最大記錄變得簡單。堆排序是先將一組元素一項項地插入到堆中,而後一次刪除一個,由於元素最早從堆中刪除(在最大堆中),從堆中獲得的元素序列將是有序序列,並且是降序的,相似地,一個最小堆可用來獲得升序的排序結果。個人實現思路是首先初始建堆,array[0]爲第一趟值最大的元素, 將堆頂元素和堆低元素交換,即獲得當前最大元素正確的排序位置,最後將剩餘的元素整理成堆。每次將堆的堆頂記錄輸出;同時調整剩餘的記錄,使他們從新排成一個堆。重複以上過程。
public int[] heapSort(int[] array){
         array = buildMaxHeap(array); 
         for(int i=array.length-1;i>1;i--){  
             int temp = array[0]; 
             array[0] = array[i];
             array[i] = temp;
             adjustDownToUp(array, 0,i);  
         }
         return array;
     }

  • 2.二叉樹排序,該排序方式是根據二叉排序樹的性質——結點左孩子小於結點值、右孩子大於結點值來實現排序的。因爲該算法在17章的教材中早就已經實現,因此就很少闡述。主要點在於在二叉排序樹添加元素的操做,放入書中成爲根結點並進行比較入左子樹仍是右子樹的代碼實現。
public void add (T item) {
    if (item.compareTo(element) < 0)
        if (left == null)
            left = new BSTNode (item);
    else
        ((BSTNode)left).add (item);
    else
        if (right == null)
            right = new BSTNode (item);
    else
        ((BSTNode)right).add (item);

  • 3.桶排序工做的原理是將數組分到有限數量的桶子裏。每一個桶子再個別排序(有可能再使用別的排序算法或是以遞歸方式繼續使用桶排序進行排序)。個人實現思路:根據數組的長度建立桶的數量,而後遍歷數組,將數組的元素放入桶中,而後再排序桶,最後將桶中的元素打印出來。
public static void bucketSort(int[] arr){

        int max = Integer.MIN_VALUE;
        int min = Integer.MAX_VALUE;
        for(int i = 0; i < arr.length; i++){
            max = Math.max(max, arr[i]);
            min = Math.min(min, arr[i]);
        }
        //桶數
        int bucketNum = (max - min) / arr.length + 1;
        ArrayList<ArrayList<Integer>> bucketArr = new ArrayList<>(bucketNum);
        for(int i = 0; i < bucketNum; i++){
            bucketArr.add(new ArrayList<Integer>());
        }

        for(int i = 0; i < arr.length; i++){
            int num = (arr[i] - min) / (arr.length);
            bucketArr.get(num).add(arr[i]);
        }
        for(int i = 0; i < bucketArr.size(); i++){
            Collections.sort(bucketArr.get(i));
        }
        System.out.println(bucketArr.toString());

  • 4.希爾排序,是插入排序的改進方法,希爾排序是把記錄按下標的必定增量分組,對每組使用直接插入排序算法排序;隨着增量逐漸減小,每組包含的關鍵詞愈來愈多,當增量減至1時,整個文件恰被分紅一組,算法便終止。個人實現思路將數組的元素放入一個初始數組中,而後將數組中每一個元素對應其相隔n個索引的數組元素,進行比較大小,小的元素將其交換至左邊,而後每完成一次操做索引數n遞減,最後獲得一個有序數列,並將其輸出。
public static void shellSortSmallToBig(int[] data) {
        int j = 0;
        int temp = 0;
        for (int increment = data.length / 2; increment > 0; increment /= 2) {
            System.out.println();
            for (int i = increment; i < data.length; i++) {
                // System.out.println("i:" + i);
                temp = data[i];
                for (j = i - increment; j >= 0; j -= increment) {
                    if (temp < data[j]) {
                        data[j + increment] = data[j];
                    } else {
                        break;
                    }
                }
                data[j + increment] = temp;
            }

                for (int i = 0; i < data.length; i++)
                    System.out.print(data[i] + " ");
            }
        }

相關文章
相關標籤/搜索