排序與搜尋

合併排序法與快速排序法

本投影片含有強烈不專業成份
如服用時有過敏不適等症狀
請立即停用並找專業教師治療矯正

回顧一下手上有的牌

  • 可以藉由循序抓對,把最大/小的值推到後面 (泡泡)

  • 可以掃出最大值,跟最後面換位置 (選擇)

  • 可以用凡走過必留下痕跡的概念,將循序到的新值放到合適的位置,走完後就是整理好的結果 (插入)

夠了吧?

  • 雖然可以在遍歷時檢查是否提前完成

  • 可是最糟的情形下這些算法都是 

  • 正常情形上也是

O(n^2)
O(n2)

不要急,但要快

  • 噗嗤

  • 可是我是認真的

改善的空間

  • 雖然原本的時間是

  • 就算我們照原本的算法,當我們只要排一半

  • 排四分之一

  • 排八分之一

  • 排n分之一 

O((\frac{n}{2})^2)
O((2n)2)
O((\frac{n}{4})^2)
O((4n)2)
O((\frac{n}{8})^2)
O((8n)2)
O(1)
O(1)
O(n^2)
O(n2)

這只是理想吧

  • 人若沒有理想,那跟鹹魚有什麼分別?

  • 但沒錯我們不能只談理想

分而治之

  • 我們需要一個合理把原序列切分的方法

  • 也需要一個合理的合併方法

  • 是的,要快,但不要急

合併排序法

  • 天下大勢,分久必合,合久必分......

  • 專業人士好像會說歸併排序法?

  • 將原序列切成左半跟右半

  • 左半跟右半分別再進行排序

  • 排序完的左半跟右半進行合併

分別再進行排序

  • 這是要呼叫自己的意思嘛?

  • 很有那個感覺

愉快的教材時間

請看教材Active Code: Merge Sort (lst_merge)

目標達成

  • 一般來說實作的好的話可以達到最差狀況也能
  • 可是過程會耗掉大量空間
  • 如果空間是優先考量怎麼辦?
O(n \log{n})
O(nlogn)

快速排序法

  • 名字非常的威

  • 相對於切固定的子序列,讓序列自己找出子序列

  • 概念也很威

  • 找出子序列放下去排,子序列排完原序列也排完了

  • 行為上也很威

找出子序列

  • 首先先拿一個值為比較標的,稱為pivot

  • 使用兩個指標

  • 一個從前往後走,目的是要找出比pivot大的值

  • 一個從後往前走,目的是要找出比pivot小的值

  • 行動的指標找到目的後停止,與另一個指標互換值後,換另一個指標行動

  • 當指標產生黃金交差,就表示找到甜蜜點了

  • pivot與往後走的指標互換值

  • 這時pivot之前都是比較小的值,之後都是比較大的值

找出子序列

  • 這時子序列其實還沒排序

  • 所以把子序列繼續排序直到沒有子序列

  • 注意子序列有左右兩邊

  • 只是不一定兩邊都有

  • 如何判斷呢?

來看教材吧

請看教材Active Code: Quick Sort (lst_quick)

是不是真有那麼威啊

  • 如果每次取pivot都很剛好的可以拿到中位數
  • 可以完美分割排序達到
  • 而且自己內部完成只要一個互換用的暫存空間
  • 很快
O(n\log{n})
O(nlogn)

那不是拿到中位數呢

  • 一般狀況時大概就是上揚一點
  • 可是如果很衰的每次取pivot都拿到極值
  • 那子序列都是n-1
  • 這時要花到
  • 這是一個要快,很急造成的後果的例子
O(n^2)
O(n2)

結論

  • 可以看到不要急要快是有那樣的環境與資源的,所以要跟老闆說......
  • 演算法的使用可以有很多種考量,所以沒事多想想,多想想沒事。
  • 多看看各種實作有益身心健康。

SortingMergeQuick

By Ted Wu

SortingMergeQuick

  • 1,315