常見的排序算法(JavaScript實現(xiàn))

摘要:本文簡單介紹幾個常見的排序算法答毫,包括:冒泡排序褥民、選擇排序、插入排序洗搂、快速排序消返、歸并排序、希爾排序耘拇。列出的代碼為 JavaScript 實現(xiàn)撵颊,標(biāo)題后表示的是該排序算法的時間復(fù)雜度。

冒泡排序 —— O(n^2)

function bubbleSort (array) {
  for(let i = 0; i < array.length; i++){
    for(let j = 1; j < array.length; j++){
      if(array[i] > array[j]){
        [array[i], array[j]] = [array[j], array[i]]
      }
    }
  }
  return array
}

選擇排序 —— O(n^2)

function selectionSort (array) {
  let min = null
  for(let i = 0; i < array.length; i++){
    min = i
    for(let j = i + 1; j < array.length; j++){
      if(array[min] > array[j]){
        min = j
      }
    }
    [array[i],array[min]] = [array[min],array[i]]
  }
  return array
}

插入排序 —— O(n^2)

  • 普通版
function insertionSort (array) {
  let temp = null
  for(let i = 1; i < array.length; i++){
    temp = array[i]
    for(var j = i; j >=0 && temp < array[j-1]; j--){
      array[j] = array[j-1]
    }
    array[j] = temp
  }
  return array
}
  • JS版( 使用splice )
function insertionSort (array) {
  for(let i = 1; i < array.length; i++){
    for(var j = 0; j < i; j++){
      if(array[i] < array[j]){
        array.splice(j,0,array[i])
        array.splice(i+1,1)
        break
      }
    }
  }
  return array
}

快速排序 —— O(nlogn)

  • 遞歸版(存在空間浪費)
function quickSort (array) {
  if(array.length <= 1) {
    return array
  }
  let leftArray = [] 
  let rightArray = []
  for(let i = 1; i < array.length; i++){
    if(array[i] >= array[0]) {
      rightArray.push(array[i])
    } else {
      leftArray.push(array[i])
    }
  }
  return quickSort(leftArray).concat(array[0]).concat(quickSort(rightArray))
}
  • 遞歸的進階版(在原數(shù)組上操作惫叛,最典型的快排寫法)
    該方法大致流程如下:
    1. 對于一個數(shù)組倡勇,挑選最后一個值作為參考值(key)
    2. 從數(shù)組的頭部開始掃描,如果值比參考值小挣棕,繼續(xù)往后掃描译隘,直到掃描到的值(左值)比參考值大
    3. 從數(shù)組的尾部(參考值的前一個)開始掃描亲桥,如果值比參考值大,繼續(xù)往前掃描固耘,直到掃描到的值(右值)比參考值小
    4. 此時交換掃描停止時的這兩個值
    5. 繼續(xù)上面的邏輯题篷,直到左值和右值相遇
    6. 如果相遇時的值大于等于參考值,讓參考值和相遇值調(diào)換位置(一般情況)
    7. 如果相遇時的值小于參考值厅目,不調(diào)換番枚,但 left 后移以為 (特殊情況,如 [2, 1, 3, 4, 5])
    8. 經(jīng)過上面的處理后损敷,就會把數(shù)組變成以原數(shù)組末尾數(shù)字為分割(左邊都比它小葫笼,右邊都比它大)的數(shù)組。然后分別對參考值左側(cè)和右側(cè)通過類似的邏輯繼續(xù)處理拗馒。
function quickSort(arr) {
  function _quickSort(arr, start, end) {
    if(start >= end) return
    let key = arr[end]
    let left = start, right = end - 1
    while(left < right) {
      while(arr[left] < key && left < right) left++
      while(arr[right] >= key && left < right) right--
      [arr[left], arr[right]] = [arr[right], arr[left]]
    }
    if(arr[left] >= arr[end]) { 
      [arr[left], arr[end]] = [arr[end], arr[left]]
    } else {  // 如 [2, 1, 3, 4]
      left++
    }
    _quickSort(arr, start, left - 1)
    _quickSort(arr, left + 1, end)
  }
  _quickSort(arr, 0, arr.length - 1)
  return arr
}

歸并排序 —— O(nlogn)

  • 大致流程:
    1. 申請空間路星,使其大小為兩個已經(jīng)排序序列之和,該空間用來存放合并后的序列
    2. 設(shè)定兩個指針诱桂,最初位置分別為兩個已經(jīng)排序序列的起始位置
    3. 比較兩個指針?biāo)赶虻脑匮筘ぃx擇相對小的元素放入到合并空間,并移動指針到下一位置
    4. 重復(fù)步驟3直到某一指針到達序列尾
    5. 將另一序列剩下的所有元素直接復(fù)制到合并序列尾
/*
left : [1, 3, 4, 7]
right: [2, 5, 6, 9]
result: [1, 2, 3, 4, 5, 6, 7, 9]
 */

function mergeSort(arr) {
  var merge = function(left, right) {
    var result = []
    while(left.length && right.length) {
      result.push(left[0] <= right[0] ? left.shift() : right.shift())
    }
    return result.concat(left.concat(right))
  }
  if(arr.length < 2) return arr
  var mid = arr.length >> 1
  return merge(mergeSort(arr.slice(0, mid)), mergeSort(arr.slice(mid)))
}

希爾排序 —— O(nlog2n)

原理:先將整個待排數(shù)組分割成若干個子數(shù)組(由相隔某個“增量”的元素組成的)分別進行直接插入排序挥等,然后依次縮減增量再進行排序友绝,待整個數(shù)組中的元素基本有序(增量足夠小)時肝劲,再對全體元素進行一次直接插入排序迁客。因為直接插入排序在元素基本有序的情況下效率是很高的,因此希爾排序在時間效率上較大提高辞槐。

function shellSort(arr) {
  var temp
  var len = arr.length
  for (var gap = len >> 1; gap > 0; gap = gap >>=1) {
    for (var i = gap; i < len; i++) {
      temp = arr[i]
      for( j = i - gap; j >=0 && arr[j] > temp; j -= gap) {
        arr[j + gap] = arr[j]
      }
      arr[j + gap] = temp
    }
    console.log(arr)
  }
}

var arr = [3, 1, 7, 2, 5, 0, 4, 6]
shellSort(arr)
console.log(arr)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末掷漱,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子催蝗,更是在濱河造成了極大的恐慌切威,老刑警劉巖育特,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件丙号,死亡現(xiàn)場離奇詭異,居然都是意外死亡缰冤,警方通過查閱死者的電腦和手機犬缨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來棉浸,“玉大人怀薛,你說我怎么就攤上這事∶灾#” “怎么了枝恋?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵创倔,是天一觀的道長。 經(jīng)常有香客問我焚碌,道長畦攘,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任十电,我火速辦了婚禮知押,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘鹃骂。我一直安慰自己台盯,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布畏线。 她就那樣靜靜地躺著静盅,像睡著了一般。 火紅的嫁衣襯著肌膚如雪寝殴。 梳的紋絲不亂的頭發(fā)上温亲,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天,我揣著相機與錄音杯矩,去河邊找鬼栈虚。 笑死,一個胖子當(dāng)著我的面吹牛史隆,可吹牛的內(nèi)容都是我干的魂务。 我是一名探鬼主播,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼泌射,長吁一口氣:“原來是場噩夢啊……” “哼粘姜!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起熔酷,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤孤紧,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后拒秘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體号显,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年躺酒,在試婚紗的時候發(fā)現(xiàn)自己被綠了押蚤。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡羹应,死狀恐怖揽碘,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤雳刺,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布劫灶,位于F島的核電站,受9級特大地震影響掖桦,放射性物質(zhì)發(fā)生泄漏浑此。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一滞详、第九天 我趴在偏房一處隱蔽的房頂上張望凛俱。 院中可真熱鬧,春花似錦料饥、人聲如沸蒲犬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽原叮。三九已至,卻和暖如春巡蘸,著一層夾襖步出監(jiān)牢的瞬間奋隶,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工悦荒, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留唯欣,地道東北人。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓搬味,卻偏偏與公主長得像境氢,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子碰纬,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內(nèi)容