排序算法-2(javascript) 快速排序的實現

快速排序

快速排序是冒泡排序的優化,與冒泡排序不同的是,使用了分治法,進行優化。會隨機選取一個值pivot(基準元素),與其它值進行比較,將小于這個值的值全部放到一邊,大于這個值的值放到另一邊。然后再對兩邊的序列區間重復進行此操作,直至成為有序隊列為止。

  • 時間復雜度為:nlogn
  • 空間復雜度為:logn
  • 是不穩定的排序方法

快排的實現

單邊循環法

比如對于初始序列:[8, 9, 6, 3, 2, 7]
實現過程思路:

  1. 使用一個mark指針,用來表示小于基準元素的區域邊界,初始時,指向pivot(基準元素,一般我們可以取第1位),也就是mark指向8,[8(mark), 9, 6, 3, 2, 7]
  2. 從基準元素下一位x開始遍歷,如果x > pivot,也就是9 > 8,不做任何操作,,[8(mark), 9(x), 6, 3, 2, 7],繼續遍歷
  3. 遍歷的下一位, [8(mark), 9, 6(x), 3, 2, 7],此時6 < 8,代表著這個數要移動到pivot的左側,所以此時mark往右移一位,用來放置這個數,然后x和mark指向的數進行位置交換,也就是6和9交換,得到[8, 6(mark), 9(x), 3, 2, 7]
  4. 繼續[8, 6(mark), 9, 3(x), 2, 7],x = 3,x < pivot,mark向右移一位指向9,3和mark指向的數9交換,交換后得到 [8, 6, 3(mark), 9(x), 2, 7]
  5. 繼續,[8, 6, 3(mark), 9, 2(x), 7], x = 2, 2 < 8,mark+1指向9,9與2交換,得到[8, 6, 3, 2(mark), 9(x), 7]
  6. 繼續[8, 6, 3, 2(mark), 9, 7(x)],7 < 8,mark+1指向9,9與7交換,得到[8(pivot), 6, 3, 2, 7(mark), 9(x)],此時x已是遍歷的最后一位,所以這時將pivot與mark位置進行交換, [7, 6, 3, 2, 8, 9],這樣就完成了第一輪的快排,此時8左邊的數都是小于8的,右邊的數都是大于8的
  7. 再遞歸對8左右兩邊序列[7,6,3,2]、[9]進行1-6步驟進行快速,直至成為整個數組變成有序隊列
/*
* 快速排序
* 單邊循環法的遞歸實現
*/
function singleQuickSort(arr, startIndex, endIndex) {
  // 健壯性判斷
  if(!Array.isArray(arr)) throw new Error("請輸入一個數組")
  if(!arr.length) return []
  if(startIndex >= endIndex) return;
  // 基準元素
  let pivot = arr[startIndex];
  // 標記指針,用于表示小于基準元素的區域邊界
  let mark = startIndex;
  for(let i = startIndex + 1; i <= endIndex; i++) {
    if(arr[i] < pivot) {
      mark++;
      [ arr[mark], arr[i] ] = [ arr[i], arr[mark] ]
    }
  }
  [ arr[startIndex], arr[mark] ] = [ arr[mark], arr[startIndex] ]
  
  singleQuickSort(arr, startIndex, mark - 1)
  singleQuickSort(arr, mark + 1, endIndex)
  return arr
}

const arr = singleQuickSort([8, 9, 6, 3, 2, 7], 0, 5)
console.log(arr) // [ 2, 3, 6, 7, 8, 9 ]

雙邊循環法

雙邊循環法,顧名思義,就是用雙指針的方法來遍歷元素
實現過程:
如:[8, 2, 6, 3, 9, 7]

  1. 假如隨機值定基準元素pivot為第一個數8,定義一個左指針(指向第一個數),和一個右指針(指向最后一個),則8先與最后一個值進行比較,8比7大,所以兩值交換位置[7, 2, 6, 3, 9, 8]
  2. 此時左指針往右移一位,2與8比,2比8小,位置不變,左指針繼續往右移動一位
  3. 此時左指針往右移一位,6與8比,6比8小,位置不變,左指針繼續往右移動一位
  4. 3和8比,左指針繼續往右移動一位
  5. 9和8比,交換位置[7, 2, 6, 3, 8, 9],此時左指針不變,右指針向左移一位,至此左右指針相同,第一輪比較結束,注意,結束的條件是左指針位置大于等于右指針;比8小的數都在8的左邊,比8大的數都在8的右邊
  6. 對左邊[7, 2, 6, 3]和右邊的序列[9]分別再重復1-4步,直至都成為有序序列
/*
* 快速排序
* 雙邊循環法的遞歸實現
*/
function doubleQuickSort(arr, startIndex, endIndex) {
  // 健壯性判斷
  if(!Array.isArray(arr)) throw new Error("請輸入一個數組")
  if(!arr.length) return []
  if(startIndex >= endIndex) return arr;
  // 基準元素
  const pivot = arr[startIndex]
  // 左指針
  let left = startIndex
  // 右指針
  let right = endIndex
  // 只要左右指針不重合,就會繼續循環
  while(left != right) {
    // 從最右邊開始比較,如果right元素大于基準元素,則右指針向左移一位
    while(left < right && pivot <= arr[right]) {
      right--;
    }
    // 如果右邊元素小于基準元素,則交換位置,然后左指針向右移一位
    if(arr[right] < pivot) {
      [ arr[left], arr[right] ] = [ arr[right], arr[left] ]
      left++;
    }
    // 然后開始比較基準元素和左邊元素,如果左邊元素小于基準元素,左指針向右移一位    
    while(left < right && pivot >= arr[left]) {
      left++;
    }
    // 如果左邊元素大于基準元素,則交換位置,然后右指針向左移一位
    if(arr[left] > pivot) {
      [ arr[left], arr[right] ] = [ arr[right], arr[left] ]
      right--;
    }
  }
  // 當left===right時,就是基準元素所在的最終位置,此時 arr[left] === arr[right] === pivot;
  // 遞歸遍歷左邊和右邊的無序隊列
  doubleQuickSort(arr, startIndex, left-1)
  doubleQuickSort(arr, left + 1, endIndex)
  return arr;
}

const arr2 = doubleQuickSort([8, 9, 6, 3, 2, 7], 0, 5)
console.log(arr2) // [ 2, 3, 6, 7, 8, 9 ]

排序算法系列文章傳送門(未完,持續更新中):
排序算法-1(javascript) 冒泡、選擇、插入、希爾排序的實現
排序算法-2(javascript) 快速排序的實現
排序算法-3(javascript) 堆排序的實現
排序算法-4(javascript) 歸并排序的實現

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

推薦閱讀更多精彩內容