<style>
.reveal .slides {
font-size: 40px;
}
</style>
# 南大附中資訊研究社 NFIRC 1st
## 第 10 次社課講義
2024/04/17
主講:ShiYu
---
## 課前準備
----
## 今日課程內容
# 排序演算法
## 1. 氣泡排序法
## 2. 選擇排序法
## 3. 插入排序法
## 進階:合併排序法
---
## 什麼是排序演算法?
----
## 什麼是排序演算法?
將資料以特定規則重新排列
----
### 上次已經教過了 C++ 內建的 sort 函式了
## 為什麼還要學排序演算法?
----
### 上次已經教過了 C++ 內建的 sort 函式了
## 為什麼還要學排序演算法?
<!-- 當我們用內建 sort 函式幫我們排序
我們只停留在應用而已 而沒有實際去了解其中的原理 -->
真正去學習演算法才能培養解決問題的能力
----
## 在還沒學過排序演算法之前
先請各位到前面以自己的方式嘗試排序一下撲克牌
---
## 1. 氣泡排序法 Bubble Sort
每次交換相鄰元素重複直到完成排序
動畫:https://visualgo.net/zh/sorting
----
## 實際操作
----
## 實作 Code
```cpp=
void BubbleSort()
{
int n = v.size();
for (int i=n; i>1; --i)
{
for (int j=0; j<i-1; ++j)
{
if (v[j] > v[j+1])
{
swap(v[j],v[j+1]);
}
}
}
}
```
----
## 時間複雜度是多少?
----
## 時間複雜度是多少?
有 n 個元素要浮上來
每個元素都需要遍歷一次數列
所以為 $n^2$
---
## 2. 選擇排序法 Selection Sort
選擇最小的元素放到前面重複直到完成排序
動畫:https://visualgo.net/zh/sorting
----
## 實際操作
----
## 實作 Code
```cpp=
void SelectionSort()
{
int n = v.size();
for (int i=0; i<n-1;++i)
{
int mini = i;
for (int j=i; j<n; ++j)
{
if (v[j] < v[mini])
{
mini = j;
}
}
swap(v[i],v[mini]);
}
}
```
----
## 時間複雜度是多少?
----
## 時間複雜度是多少?
每次找最小的元素需要遍歷整個數列
要遍歷 n 次才能讓整個數列完成排序
所以為 $n^2$
---
## 3. 插入排序法 Insertion Sort
將未排序的元素依對應位置插入已排序好的序列
動畫:https://visualgo.net/zh/sorting
----
## 實際操作
----
```cpp=
void InsertSort()
{
int n = v.size();
for (int i=1; i<n;++i)
{
int temp = v[i], j = i-1;
while (j >= 0 && temp < v[j])
{
v[j+1] = v[j];
j--;
}
v[j+1] = temp;
}
}
```
----
## 時間複雜度是多少?
----
## 時間複雜度是多少?
要遍歷 n 個元素
並往前搬動到序列中
所以為 $n^2$
---
## 進階:合併排序法 Merge Sort
一種以 分治法 為核心概念的排序演算法
不斷的將數列切分成兩個小數列
再將兩個小數列以特定方式合併成有序
透過遞迴就可完成排序
動畫:https://visualgo.net/zh/sorting
----
## 實際操作
----
```cpp=
void merge(int l, int r)
{
int mid = (l+r)/2, tmp[r-l+1];
for(int i=l,j=mid+1,k=0; i<=mid || j<=r; ++k)
{
if((v[i] <= v[j] && i <= mid) || j > r) tmp[k] = v[i++];
else tmp[k] = v[j++];
}
for(int i=l,j=0; i<=r; ++i,++j) v[i] = tmp[j];
}
void MergeSort(int l, int r)
{
if(l == r) return;
int mid = (l+r)/2;
MergeSort(l,mid); MergeSort(mid+1,r);
merge(l,r);
}
```
----
## 時間複雜度是多少?
----
## 時間複雜度是多少?
每次都將數列切成兩半 $\log n$
把兩段數列合併成一段 $n$
所以是 $n \log n$
---
## 這麼多種排序演算法
## 我該選哪種?
----
## 比較各種排序演算法
| 排序演算法 | 最差時間複雜度 | 空間複雜度 |
| --- | --- | --- |
| 氣泡排序 | $O(n^2)$ | $O(1)$ |
| 選擇排序 | $O(n^2)$ | $O(1)$ |
| 插入排序 | $O(n^2)$ | $O(1)$ |
| 合併排序 | $O(n\log n)$ | $O(n)$ |
---
## 實作練習
### [ZJ a104. 排序](https://zerojudge.tw/ShowProblem?problemid=a104)
這題大家在之前的提單有用內建的 sort 函式寫過
可以試著用氣泡、選擇、插入排序分別來寫寫看
----
## 進階題
### [ZJ a233. 排序法 挑戰極限](https://zerojudge.tw/ShowProblem?problemid=a233)
這題用前三種複雜度 $n^2$ 的排序演算法會 TLE
要用 Merge sort 才會過 複雜度 $n \log n$
---
## 延伸閱讀
詳細介紹 10 種不同的排序演算法
## [ShiYu Blog 文章連結](https://shiyu0318.github.io/post/Sort-Algorithm/)
{"title":"第 10 次社課講義","contributors":"[{\"id\":\"a5e01884-520b-4df5-8e23-bfcc32fb4697\",\"add\":3555,\"del\":431}]","description":"2024/04/17主講:ShiYu"}