天天看點

結構與算法(04):排序規則與查找算法一、遞歸算法二、排序算法三、查找算法四、源代碼位址

本文源碼: 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);
    }
}           

遞歸圖解:

結構與算法(04):排序規則與查找算法一、遞歸算法二、排序算法三、查找算法四、源代碼位址

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

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

遞歸算法的條件必須要不斷接近退出條件,不然很容易出現無限循環導緻記憶體溢出異常問題。

二、排序算法

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

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           

繼續閱讀