1. 程式人生 > >11-排序(上) : 為什麼插入排序比氣泡排序更受歡迎?

11-排序(上) : 為什麼插入排序比氣泡排序更受歡迎?

如何分析一個"排序演算法"?

  • 排序演算法的執行效率 1.最好情況,最壞情況,平均情況 排序演算法中,不同的排序演算法在不同的資料下效能表現也是不一樣的 2.時間複雜度的係數,常數,低階 由於我們的排序可能是很小規模的資料,所以,我們要把係數,常數,低階也新增過來 3.比較次數和交換(或移動)次數 比較演算法,涉及到兩個操作,比較和交換(移動)
  • 排序演算法的記憶體消耗 我們知道,演算法的記憶體消耗可以通過空間複雜度來衡量,針對排序演算法的空間複雜度,我們引入一個新的概念,原地排序:特指空間複雜度為O(1)的排序演算法.
  • 排序演算法的穩定性 穩定性:如果待排序的序列中存在值相等的元素,經過排序之後,相等元素之間原有的先後順序不變. 穩定排序演算法:我們先按照下單時間給訂單排序,注意是按照下單時間,不是金額。排序完成之後,我們用穩定排序演算法,按照訂單金額重新排序。兩遍排序之後,我們得到的訂單資料就是按照金額從小到大排序,金額相同的訂單按照下單時間從早到晚排序的。 在這裡插入圖片描述

氣泡排序

氣泡排序只會操作相鄰的兩個資料。每次冒泡操作都會對相鄰的兩個元素進行比較,看是否滿足大小關係要求。如果不滿足就讓它倆互換。一次冒泡會讓至少一個元素移動到它應該在的位置,重複 n 次,就完成了 n 個數據的排序工作。

  • 當某次氣泡排序已經沒有資料交換時,說明已經達到完全有序,不需要繼續執行後續的冒泡操作.
// 氣泡排序,a 表示陣列,n 表示陣列大小
public void bubbleSort(int[] a, int n) {
  if (n <= 1) return;
 
 for (int i = 0; i < n; ++i) {
    // 提前退出冒泡迴圈的標誌位
boolean flag = false; for (int j = 0; j < n - i - 1; ++j) { if (a[j] > a[j+1]) { // 交換 int tmp = a[j]; a[j] = a[j+1]; a[j+1] = tmp; flag = true; // 表示有資料交換 } } if (!flag) break; // 沒有資料交換,提前退出 } }
  • 氣泡排序由於只需要常量級的臨時空間,所以它的複雜度為O(1),是一個原地排序演算法
  • 氣泡排序是一個穩定的排序演算法
  • 時間複雜度 在這裡插入圖片描述 推算平均情況下的時間複雜度
  • 有序度:陣列中具有有序關係元素對的個數
有序元素對:a[i] <= a[j], 如果 i < j。
  • 逆序度:恰好跟有序度相反
逆序元素對:a[i] > a[j], 如果 i < j。
  • 逆序度 = 滿有序度 - 有序度 從而推出平均有序度為O(n²)

插入排序

一個有序陣列,我們往裡面新增一個新的資料後,如何繼續保持資料的有序性 在這裡插入圖片描述

  • 這是一個動態排序的過程,即動態地往有序集合中新增資料,我們可以通過這種方法保持集合中的資料一直有序。而對於一組靜態資料,我們也可以借鑑上面講的插入方法,來進行排序,於是就有了插入排序演算法。
  • 首先,我們將陣列中的資料分為兩個區間,已排序區間和未排序區間。初始已排序區間只有一個元素,就是陣列的第一個元素。插入演算法的核心思想是取未排序區間中的元素,在已排序區間中找到合適的插入位置將其插入,並保證已排序區間資料一直有序。重複這個過程,直到未排序區間中元素為空,演算法結束。
  • 插入排序包含兩種操作,一種是元素的比較,一種是元素的移動.
  • 移動操作的次數總是固定的,就等於逆序度. 在這裡插入圖片描述
// 插入排序,a 表示陣列,n 表示陣列大小
public void insertionSort(int[] a, int n) {
  if (n <= 1) return;

  for (int i = 1; i < n; ++i) {
    int value = a[i];
    int j = i - 1;
    // 查詢插入的位置
    for (; j >= 0; --j) {
      if (a[j] > value) {
        a[j+1] = a[j];  // 資料移動
      } else {
        break;
      }
    }
    a[j+1] = value; // 插入資料
  }
}
  • 插入排序是不需要額外的儲存空間的,所以空間複雜度是O(1),因此是一個原地排序演算法
  • 在插入排序中,對於值相同的元素,我們可以將後面出現的元素,插入到前面出現元素的後面,保持原有的前後順序不變,所以插入排序是穩定的排序演算法
  • 插入排序的時間複雜度,最好的是O(n),最壞情況時間複雜度位O(n²),平均時間複雜度為O(n²)

選擇排序

在這裡插入圖片描述

  • 選擇排序空間複雜度為O(1),是一種原地排序演算法
  • 選擇排序最好情況時間複雜度,最壞情況時間複雜度都為O(n²),平均時間複雜度為O(n²)
  • 選擇排序不是一個穩定的排序演算法

解答開篇

  • 我們前面分析氣泡排序和插入排序的時候講到,氣泡排序不管怎麼優化,元素交換的次數是一個固定值,是原始資料的逆序度。插入排序是同樣的,不管怎麼優化,元素移動的次數也等於原始資料的逆序度。但是交換時遠比移動要複雜,所以優選插入排序

內容小結

在這裡插入圖片描述