---
###### tags: `2020 師大附中資訊科暑期培訓`
---
# 排序
2020 師大附中資訊科暑期培訓
joylintp
---
## 選擇排序(Selection Sort)
* 找到未排序的部分中最小/最大的數字
* 把該數字與未排序的數字中最左邊的數字交換
* 將未排序的數字中最左邊的數字設成已排序
----
```cpp=
for (int i = 0; i < n - 1; i++)
{
int mn = arr[i], mxp = i;
for (int j = i + 1; j < n; j++)
if (arr[j] < mn)
{
mn = arr[j];
mxp = j;
}
swap(arr[i], arr[mxp]);
}
```
複雜度 $O(n^2)$
---
## 泡沫排序(Bubble Sort)
* 將未排序的部分由左到右兩兩比較
* 若右邊的數字較小則將兩數字左右交換
* 將未排序的部分最右邊的數字設為已排序
----
```cpp=
for (int i = n - 1; i > 0; i--)
for (int j = 0; j < i; j++)
if (arr[j] > arr[j + 1])
swap(arr[j], arr[j + 1]);
```
複雜度 $O(n^2)$
---
## 計數排序(Counting Sort)
* 計算各數字的數量
* 將數字由小到大填入陣列
----
```cpp=
int cnt[1000001] = {};
for (int i = 0; i < n; i++)
cnt[arr[i]]++;
int id = 0;
for (int i = 0; i < 1000001; i++)
while (cnt[i]--)
arr[id] = i, id++;
```
複雜度 $O(n + 值域)$
---
## 合併排序(Merge Sort)
* 將陣列遞迴切成左右兩半
* 將兩側排序後依序填回原本陣列
----
```cpp=
void msort(int l, int r)
{
if (r == l)
return;
msort(l, (l + r) / 2);
msort((l + r) / 2 + 1, r);
queue<int> la, ra;
for (int i = l; i <= (l + r) / 2; i++)
la.push(arr[i]);
for (int i = (l + r) / 2 + 1; i <= r; i++)
ra.push(arr[i]);
for (int i = l; i <= r; i++)
{
if (!la.size())
arr[i] = ra.front(), ra.pop();
else if (!ra.size())
arr[i] = la.front(), la.pop();
else if (la.front() <= ra.front())
arr[i] = la.front(), la.pop();
else
arr[i] = ra.front(), ra.pop();
}
return;
}
```
時間複雜度 $O(n\log{n})$
額外空間複雜度 $O(n)$
---
## std::sort
```cpp=
#include<algorithm>
//...
int arr[] = {5, 9, 4, 8, 7};
sort(arr, arr + 5); // 遞增
sort(arr, arr + 5, greater<int>());
vector<int> v;
sort(v.begin(), v.end());
```
時間複雜度 $O(n\log{n})$
----
自訂比較函式:
```cpp=
bool cmp(int a, int b)
{
return a < b;
// 若 a 要在 b 前面回傳 true
// 否則回傳 false
}
// ...
sort(v.begin(), v.end(), cmp);
```
{"metaMigratedAt":"2023-06-15T11:45:31.529Z","metaMigratedFrom":"Content","title":"排序","breaks":true,"contributors":"[{\"id\":\"6b95215f-91a7-4eaf-bcfe-d43740108f96\",\"add\":2158,\"del\":119}]"}