# 排序(sort)
## 基本介紹
排序,顧名思義就是將一個陣列中的所有元素依照特定順序去做排列,若要使用此函式需引用名為 ```algroithm``` 的標頭檔
```cpp
#include <algorithm>
```
收錄在 ```algorithm``` 的 ```sort``` 是最快的排序演算法,時間複雜度約為 $O(n\ log\ n)$,當然也有其他時間複雜度較慢的排序演算法,如泡沫排序法或合併排序法,但在此章節暫不介紹
*所以不要覺得自己能手刻出比 ```std::sort``` 還快的排序方法 ||邱O家曾經想做過||*
## 在傳統 array 中使用 sort 凾式
==```sort``` 的預設排序方式是遞增喔==
```cpp=
#include <iostream>
#include <algorithm> //這很重要!!!
using namespace std;
int main(){
int arr[10] = {5, 6, 3, 8, 7, 9, 10, 2, 1, 4}; // 排序前的陣列
sort(arr, arr+10);
// 假設你要從 arr[i] 排序到 arr[j], 你就會要打 sort(arr + i, arr + j + 1);
// 像這裡就是由 arr[0] 排到 arr[9] 的結果, 當然 i 跟 j 也可以自己改改看
for(int i = 0; i < 10; i++){
cout << arr[i] << ' ';
}
// 輸出排序完的陣列
cout << '\n';
return 0;
}
```
```
1 2 3 4 5 6 7 8 9 10
```
## 在 vector 中使用 sort 函式
==```sort``` 的預設排序方式是遞增喔==
```cpp=
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main(){
vector<int> vec;
vec.push_back(4);
vec.push_back(2);
vec.push_back(3);
vec.push_back(5);
vec.push_back(6);
vec.push_back(1);
// 排序前的陣列
sort(vec.begin(), vec.end());
// 假設你要從 vec[i] 排序到 vec[j], 你就會要打 sort(vec.begin() + i, vec.end() - vec.size() + j);
// 不要看我註解那行然後覺得很麻煩,如果要重頭排到尾的話,直接打我16行那一行就好了
// 像這裡就是由 vec[0] 排到 vec[5] 的結果, 當然 i 跟 j 也可以自己改改看
for(int i = 0; i < vec.size(); i++){
cout << vec[i] << ' ';
}
// 輸出排序完的陣列
cout << '\n';
return 0;
}
```
```
1 2 3 4 5 6
```
## 將陣列中的元素以遞減排序
在```std::sort```中的預設排序方式是遞增(less), 若是要遞減的話, 可參考以下寫法
使用 ```greater``` 函式
:::spoiler code
```cpp=
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main(){
vector<int> vec;
vec.push_back(4);
vec.push_back(2);
vec.push_back(3);
vec.push_back(5);
vec.push_back(6);
vec.push_back(1);
// 排序前的陣列
sort(vec.begin(), vec.end(), greater<int>());
for(int i = 0; i < vec.size(); i++){
cout << vec[i] << ' ';
}
// 輸出排序完的陣列
cout << '\n';
return 0;
}
```
:::
當然也可以用遞增排序完之後再用```reverse```換成遞減
:::spoiler code
```cpp=
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main(){
vector<int> vec;
vec.push_back(4);
vec.push_back(2);
vec.push_back(3);
vec.push_back(5);
vec.push_back(6);
vec.push_back(1);
// 排序前的陣列
sort(vec.begin(), vec.end());
//comment 起來的是第一種寫法, 直接for迴圈交換頭尾
/*
for(int i = 0; i < vec.size() / 2; i++){
int temp = vec[vec.size() - i - 1];
vec[vec.size() - i - 1] = vec[i];
vec[i] = temp;
}
*/
//也可用reverse函式
reverse(vec.begin(), vec.end());
for(int i = 0; i < vec.size(); i++){
cout << vec[i] << ' ';
}
// 輸出排序完的陣列
cout << '\n';
return 0;
}
```
:::
## 自定義排序方法
在此簡單舉兩個例子
### 在 pair 內先比 second 的大小再比 first 的排序
:::spoiler code
```cpp=
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
//以下這個函式若放在sort中, sort就會依照函式所寫之判斷方式去排序
bool cmp(pair<int,int> p1, pair<int, int> p2){
if(p1.second == p2.second){
return p1.first > p2.first;
//若函式回傳true, 代表p1會被排在p2的左邊
}
return p1.second > p2.second;
//以此程式碼為例, 將會先比較second再比較first並以遞減排序
}
int main(){
vector<pair<int,int>> vec;
vec.push_back({1, 2});
vec.push_back({3, 1});
vec.push_back({5, 2});
vec.push_back({1, 6});
sort(vec.begin(), vec.end(), cmp);
//在sort函式中放入自訂義之cmp函式即可依自己設計的方式排序
for(int i = 0; i < vec.size(); i++){
cout << vec[i].first << ' ' << vec[i].second << '\n';
}
}
```
:::
### 將兩個字串以字典序排序
[維基百科中對於字典序的介紹](https://zh.wikipedia.org/zh-tw/%E5%AD%97%E5%85%B8%E5%BA%8F)
:::spoiler code
```cpp=
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
bool cmp(string a, string b){
for(int i = 0; i < min(a.size(), b.size()); i++){
if(a[i] == b[i]) continue;
return a[i] < b[i];
}
return a.size() < b.size();
}
int main(){
int n;
cin >> n;
vector<string> vec;
for(int i = 0; i < n; i++){
string str;
cin >> str;
vec.push_back(str);
}
sort(vec.begin(), vec.end(), cmp);
for(int i = 0; i < n; i++){
cout << vec[i] << '\n';
}
}
```
:::
## 練習題
### [Zerojudge a233. 排序法~~~ 挑戰極限](https://zerojudge.tw/ShowProblem?problemid=a233)
:::spoiler AC code
```cpp=
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
int n;
cin >> n;
vector<int> vec(n);
for(int i = 0; i < n; i++){
cin >> vec[i];
}
sort(vec.begin(), vec.end());
for(int i = 0; i < n; i++){
cout << vec[i] << ' ';
}
cout << '\n';
}
```
:::
### [Zerojudge a225. 明明愛排列](https://zerojudge.tw/ShowProblem?problemid=a225)
:::spoiler AC Code
```cpp=
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
vector<int> vec;
bool cmp(int a, int b){
if(a % 10 == b % 10){
return a > b;
}
return (a % 10) < (b % 10);
}
int main(){
int n;
while(cin >> n){
vec.resize(n);
for(int i = 0; i < n; i++){
cin >> vec[i];
}
sort(vec.begin(), vec.end(), cmp);
for(int i = 0; i < n; i++){
cout << vec[i] << ' ';
}
cout << '\n';
}
}
```
:::
### [Zerojudge a528. 大數排序](https://zerojudge.tw/ShowProblem?problemid=a528)
:::spoiler AC Code
```cpp=
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
bool cmp(pair<bool,string> a, pair<bool,string> b){
if(a.first != b.first) return a.first;
if(!a.first){
if(a.second.size() != b.second.size()) return a.second.size() < b.second.size();
for(int i = 0; i < a.second.size(); i++){
if(a.second[i] != b.second[i]) return a.second[i] < b.second[i];
}
}else{
if(a.second.size() != b.second.size()) return a.second.size() > b.second.size();
for(int i = 0; i < a.second.size(); i++){
if(a.second[i] != b.second[i]) return a.second[i] > b.second[i];
}
}
return false; //這很重要
}
int main(){
vector<pair<bool, string>> vec;
int n;
while(cin >> n){
vec.resize(n);
for(int i = 0; i < n; i++){
string s;
cin >> s;
if(s[0] == '-'){
vec[i] = make_pair(1, s.substr(1));
}else{
vec[i] = make_pair(0, s);
}
}
sort(vec.begin(), vec.end(), cmp);
for(int i = 0; i < n; i++){
if(vec[i].first) cout << '-';
cout << vec[i].second << '\n';
}
}
}
```
:::
## 總結
```sort```總結來說有以下四種用法
在 $array$ 中 :
* ```sort(arr, arr+n) //預設遞增排序```
* ```sort(arr, arr+n, cmp) //自訂義排序```
在 $vector$ 中 :
* ```sort(vec.begin(), vec.end()) //預設遞增排序```
* ```sort(vec.begin(), vec.end(), cmp) //自訂義排序```