八大排序演算法

來源:互聯網
上載者:User

標籤:選擇   堆排   import   分析   需要   特殊   ref   public   href   

目錄

  • 排序演算法
    • 一、時間複雜度為O(n^2)的排序演算法
      • 1.1 冒泡排序(bubbleSort)
      • 1.2 選擇排序(selectionSort)
      • 1.3 插入排序(insertionSort)
    • 二、時間複雜度為O(log(n))的排序演算法
      • 2.1 歸併排序(mergeSort)
      • 2.2 快速排序(quickSort)
      • 2.3 堆排序
      • 2.4 希爾排序(shellSort)
    • 三、 桶排序(時間複雜度O(n))
      • 3.1 計數排序
      • 3.2 基數排序
排序演算法

排序演算法之間的比較:

排序演算法 最差時間分析 平均時間複雜度 穩定度 空間複雜度
冒泡排序 O(n^2) O(n^2) 穩定 O(1)
選擇排序 O(n^2) O(n^2) 不穩定 O(1)
插入排序 O(n^2) O(n^2) 穩定 O(1)
歸併排序 O(nlogn) O(nlogn) 穩定 O(n)
快速排序 O(n^2) O(nlogn) 不穩定 O(1)
堆排序 O(n^2) O(n*logn) 不穩定 O(1)
希爾排序 O(n^2) O(n^1.3) 不穩定 O(1)
桶排序 O(n) O(n) 穩定 O(n)
一、時間複雜度為O(n^2)的排序演算法1.1 冒泡排序(bubbleSort)
  • 進行n-1輪排序,每輪排序數組中元素依次兩兩交換, 擷取最大的元素;
  • 時間複雜度 O(n^2), 空間複雜度O(1);
public class BubbleSort {    public int[] bubbleSort(int[] A) {        // write code here        if(A == null || A.length < 2) return 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]){                    swap(A, j, j+1);                }            }        }        return A;    }        public void swap(int[] A, int i1, int i2){        int tmp = A[i1];        A[i1] = A[i2];        A[i2] = tmp;    }}
1.2 選擇排序(selectionSort)
  • 進行n-1輪交換, 每輪交換擷取最小的元素
  • 時間複雜度 O(n^2), 空間複雜度O(1);
public class SelectionSort {    public int[] selectionSort(int[] A) {        // write code here        if(A == null || A.length < 2) return A;        for(int i = 0; i < A.length - 1; i++){            for(int j = i + 1; j < A.length; j ++){                if(A[i] > A[j]){                    swap(A, i, j);                }            }        }        return A;    }     public void swap(int[] A, int i1, int i2){        int tmp = A[i1];        A[i1] = A[i2];        A[i2] = tmp;    }}
1.3 插入排序(insertionSort)
  • 時間複雜度 O(n^2), 空間複雜度O(1);
  • 當數組元素有序, 時間複雜度O(n)
public class InsertionSort {    public int[] insertionSort(int[] A, int n) {        // write code here        for(int i = 1; i < A.length; i++){            int key = A[i];            int pre = i - 1;            while(pre >= 0 && A[pre] > key){                A[pre+1] = A[pre--];            }            A[pre + 1] = key;        }        return A;    }}
二、時間複雜度為O(log(n))的排序演算法2.1 歸併排序(mergeSort)
  • 時間複雜度O(log(n)), 空間複雜度O(n)
  • 歸併排序的時間複雜度與排序數組元素順序無關;
public class MergeSort {    public int[] mergeSort(int[] A, int n) {        // write code here        if(A == null || A.length < 2) return A;        int[] tmp = new int[A.length];        divide(A, 0, A.length - 1, tmp);        return A;    }    // 數組合并    public void merge(int[] A, int left, int right, int mid, int[] tmp){        for(int i = left; i <= right; i++){            tmp[i] = A[i];        }        int l1 = left, l2 = mid+1, index = left;        for(int i = left; i <= right; i++){            if(l1 > mid){                A[index++] = tmp[l2++];            }else if(l2 > right){                A[index++] = tmp[l1++];            }else if(tmp[l1] < tmp[l2]){                A[index++] = tmp[l1++];            }else{                A[index++] = tmp[l2++];            }        }    }        public void divide(int[] A, int left, int right, int[] tmp){        if(left < right){            // 與 mid = (left + right)/2 相比, 可以防止left+right超出int範圍            int mid = left + (right-left)/2;            divide(A, left, mid, tmp);            divide(A, mid+1, right, tmp);            merge(A, left, right, mid, tmp);        }    }}
2.2 快速排序(quickSort)

最優情況: 元素分布均勻, 每次都能取到中間位置

  • 時間複雜度O(log(n)), 空間複雜度O(logn);

最壞情況: 時間複雜度O(n^2), 空間複雜度O(n), 以下三種最壞情況

  • 數組已經是正序(same order)排過序的。
  • 數組已經是倒序排過序的。
  • 所有的元素都相同(1、2的特殊情況)
public class QuickSort {    public int[] quickSort(int[] A, int n) {        // write code here        quick(A, 0, A.length - 1);        return A;    }        public void quick(int[] A, int left, int right){        if(left >= right) return ;        int key = A[left];        int head = left, tail = right+1;        while(true){            while(A[++head] <= key) if(head == right) break;            while(A[--tail] > key) if(tail == left) break;            if(head >= tail) break;            int tmp = A[head];            A[head] = A[tail];            A[tail] = tmp;        }        A[left] = A[tail];        A[tail] = key;        quick(A, left, tail-1);        quick(A, tail + 1,right);    }}
2.3 堆排序
  • 時間複雜度O(nlog(n)), 空間複雜度O(1)

  • 最差情況, 數組元素已經是從小到大有序的, 時間複雜度O(n^2)

public class HeapSort {    public int[] heapSort(int[] A, int n) {        // 建堆        for(int i = A.length/2; i >= 0; i--){            heapAdjust(A, i, A.length);        }        for(int i = A.length - 1; i >= 0; i--){            int head = A[0];            A[0] = A[i];            A[i] = head;            heapAdjust(A, 0, i);        }        return A;    }    // 堆調整 O(log(n))    public void heapAdjust(int[] A, int parent, int len){        int head = A[parent];        while(parent*2+1 < len){            int childLeft = parent*2 + 1;            if(childLeft + 1 < len && A[childLeft + 1] > A[childLeft]){                childLeft++;            }            if(A[childLeft] < head) break;            A[parent] = A[childLeft];            parent = childLeft;        }        A[parent] = head;    }}
2.4 希爾排序(shellSort)
  • Shell排序比起QuickSort,MergeSort,HeapSort慢很多。適合於資料量在5000以下並且速度並不是特別重要的場合。它對於資料量較小的數列重複排序是非常好的。

  • 時間複雜度O(nlog(n)),空間複雜度O(1)
public class ShellSort {    public int[] shellSort(int[] A, int n) {        for(int i = n; i >= 1; i /= 2){            for(int j = i; j < n; j++){                int key = A[j];                int pre = j - i;                while(pre >= 0 && A[pre] > key){                    A[pre + i] = A[pre];                    pre -= i;                }                A[pre + i] = key;            }        }        return A;    }}
三、 桶排序(時間複雜度O(n))3.1 計數排序
  • 計數排序適用於元素在一定有限範圍內的數組;
  • 時間複雜度O(n), 空間複雜度 O(m)
import java.util.*;public class CountingSort {    public int[] countingSort(int[] A, int n) {        if(A == null || A.length < 2) return A;        int min = A[0], max = A[0];        for(int i = 0; i < A.length; i++){            min = Math.min(min, A[i]);            max = Math.max(max, A[i]);        }        int[] bucket = new int[max - min + 1];        // 入桶        for(int i = 0; i < A.length; i++){            bucket[A[i] - min]++;        }        // 出桶        int index = 0;        for(int i = 0; i < bucket.length; i++){            while(bucket[i]-- > 0){                A[index++] = i + min;            }        }        return A;    }}
3.2 基數排序
  • 時間複雜度O(n), 空間複雜度O(n)
// 保證元素均小於等於2000的基數排序public class RadixSort {    public int[] radixSort(int[] A, int n) {        if(A == null || n < 2) return A;        int[][] bucket = new int[10][n]; // 建立10個桶,每個桶需要的長度都有可能為n        int[] count = new int[10];  // 記錄每個對應桶中裝入的元素個數                for(int i = 1; i <= 1000; i *= 10) {            for(int k = 0; k < n; k++) {                int num = A[k] / i % 10; // 擷取位元上對應數字                bucket[num][count[num]++] = A[k];            }            // 從bucket中將資料倒回A中            int index = 0;            for(int k = 0; k < 10; k++) {                for(int j = 0; j < count[k]; j++) {                    A[index++] = bucket[k][j];                }                count[k] = 0; // 重設為0            }        }        return A;    }}

八大排序演算法

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.