排序

分析排序算法

執行效率

1. 最好、最壞、平均時間復雜度

數據的有序程度不一樣,對排序算法時間復雜度的影響很大,所以需要對最好、最壞情況復雜度有了解

2. 時間復雜度的系數、常數

當兩個算法的時間復雜度是一個階層的,這時就需要考慮它們的系數或者常數項,以此來判斷快慢

3. 比較次數和交換次數

基于比較的排序算法基本都有比較和交換的操作,計算時間復雜度的時候,需要把這兩種操作計算進去

內存消耗

內存消耗可以用空間復雜度來表示,對于空間復雜度為 O(1) 排序算法,稱其為 原地排序

穩定性

針對排序算法,還有另外一個指標,即算法的穩定性。
算法的穩定性指的是,排序關鍵字相同的兩個項,在排序之前和之后的相對位置是否變化,若相對位置沒有變化,則是穩定排序算法,否則是非穩定排序算法

O(n2) 復雜度排序算法

算法 原地排序 穩定排序 最好時間復雜度 最壞時間復雜度 平均時間復雜度
冒泡排序 O(n) - 數組有序 O(n2) - 數組逆序 O(n2)
插入排序 O(n) - 數組有序 O(n2) - 數組逆序 O(n2)
選擇排序 O(n2) O(n2) O(n2)

1. 冒泡排序

思想:每次比較相鄰的兩個數,滿足交換條件則交換兩個數,所以每次都能將未排序的最大(小)的數冒泡到末尾,循環 n 次后,數組已經有序

可優化點:當某次冒泡中沒有發生數據交換時,此時數組已經有序,不需要再進行后續的冒泡比較了

function quickSort(arr) {
  if(!arr || arr.length < 2) {
    return arr;
  }

  for (let i = 0; i < arr.length; i++) {

    // j 和 j + 1 比較,最后一個元素就是 j + 1,所以 - 1
    const top = arr.length - i - 1;
    let isSorted = true;
    for(let j = 0; j < top; j++) {
      if (arr[j] > arr[j+1]) {
        const temp = arr[j];
        arr[j] = arr[j+1];
        arr[j+1] = temp;
        isSorted = false;
      }
    }
    if (isSorted) {
      break;
    }
  }
  return arr;
}

2. 插入排序

思想: 將數組分為 已排序區間和未排序區間,每次從將未排序區間第一個元素插入到已排序區間的正確位置上

// 使用 js 數組方法
function insertSort(arr) {
  for (let i = 1; i < arr.length; i++) {
    const ordered = arr.slice(0, i);
    const value = arr[i];
    const index = ordered.findIndex(val => val > value);
    if (index !== -1) {
      arr.splice(i, 1);
      arr.splice(index, 0, value);
    }
  }
  return arr;
}

// 不使用 js 數組方法
function insertSort(arr) {
  if (arr.length < 2) {
    return arr;
  }

  for (let i = 1; i < arr.length; i++) {
    const value = arr[i];
    let j = i;
    while (j--) {
      if (arr[j] > value) {
        arr[j + 1] = arr[j];
      } else {
        break;
      }
    }
    arr[j + 1] = value;
  }
  return arr;
}

3. 選擇排序

思想: 也是將數組分為 已排序區間和未排序區間,每次從未排序區間中找到最小值,和未排序區間第一個值做交換

function selectSort(arr) {
  if (arr.length < 1) {
    return arr;
  }

  let orderedTrail = 0;
  while (orderedTrail < arr.length){
    let j = orderedTrail;
    let min = arr[j];
    let minIndex = j;
    while (j < arr.length) {
      if (arr[j] < min) {
        min = arr[j];
        minIndex = j;
      }
      j += 1;
    }
    arr[minIndex] = arr[orderedTrail];
    arr[orderedTrail++] = min;
  }
  return arr;
}

O(nlogn) 復雜度排序算法

算法 原地排序 穩定排序 最好時間復雜度 最壞時間復雜度 平均時間復雜度
歸并排序 否 - O(n) O(nlogn) O(nlogn) O(nlogn)
快速排序 O(O(nlogn)) - 分區比較均衡 O(n2) - 分區及其不均衡 O(O(nlogn))

1. 歸并排序

思想: 把數組分為前后兩個部分,分別對兩個部分進行排序,然后將排好序的兩部分合并,則數組有序( 分而治之的思想 )

function mergeSort(arr) {
  if (!arr || !Array.isArray(arr) || !arr.length) {
    return [];
  }

  const merge = function(left, middle, right) {
    const tempArr = Array(right - left);
    let index = 0;
    let leftIndex = left;
    let rightIndex = middle;

    while (leftIndex < middle && rightIndex < right) {
      const leftValue = arr[leftIndex];
      const rightValue = arr[rightIndex];
      if (leftValue <= rightValue) {
        tempArr[index++] = leftValue;
        leftIndex += 1;
      } else {
        tempArr[index++] = rightValue;
        rightIndex += 1;
      }
    }

    let start = leftIndex < middle ? leftIndex : rightIndex;
    let end = leftIndex < middle ? middle : right;

    while (start < end) {
      tempArr[index++] = arr[start++];
    }

    end = right - left;
    for (start = 0; start < end; start++) {
      arr[start + left] = tempArr[start];
    }
  }
  const sort = function(left, right) {
    if (left >= right) {
      return;
    }
    const middle = ((right + left) / 2) >> 0;
    sort(left, middle);
    sort(middle + 1, right);
    merge(left, middle, right);
  }
  sort(0, arr.length)
  return arr;
}

時間復雜度分析: T(n) = T(n/2)(左伴部分的時間復雜度) + T(n/2)(右半部分的時間復雜度) + K(合并時的時間復雜度),可以以此推出 T(n) = 2^k*T(n/2^k) + k*n,當 2^k == 1時,k = logn,帶入即可得 T(n) = nlogn + Cn

2. 快速排序

思想: 取區間任意位置為標準值,遍歷區間,比標準值小的都放在左邊,比標準值大的都放在右邊,以此類推,直到只有一個元素,此時數組有序( 分而治之的思想 )

function quickSort(arr) {
  if (!arr || !Array.isArray(arr) || !arr.length) {
    return [];
  }

  const swap = function(i ,j) {
    const temp = arr[j];
    arr[j] = arr[i];
    arr[i] = temp;
  }

  const partial = function(left, right) {
    const reference = arr[right];
    let i = left;
    for (let j = left; j < right; j++) {
      if (arr[j] < reference) {
        swap(i, j)
        i += 1;
      }
    }
    swap(i, right);
    return i;
  }

  const sort = function(left, right) {
    if (left >= right) {
      return;
    }
    
    border = partial(left, right);
    sort(left, border - 1);
    sort(border + 1, right);
  }

  sort(0, arr.length - 1);
  return arr;
}

注意: 由于在交換元素的過程中可能會破壞數組項的原本的先后順序,所以快速排序是非穩定排序

O(n) 復雜度排序算法

1. 桶排序

思想: 根據數據范圍,分幾個桶,將對應區間的數據放到對應的桶中進行排序,然后根據桶的順序合并每個桶中的數據

桶排序

復雜度分析: 當劃分為 m個桶時,如果劃分均勻,則每個桶有 k = n/m 個項,若對每個桶采用快速排序,則復雜度為 O(k*logk),m 個桶的總復雜度為 O(m*k*logk),又有 k = n/m,則為 O(n*log(n/m)),可見,當桶的個數越接近項的個數,時間復雜度越接近 O(n)

2. 基數排序

思想: 根據數據的每一位分別進行排序,需要使用穩定的排序算法

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,363評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,497評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,305評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,962評論 1 311
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,727評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,193評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,257評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,411評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,945評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,777評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,978評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,519評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,216評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,657評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,960評論 2 373

推薦閱讀更多精彩內容