排序演算法
不正經的排序演算法
講師介紹
Boron
C++ 小社課講師
vibe coding 出了一個低配版 arrayV 所以今天來講排序演算法
今天會講的其中一個排序演算法->

排序
排序甚麼
今天講的排序都是數字的排序(從小到大)

今天也會講的其中一個排序演算法->
不會有太難的演算法
會有很白癡的演算法
講完概念之後會大概講程式怎麼實作
插入排序法
Insertion sort
| 5 | 7 | 1 | 3 | 2 | 13 |
|---|
現在有這樣一串沒有排序好的數字
怎麼排好?
插入
| 5 | 7 | 1 | 3 | 2 | 13 |
|---|
這個數字沒有排好(左邊的數字比這個數字大)
所以,我把它往前插入到正確的位置
我從左到右依序檢查,並將排序錯誤的值插回正確的位置
排好
| 1 | 5 | 7 | 3 | 2 | 13 |
|---|
| 1 | 3 | 5 | 7 | 2 | 13 |
|---|
| 1 | 2 | 3 | 5 | 7 | 13 |
|---|
這個就是插入排序法
那麼要怎麼知道該插入到哪個位置呢?
程式跑插入排序法的流程
| 1 | 5 | 7 | 3 | 2 | 13 |
|---|
| 1 | 5 | 7 | 7 | 2 | 13 |
|---|
把左邊的數字複製過來,並比較 3 與 5。5 比較大
| 1 | 5 | 5 | 7 | 2 | 13 |
|---|
| 1 | 3 | 5 | 7 | 2 | 13 |
|---|
把左邊的數字複製過來,並比較 3 與 1。1 比較小
把剛剛抽出來的 3 放到正確位置,結束排序
先把 3 抽出來
視覺化

選擇排序法
Selection sort
抽出最小的
| 5 | 7 | 1 | 3 | 2 | 13 |
|---|
同樣的一串數字,怎麼排?
我可以每次都抽出所有數字裡最小的,依抽出來的先後順序排好
抽出最小的
| 5 | 7 | 1 | 3 | 2 | 13 |
|---|
1 是裡面最小的數字,抽出來
依次進行
2
3
5
7
13
排序完成
1
| 5 | 7 | 3 | 2 | 13 |
|---|
| 5 | 7 | 3 | 13 |
|---|
| 5 | 7 | 13 |
|---|
| 7 | 13 |
|---|
| 13 |
|---|
那要怎麼找最小
把所有數字掃過一遍
👍
對沒錯就是這麼暴力
視覺化

雙選擇排序法
我可以一次找出最大值與最小值,並把它放到頭跟尾
速度變兩倍
| 5 | 7 | 1 | 3 | 2 | 13 |
|---|
2
3
5
7
13
1
氣泡排序法
bubble sort
氣泡大的浮起來
| 5 | 7 | 1 | 3 | 2 | 13 |
|---|
比較這兩格,這兩個是不是排序好的:是
不用動,到下一格
比較這兩格,這兩個是不是排序好的:否
把這兩格的數值交換
| 5 | 1 | 7 | 3 | 2 | 13 |
|---|
| 5 | 1 | 3 | 7 | 2 | 13 |
|---|
| 5 | 1 | 3 | 2 | 7 | 13 |
|---|
比較這兩格,這兩個是不是排序好的:否
把這兩格的數值交換
比較這兩格,這兩個是不是排序好的:否
把這兩格的數值交換
比較這兩格,這兩個是不是排序好的:是
不用動,結束一輪的氣泡排序
| 5 | 7 | 1 | 3 | 2 | 13 |
|---|
一直重複
你會發現,第一輪的氣泡排序法排完之後,最大值會跑到最右邊
| 5 | 7 | 1 | 3 | 2 | 13 |
|---|
而第二輪則是次大值跑到最右邊的左邊一格
以此類推
所以第一輪排好後,下一輪就可以不用檢查最後一格,因為最後一格會是好的
以此類推,每一輪排好之後,下一輪就可以少檢查一個數字
像這個陣列,只要排 5 次就一定可以排好
視覺化

雞尾酒排序法
用氣泡排序法從左掃到右邊,再從右邊掃到左邊
當作一輪的雞尾酒排序
因為一直左右搖晃,所以稱為 cock tail shake sort

速度
猜猜前面三個誰最快
比個速度
當數字有 25000 個時,三個演算法在排序一個隨機的陣列所需的時間:
| bubble sort | insertion sort | selection sort |
|---|---|---|
| 7794.5ms | 1889.1ms | 1373.5ms |
爛死了
最快
補充
| cocktail sort(optimized) | 二分搜+insertion sort | double selection sort |
|---|---|---|
| 5414.1ms | 24.78ms | 1153.5ms |
| bubble sort | insertion sort | selection sort |
|---|---|---|
| 7794.5ms | 1889.1ms | 1373.5ms |
| comb sort | shell sort(original) | heap sort |
|---|---|---|
| 2.34ms | 2.49ms | 2.92ms |
這三種演算法的各種優化版本
bogo sort
事情開始奇怪起來了
撲克牌
現在想像一下你有一疊撲克牌(A~K 各一張)
要怎麼把他從下到上,從小到大的排序好呢?
對沒錯你可以一直洗牌,洗到他是對的為止
????????
SHUFFLE
我就把這疊牌洗牌,一直洗牌、一直洗牌、一直洗牌、一直洗牌、一直洗牌、一直洗牌、一直洗牌、一直洗牌、一直洗牌、一直洗牌、一直洗牌、一直洗牌、一直洗牌、一直洗牌、一直洗牌、一直洗牌、一直洗牌、一直洗牌、一直洗牌、一直洗牌、一直洗牌、一直洗牌、一直洗牌、一直洗牌、一直洗牌、一直洗牌、一直洗牌、一直洗牌、一直洗牌、一直洗牌、一直洗牌、一直洗牌、一直洗牌、一直洗牌、一直洗牌...............................
就平均來說 13 張牌要洗成正確排序的順序,要 13! 次,也就是約 \(6.2 \times10^9\)次
????????
bogo BOGO sort
事情繼續奇怪起來了
更浪費時間的洗牌
| 5 | 7 | 1 | 3 | 2 | 13 |
|---|
檢查前一個數字是不是排好的:是
檢查前兩個數字是不是排好的:是
檢查前三個數字是不是排好的:不是
把前三個數字洗一次牌,並重新檢查
每次檢查時,如果沒有排序好,就把前面所有數字洗牌,再重頭開始檢查
要幾次
如果有 13 張牌要排序的話平均大約要......
\(1! \times 2! \times 3! \times 4! \times 5! \times ...... \times 13! = 8 \times 10^{53}\) 次
以電腦一秒進行 \(10^9\) 次運算來計算
大約需要 \(2.53 \times 10^{37}\) 年
💀💀💀
stalin sort
目前最快的排序演算法(?
拖出去
| 5 | 7 | 1 | 3 | 2 | 13 |
|---|
檢查這個值是否大於前面一格的值:是
不用動
檢查這個值是否大於前面一格的值:否
拖出去斬了
檢查這個值是否大於前面一格的值:否
拖出去斬了
檢查這個值是否大於前面一格的值:否
拖出去斬了
檢查這個值是否大於前面一格的值:是
不用動,排序完成
| 5 | 7 | 3 | 2 | 13 |
|---|
| 5 | 7 | 2 | 13 |
|---|
| 5 | 7 | 13 |
|---|
| 5 | 7 | 13 |
|---|
| 5 | 7 | 1 | 3 | 2 | 13 |
|---|
:可是陣列在排序的過程中被破壞了欸
你就說是不是排序好了
😡
所以才叫做「史達林排序法」
sleep sort
zzzzzzzzzzzzz
訂個鬧鐘
我現在給每個數字訂個倒數計時,數字越大給的時間越長
時間一到,就把數字丟出來
因為剛剛是照著數字大小定鬧鐘,所以丟出來的順序就是排好的順序
原版似乎是一秒丟出一個數字
solar bit flip sort
怪
solar bit flip
我覺得我的記憶體暴露在太陽輻射下時,會有一些儲存單元的狀態從 0 變成 1,或從 1 變成 0(bit flip)
因此我希望這樣有朝一日能夠使記憶體裡儲存的一串數字變成排列好的樣子
打個比方
這就像是你把一疊撲克牌打開攤放在桌上,覺得地震會使他們的位置移動。
所以希望有朝一日撲克牌的順序會被震成正確的樣子
程式怎麼寫
每十秒檢查一次陣列是不是排序好的
💀
random sort
找人幫忙
???
我在得到一串數字後,我不對他做處理
我把這串程式丟到其他隨機一個程式裡做運算
然後獲取該程式的輸出,確認他的輸出是不是排序好的
打個比方
我拿到一疊撲克牌,然後去找其他生物幫我排好
你可能找到的是猴子、烏龜、貓之類的
然後最後看看這個生物有沒有把他排好,沒排好就再去找下一個生物
阿不是啊這幾個「演算法」是幹嘛用的
emmm
我也不知道
🙃
補充
有三十種排序演算法的視覺化
如果你對排序有興趣的話可以看看
看不懂的話可以問我
內容應該大致都是對的
結束啦
好欸
sorting algorithm
By 硼/Boron
sorting algorithm
- 76