資料結構-搜尋與排序
考研相關文章參考資料為 wjungle 大神提供的筆記
Search
Linear Search
- 又稱為
Sequential Search,從頭到尾一一比較是否符合 - 特性:
- 不必事先進行排序
- 資料可以保存在
Ramdom Access(array) 或Sequentail Access(link list) 結構中
- 時間複雜度:
Binary Search
- 預先準備
- 必須將資料排序 (小 -> 大)
- 資料必須保存在
Ramdom Access(array) 結構
- 可以做成
Iterative / Recursive版本 - 時間複雜度:
- 最多比較次數為
Decision Tree(高度最小化的 BT) 之樹高
- 最多比較次數為
Sort
初等排序
平均時間複雜度為
Insertion Sort
-
觀念: (迴圈)將
第 i 筆資料插入到前面已排序的 i - 1 筆資料中的適當位置,形成 i 筆已排序資料 -
時間複雜度
- Best case: (所有資料由小到大排好)
- Worst case: (所有資料由大到小反序排列)
- Avg case:
-
空間複雜度: (固定大小)
-
Stable -
延伸: Binary / Linear Insertion Sort
- Binary: 使用
Binary Search找到資料的適當位置 - Linear: 使用
link list儲存資料,使插入元素時間減少 - 以下操作需要進行 n - 1 輪,兩種方法分別減少了
尋找資料位置以及插入資料的時間,不過整體時間複雜度仍為
資料結構 決定資料位置 插入資料 Insertion Sort Array Binary Insertion Sort Array Linear Insertion Sort Link list - Binary: 使用
Selection Sort
- 觀念: (迴圈)自第 i 筆至最後一筆資料中
尋找最小值,並與第 i 筆資料進行 swap - 時間複雜度
- Best / Worst / Avg case 皆為
- 適合用於
大型紀錄(一筆資料包含多個欄位) 之排序上,因為每一回合最多進行一次 swap - 空間複雜度: (固定大小)
Unstable(交換時可能破壞順序)
Bubble Sort
- 觀念: (迴圈)由左而右,兩兩資料互相比較,如果
前者 > 後者則進行 swap,每一回合會使最大值移動至最右邊- 如果在某一回合
沒有進行任何 swap則可提前結束
- 如果在某一回合
- 也有由右往左進行比較的版本 (每回合將最小值移動至最左邊)
- 時間複雜度
- Best case: (所有資料由小到大排好,第一輪沒有任何 swap)
- Worst case: (所有資料由大到小反序排列)
- Avg case:
- 空間複雜度: (固定大小)
Stable
Shell Sort
- 觀念: (迴圈)根據
span將資料分為多組,在組內進行排序 (插入排序),每組完成排序之後會縮小span的值,並再次進行排序,直到span = 1為止 span型式:- 型
- ex:
- 型
- ex:
- 自定型
- 型
- 時間複雜度
- Best case:
- Worst case:
- Avg case:
- 空間複雜度: (固定大小)
Unstable(分組排序時可能破壞順序)
高等排序
平均時間複雜度為
Quick Sort
- 在 Avg case 下,實際執行時間最短的方法
- 採用
Divide and Conquer策略 - 觀念: 令第一筆資料為
pivot key,經過處理後讓其位於正確位置(左邊都比它小,右邊都比它大),之後對於左右兩邊的sublists各自進行Quick Sort
- 時間複雜度
- Best case: (
pivot key恰巧將資料分為兩等分) - Worst case: (
pivot key恰巧為最小/最大值,切割無效) - Avg case:
- Best case: (
- 空間複雜度: 取決於
recursion所需要的stack space- Best case:
- Worst case:
Unstable(交換時可能破壞順序)
Merge Sort
- 是
External sort常用方法之一 - 名詞解釋:
- Run: 排序好的片段資料
- Run 長度: Run 中的資料個數
- 可分為
Iterative / Recursive版本- Iterative:
- 將所有資料視為一個一個長度為 1 的 run
- 由左而右兩個兩個 run 進行合併
- 重複直到只剩下一個 run
- Recursive:
- 採用
Divide and Conquer策略 - 將所有資料分為左右兩半,各自進行 Merge Sort
- 將左右兩半排序完的資料進行合併
- 採用
- Iterative:
- 時間複雜度
- Best / Worst / Avg case 皆為
- 空間複雜度:
Stable
Selection Tree
用於
k-way merge(將 k 個 run 合併),可加速尋找最小值的過程,時間複雜度為
Winner tree- 將每個 run 的最小值作為葉節點
- 由下而上兩兩比較選出較小者作為父節點,直到決定出 root
- 輸出最小值 (root),並由該值來源的 run 中的值進行遞補 (與兄弟節點進行比較並調整父節點)
Loser tree(比較常用)- 類似 winner tree,但是父節點的值為較大者 (輸家)
向上比較的仍然為兩者的較小值- 遞補之後,每次比較時是與父節點進行比較
比較次數較少,因此較常被使用
Heap Sort
- 觀念:
- 先用
bottom up方法建立Max-heap - (迴圈)執行類似
Delete-Max的操作:將 root 與 heap 中最後一個資料 swap,之後進行heap 的調整(heap 的大小會 -1),直到 heap 中只剩下一個資料
- 先用
- 時間複雜度
- Best / Worst / Avg case 皆為
- 空間複雜度:
Unstable(heap 調整時可能破壞順序)
比較
| 操作輪數 | 每輪操作時間 | |
|---|---|---|
| Quick Sort | ||
| Merge Sort | ||
| Heap Sort |
線性排序
不是採用
Comparison-based的排序技巧,因此可以突破 ,達成線性時間
Radix Sort
- 又稱為
Bin Sort,Bucket Sort - 使用
Distribution & Merge(分派 & 合併) 的排序技巧 - 可分為
LSD / MSD Radix Sort
| DS 版本 | Algo 版本 | |
|---|---|---|
| straight radix | LSD Radix Sort | Radix Sort |
| radix exchange | MSD Radix Sort | Bucket Sort |
LSD Radix Sort
- 令 r 為採用之基底: Bucket 編號為 0 ~ (r - 1)
- 令 d 為資料中最大值的位數個數: 代表需要進行 d 回合
- 資料的範圍受到限制
由最低位數開始,往最高位數進行每回合的分派動作- 每回合之操作 (d 回合):
分派: 根據該位數的數值,將資料放入對應的 Bucket 中合併: 由 0 ~ (r - 1) 依序合併 Bucket 成一個串列- Bucket 中資料為
FIFO
- Bucket 中資料為
- 時間複雜度: 等級
-
- 分派:
- 合併:
-
- 空間複雜度: 等級
Stable
MSD Radix Sort
- 與 LSD 不同,只進行一次分派與合併
- 根據
資料的最大位數,分配到各個 Bucket 中 - 每個
Bucket 內部各自進行排序 - 由 0 ~ (r - 1) 依序合併 Bucket 成一個串列
- 根據
Stable(由 Bucket 內部的排序方式決定)- 當 Bucket 數量足夠多,時間會接近線性
Counting Sort
- 假設資料的範圍為 1 ~ k
- 觀念:
- 準備一個陣列統計各個鍵值的
出現次數 Count[] - 求出排序資料後各個鍵值的
起始位置 Start[] - 由左往右遍歷原始陣列,根據 Start[] 之指示,將鍵值 i 放到
Output array中的 Start[i] 位置,並將 Start[i]++
- 準備一個陣列統計各個鍵值的
- 時間複雜度:
- 鍵值範圍 k 為 等級
統整
| 初等排序 | Bset T | Avg T | Worst T | Space | Stable/Unstable |
|---|---|---|---|---|---|
| Insertion Sort | * |
S | |||
| Selection Sort | U* |
||||
| Bubble Sort | * |
S | |||
| Shell Sort | U* |
| 高等排序 | Bset T | Avg T | Worst T | Space | Stable/Unstable |
|---|---|---|---|---|---|
| Quick Sort | * |
~ | U* |
||
| Merge Sort | S | ||||
| Heap Sort | U* |
| 線性排序 | Time | Space | Stable/Unstable |
|---|---|---|---|
| Radix Sort | S | ||
| Counting Sort | S |
補充-Selection Problem
如何在 n 個資料中,選出第 i 小的資料
- 方法一: 將資料排序後取出第 i 個
- 時間複雜度 (沒有限制資料範圍)
- 方法二: 利用
Quick Sort中的Partition方法- 利用
pivot key將資料分為兩堆,並根據pivot key的位置k決定下一步- 如果
k < i: 搜尋右邊 subkist 第i - k小的資料 - 如果
k > i: 搜尋右邊 subkist 第 i 小的資料 - 如果
k = i: 回傳資料
- 如果
- 時間複雜度
- Best case:
- Worst case: (
pivot key恰巧為最小/最大值,切割無效) - Avg case:
- 利用
- 方法三:
Median of medians- 操作:
- 將所有資料
每 5 個為一組進行分配,並且對每一個組內進行 Insertion Sort,挑選出中間值 (第三個) - 對所有組別的中間值利用
Selection 遞迴取出其中間值 - 將
Median of medians作為pivot key進行Partition取得位置 k
- 將所有資料
- 類用這個方法進行
Partition的 Worst case 時間複雜度仍為- 證明見
wjungle大神的筆記
- 證明見
- 分組時至少 5 個為一組,比 5 小則時間複雜度無法達到
- 操作:





