【算法】八大排序

八大排序算法-Java實現

1. 插入排序

2. 希爾排序

3. 選擇排序

4. 堆排序

5. 冒泡排序

6. 快速排序

7. 歸併排序

8. 基數排序


插入排序

代碼實現:
//通過冒泡的方法進行插入排序
public static void sort(int[] a){
    for(int i = 0; i< a.length -1; i++){
        for(int j = i + 1; j>0; j--){
            if(a[j]<a[j-1]){
                int temp = a[j];
                a[j] = a[j-1];
                a[j-1] = temp;
            }
        }
    }
}
//通過將較大的元素都向右移動而不總是交換兩個元素
//此方法優於前者
public static void sort(int[] a){
    for(int i = 1; i< a.length; i++){
        int num = a[i];
        int j;
        for(j = i ; j>0 && num < a[j-1]; j--){
            a[j] = a[j-1];
        }
        a[j] = num;
    }
}

希爾排序

希爾排序,也稱爲遞減增量排序算法,是插入排序的一種更加高效的改進版本。(非穩定排序算法)

  1. 插入排序在對幾乎已經排好序的數據進行操作的時候,效率高,可以達到現行排序的效率。
  2. 一般來說比較低效,因爲插入排序每次只能將數據移動一格。
代碼實現:
```java public static void sort(int[] a) { int length = a.length; int h = 1; while (h < length / 3) h = 3 * h + 1; for (; h >= 1; h /= 3) { for (int i = 0; i < a.length - h; i += h) { for (int j = i + h; j > 0; j -= h) { if (a[j] < a[j - h]) { int temp = a[j]; a[j] = a[j - h]; a[j - h] = temp; } } } } } ```

選擇排序

選擇排序(Selection sort)是一種簡單直觀的排序算法。它的工作原理如下。首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然後,再從剩餘未排序元素中繼續尋找最小(大)元素,然後放到已排序序列的末尾。以此類推,直到所有元素均排序完畢。

代碼實現:
public static void sort(int[] a) {
    for (int i = 0; i < a.length; i++) {
        int min = i;
        //選出之後待排序中值最小的位置
        for (int j = i + 1; j < a.length; j++) {
            if (a[j] < a[min]) {
                min = j;
            }
        }
        //最小值不等於當前值時進行交換
        if (min != i) {
            int temp = a[i];
            a[i] = a[min];
            a[min] = temp;
        }
    }
}

堆排序

代碼實現:

(沒看懂!)以後有時間再看看。


public static void sort(int[] a) {

    for (int i = a.length - 1; i > 0; i--) {
        max_heapify(a, i);

        //堆頂元素(第一個元素)與Kn交換
        int temp = a[0];
        a[0] = a[i];
        a[i] = temp;
    }
}

/***
 *
 *  將數組堆化
 *  i = 第一個非葉子節點。
 *  從第一個非葉子節點開始即可。無需從最後一個葉子節點開始。
 *  葉子節點可以看作已符合堆要求的節點,根節點就是它自己且自己以下值爲最大。
 */
public static void max_heapify(int[] a, int n) {
    int child;
    for (int i = (n - 1) / 2; i >= 0; i--) {
        //左子節點位置
        child = 2 * i + 1;
        //右子節點存在且大於左子節點,child變成右子節點
        if (child != n && a[child] < a[child + 1]) {
            child++;
        }
        //交換父節點與左右子節點中的最大值
        if (a[i] < a[child]) {
            int temp = a[i];
            a[i] = a[child];
            a[child] = temp;
        }
    }
}

冒泡排序

代碼實現:
public static void sort(int[] a) {
    //外層循環控制比較的次數
    for (int i = 0; i < a.length - 1; i++) {
      //內層循環控制到達位置
        for (int j = 0; j < a.length - i - 1; j++) {
            //前面的元素比後面大就交換
            if (a[j] > a[j + 1]) {
                int temp = a[j];
                a[j] = a[j + 1];
                a[j + 1] = temp;
            }
        }
    }
}

快速排序

代碼實現:

快速排序的基本思想: 挖坑填數 + 分治法

快速排序使用分支發策略來把一個串行(list)分爲兩個子串行。

它是處理數據最快的排序算法之一。

代碼實現:

public static void sort(int[] a, int low, int high) {
    //已經排完
    if (low >= high) {
        return;
    }
    int left = low;
    int right = high;

    //保存基準值
    int pivot = a[left];
    while (left < right) {
        //從後向前找到比基準小的元素
        while (left < right && a[right] >= pivot)
            right--;
        a[left] = a[right];
        //從前往後找到比基準大的元素
        while (left < right && a[left] <= pivot)
            left++;
        a[right] = a[left];
    }
    // 放置基準值,準備分治遞歸快排
    a[left] = pivot;
    sort(a, low, left - 1);
    sort(a, left + 1, high);
}

歸併排序

代碼實現:

歸併排序是建立在歸併操作上的一種有效的排序算法。是一個採用分治法的一個非常典型的應用,且各層分治遞歸可以同時進行。

public class Merge {

    //歸併所需的輔助數組
    private static int[] aux;

    public static void sort(int[] a) {
        //一次性分配空間
        aux = new int[a.length];
        sort(a, 0, a.length - 1);
    }

    public static void sort(int[] a, int low, int high) {
        if (low >= high) {
            return;
        }
        int mid = (low + high) / 2;
        //將左半邊排序
        sort(a, low, mid);
        //將右半邊排序
        sort(a, mid + 1, high);
        merge(a, low, mid, high);
    }

    /**
     * 該方法先將所有元素複製到aux[]中,然後在歸併會a[]中。方法咋歸併時(第二個for循環)
     * 進行了4個條件判斷:
     * - 左半邊用盡(取右半邊的元素)
     * - 右半邊用盡(取左半邊的元素)
     * - 右半邊的當前元素小於左半邊的當前元素(取右半邊的元素)
     * - 右半邊的當前元素大於等於左半邊的當前元素(取左半邊的元素)
     */
    public static void merge(int[] a, int low, int mid, int high) {
        //將a[low..mid]和a[mid+1..high]歸併
        int i = low, j = mid + 1;
        for (int k = low; k <= high; k++) {
            aux[k] = a[k];
        }

        for (int k = low; k <= high; k++) {
            if (i > mid) {
                a[k] = aux[j++];
            } else if (j > high) {
                a[k] = aux[i++];
            } else if (aux[j] < aux[i]) {
                a[k] = aux[j++];
            } else {
                a[k] = aux[i++];
            }
        }
    }

}

基數排序

代碼實現:
public static void sort(int[] arr) {
    if (arr.length <= 1) return;

    //取得數組中的最大數,並取得位數
    int max = 0;
    for (int i = 0; i < arr.length; i++) {
        if (max < arr[i]) {
            max = arr[i];
        }
    }
    int maxDigit = 1;
    while (max / 10 > 0) {
        maxDigit++;
        max = max / 10;
    }
    //申請一個桶空間
    int[][] buckets = new int[10][arr.length];
    int base = 10;

    //從低位到高位,對每一位遍歷,將所有元素分配到桶中
    for (int i = 0; i < maxDigit; i++) {
        int[] bktLen = new int[10];        //存儲各個桶中存儲元素的數量

        //分配:將所有元素分配到桶中
        for (int j = 0; j < arr.length; j++) {
            int whichBucket = (arr[j] % base) / (base / 10);
            buckets[whichBucket][bktLen[whichBucket]] = arr[j];
            bktLen[whichBucket]++;
        }

        //收集:將不同桶裏數據挨個撈出來,爲下一輪高位排序做準備,由於靠近桶底的元素排名靠前,因此從桶底先撈
        int k = 0;
        for (int b = 0; b < buckets.length; b++) {
            for (int p = 0; p < bktLen[b]; p++) {
                arr[k++] = buckets[b][p];
            }
        }
        base *= 10;
    }
}
發佈了21 篇原創文章 · 獲贊 55 · 訪問量 2590
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章