結構與演算法(04):排序規則與查詢演算法

知了一笑發表於2020-09-21

本文原始碼:GitHub·點這裡 || GitEE·點這裡

一、遞迴演算法

遞迴就是方法自己呼叫自己,每次呼叫時傳入不同的變數,可以讓程式碼變得簡潔。遞迴演算法在電腦科學中是指一種通過重複將問題分解為同類的子問題而解決問題的方法,遞迴式方法可以被用於解決很多的電腦科學問題,因此它是電腦科學中十分重要的一個概念。

基礎案例:通過遞迴列印資料;

public class M01_Recursion {
    public static void main(String[] args) {
        printNum(3);
    }
    private static void printNum (int num){
        if (num > 1){
            printNum(num-1);
        }
        System.out.println("num="+num);
    }
}

遞迴圖解

基於棧結構的特點,遞迴呼叫會形成如上的結構,當所有遞迴方法入棧成功後,在依次執行出棧動作,列印資料結果。

在實際開發中遞迴經常用來接近樹結構問題,階乘演算法,排序查詢等數學類問題。

遞迴演算法的條件必須要不斷接近退出條件,不然很容易出現無限迴圈導致記憶體溢位異常問題。

二、排序演算法

排序演算法就是使一組資料記錄,按照特定的排序策略,遞增或遞減的排列起來的操作;常用的排序演算法:氣泡排序,選擇排序,插入排序,希爾排序,歸併排序,快速排序,基數排序等;排序演算法選擇:不同的排序業務可以通過多種演算法測試,複雜度低,耗時短的優先使用。

1、氣泡排序

通過對排序序列依次比較相鄰元素的值,若發現逆序則交換,使值較大的元素逐漸從前移向後部,演算法的名字由來是因為越小的元素會經由排序交換慢慢浮到數列的一端,就如同碳酸飲料中二氧化碳的氣泡最終會上浮到頂端一樣,故名氣泡排序。

public class M02_Bubble {
    public static void main(String[] args) {
        int[] arr = {3,7,5,9,6};
        bubbleSort(arr);
        for (int num:arr){
            System.out.println(num);
        }
    }
    public static void bubbleSort(int[] arr) {
        // 宣告臨時變數
        int temp = 0;
        // 排序總趟數
        for (int i = 0; i < arr.length - 1; i++) {
            // 元素交換
            for (int j = 0; j < arr.length - 1 - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    // 位置交換
                    temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }
}

核心思路

排序趟數只有多少元素,理論上要進行處理的次數;每個元素的位置交換都需要一次完整對比,外層迴圈總控制。內層迴圈交換單個元素位置。

2、選擇排序

選擇排序原理:第一次從待排序的資料元素中選出最小(或最大)的一個元素,存放在序列的起始位置,然後再從剩餘的未排序元素中尋找到最小(大)元素,然後放到已排序的序列的末尾。以此類推,直到全部待排序的資料元素的個數為零。

public class M03_Selection {
    public static void main(String[] args) {
        int[] arr = {30,70,50,90,60};
        selectionSort(arr);
    }
    public static void selectionSort (int[] arr){
        for (int i = 0; i < arr.length - 1; i++) {
            int minIndex = i;
            int minData = arr[i];
            for (int j = i + 1; j < arr.length; j++) {
                // 假設最小值判斷
                if (minData > arr[j]) {
                    // 交換小值
                    minData = arr[j];
                    // 重置 minIndex,遞增
                    minIndex = j;
                }
            }
            // 最小值交換放在arr[0]位置
            if (minIndex != i) {
                arr[minIndex] = arr[i];
                arr[i] = minData ;
            }
            System.out.println("第"+(i+1)+"輪排序:"+Arrays.toString(arr));
        }
    }
}

輸出結果

第1輪排序:[30, 70, 50, 90, 60]
第2輪排序:[30, 50, 70, 90, 60]
第3輪排序:[30, 50, 60, 90, 70]
第4輪排序:[30, 50, 60, 70, 90]

3、插入排序

基本思想是將一個記錄插入到已經排好序的有序表中,排序過程中每次從無序表中取出第一個元素,把它依次與有序表元素進行比較,將它插入到有序表中的適當位置,使之成為新的有序表。在實現過程使用雙層迴圈,外層迴圈對除了第一個元素之外的所有元素,內層迴圈對當前元素前面有序表進行待插入位置查詢,並進行移動。

public class M04_Insert {
    public static void main(String[] args) {
        int[] arr = {10,40,90,20,80};
        insertSort(arr);
    }
    public static void insertSort (int[] arr) {
        int insertValue = 0;
        int insertIndex = 0;
        for (int i = 1; i < arr.length; i++) {
            // 待插入數的值和下標
            insertValue = arr[i];
            insertIndex = i - 1;
            // 寫入位置
            while (insertIndex >= 0 && insertValue < arr[insertIndex]) {
                arr[insertIndex + 1] = arr[insertIndex];
                insertIndex--;
            }
            if (insertIndex + 1 != i) {
                arr[insertIndex + 1] = insertValue;
            }
            System.out.println("第" + i + "輪插入排序:"+Arrays.toString(arr));
        }
    }
}

輸出結果

第1輪插入排序:[10, 40, 90, 20, 80]
第2輪插入排序:[10, 40, 90, 20, 80]
第3輪插入排序:[10, 20, 40, 90, 80]
第4輪插入排序:[10, 20, 40, 80, 90]

三、查詢演算法

查詢演算法是指在一組元素中尋找一個特定的資訊元素,在計算機應用中,查詢是常用的基本運算,例如編譯程式中符號表的查詢;常用的查詢演算法有:順序查詢,二分查詢,插值查詢,斐波那契查詢。

1、順序查詢

順序查詢是按照序列原有順序對一組元素進行遍歷,並與要查詢的元素逐個比較的基本查詢演算法。

public class M05_OrderFind {
    public static void main(String[] args) {
        String[] arr = {"first","second","third"};
        System.out.println(seqSearch(arr,"second"));
    }
    public static int seqSearch(String[] arr, String value) {
        // 陣列下標,-1代表沒有
        int findIndex = -1 ;
        // 遍歷並逐個對比
        for (int i = 0; i < arr.length; i++) {
            if(value.equals(arr[i])) {
                return i ;
            }
        }
        return findIndex ;
    }
}

2、二分查詢

二分查詢也稱折半查詢(Binary Search),它是一種效率較高的查詢方法。但是,折半查詢要求線性表必須採用順序儲存結構,而且表中元素按關鍵字有序排列。

public class M06_BinaryFind {
    public static void main(String[] args) {
        int arr[] = { 10, 20, 30, 40, 50 };
        int index = binarySearch (arr, 0, arr.length - 1, 40);
        System.out.println("index="+index);
    }
    public static int binarySearch(int[] arr, int leftIndex, int rightIndex, int findValue) {
        // leftIndex > rightIndex,沒有查到
        if (leftIndex > rightIndex) {
            return -1;
        }
        int midIndex = (leftIndex + rightIndex) / 2;
        int midValue = arr[midIndex];
        // 向左遞迴
        if (findValue < midValue) {
            return binarySearch(arr, leftIndex, midIndex - 1, findValue);
        // 向右遞迴
        } else if (findValue > midValue) {
            return binarySearch(arr, midIndex + 1, rightIndex, findValue);
        // 直接找到
        } else {
            return midIndex;
        }
    }
}

如果要查詢的元素是沒有順序的,可以基於上述模組二中的排序演算法,先排序再查詢。

四、原始碼地址

GitHub·地址
https://github.com/cicadasmile/model-arithmetic-parent
GitEE·地址
https://gitee.com/cicadasmile/model-arithmetic-parent

推薦閱讀:程式設計體系整理

序號 專案名稱 GitHub地址 GitEE地址 推薦指數
01 Java描述設計模式,演算法,資料結構 GitHub·點這裡 GitEE·點這裡 ☆☆☆☆☆
02 Java基礎、併發、物件導向、Web開發 GitHub·點這裡 GitEE·點這裡 ☆☆☆☆
03 SpringCloud微服務基礎元件案例詳解 GitHub·點這裡 GitEE·點這裡 ☆☆☆
04 SpringCloud微服務架構實戰綜合案例 GitHub·點這裡 GitEE·點這裡 ☆☆☆☆☆
05 SpringBoot框架基礎應用入門到進階 GitHub·點這裡 GitEE·點這裡 ☆☆☆☆
06 SpringBoot框架整合開發常用中介軟體 GitHub·點這裡 GitEE·點這裡 ☆☆☆☆☆
07 資料管理、分散式、架構設計基礎案例 GitHub·點這裡 GitEE·點這裡 ☆☆☆☆☆
08 大資料系列、儲存、元件、計算等框架 GitHub·點這裡 GitEE·點這裡 ☆☆☆☆☆

相關文章