STL and Sorting
Lecturer:Yeedrag
上週我們學了甚麼STL?
窩猜你們網課都沒有認真聽.w.
Vector
Queue
Stack
Pair/Tuple
這次會教ㄉSTL:
priority_queue
(unordered)map
(unordered)set
priority_queue
需先#include<queue>
priority_queue是啥?
如其名:優先佇列!
每一次pq的最上面元素一定是裡面最大/小的!
priority_queue的宣告
和操作:
宣告
priority_queue<型態,容器,排序方式> 名字
容器:支持vector或deque,預設vector
排序方式:
預設/less<型態> top()為最大的
greater<型態> top()為最小的
宣告
#include<iostream>
#include<queue>
using namespace std;
int main(){
priority_queue<int> pq1;
priority_queue<int,vector<int>,greater<int>> pq2;
priority_queue<long long int,vector<int>,less<long long int>> pq3;
}
pq1跟pq3都是最大的在上面(max heap)
pq2則是最小的在上面(min heap)
插入元素
.push(x)
#include<iostream>
#include<queue>
using namespace std;
int main(){
priority_queue<int> pq;
pq.push(3);
pq.push(5);
}
時間複雜度:\(O(logn)\) (因為是heap)
訪問頂端元素
.top()
#include<iostream>
#include<queue>
using namespace std;
int main(){
priority_queue<int> max_pq;
priority_queue<int,vector<int>,greater<int>> min_pq;
max_pq.push(3);
max_pq.push(5);
min_pq.push(3);
min_pq.push(5);
cout<<max_pq.top()<<endl;//5
cout<<min_pq.top()<<endl;//3
}
時間複雜度:\(O(1)\)
將頂端元素移除
.pop()
#include<iostream>
#include<queue>
using namespace std;
int main(){
priority_queue<int> max_pq;
max_pq.push(3);
max_pq.push(5);
cout<<max_pq.top()<<endl;//5
max_pq.pop();//移除5
cout<<max_pq.top()<<endl;//3
}
時間複雜度:\(O(logn)\)
檢測pq大小
.size()
#include<iostream>
#include<queue>
using namespace std;
int main(){
priority_queue<int> max_pq;
max_pq.push(3);
max_pq.push(5);
cout<<max_pq.size()<<endl;//2
max_pq.pop();
cout<<max_pq.size()<<endl;//1
}
時間複雜度:\(O(1)\)
檢測pq是否為空
.empty()
#include<iostream>
#include<queue>
using namespace std;
int main(){
priority_queue<int> max_pq;
max_pq.push(3);
if(max_pq.empty()){
cout<<"Empty!"<<endl;
} else {
cout<<"Not empty!"<<endl;
}
}//Not empty!
時間複雜度:\(O(1)\)
例題:
想一想(通靈一下),怎麼做才能讓加起來最小?
set
需先#include<set>
set是啥?
其實就是數學上的那種集合
每個元素並不會重複
也就是每個值唯一
如其名:集合!
set的宣告
和操作:
宣告
set<型態> 名字
#include<iostream>
#include<set>
using namespace std;
int main(){
set<int> s;
}
插入元素
.insert(x)
#include<iostream>
#include<set>
using namespace std;
int main(){
set<int> s;
s.insert(3);
s.insert(5);
}
時間複雜度:\(O(logn)\) (因為是紅黑樹)
將元素移除
.erase(x), x可以是值或迭代器
#include <iostream>
#include <set>
using namespace std;
int main() {
set<int> s;
s.insert(3);
s.insert(5);
s.erase(5);//移除5
s.erase(s.begin());//移除第1項(3)
}
時間複雜度:\(O(logn)\) (如果值不存在不會發生任何事)
檢測Set大小
.size()
#include<iostream>
#include<set>
using namespace std;
int main(){
set<int> s;
s.insert(3);
s.insert(5);
cout<<s.size()<<endl;//2
s.erase(3);
cout<<s.size()<<endl;//1
}
時間複雜度:\(O(1)\)
檢測set是否為空
.empty()
#include<iostream>
#include<set>
using namespace std;
int main(){
set<int> s;
s.insert(3);
if(s.empty()){
cout<<"Empty!"<<endl;
} else {
cout<<"Not empty!"<<endl;
}
}//Not empty!
時間複雜度:\(O(1)\)
檢測Set是否存在元素
.count(x)
#include<iostream>
#include<set>
using namespace std;
int main(){
set<int> s;
s.insert(3);
if(s.count(3)) {
cout << "exists\n";
}
else {
cout << "doesn't exists\n";
}//exists
}
時間複雜度:\(O(log n)\)
補充:
multiset<int> 像是set,但可以記錄數字有幾個
unordered_set<int> 沒有排序的set,不能
使用*s.begin()或*--s.end()之類的方法得到最大最小值,
但是\(O(1)\) (註:是可以被卡到\(O(n\))的!)
map
需先#include<map>
map又是啥?
一個關鍵字對應一個值!
(很像是Python的dictionary)
map的宣告
和操作:
宣告
map<關鍵字型態,值型態> 名字
#include<iostream>
#include<map>
using namespace std;
int main(){
map<int,int> m1;
map<string,int> m2;
map<char,string< m3;
}
插入
兩種方法:
1.insert一個pair
2.像是array一樣賦值
#include<iostream>
#include<map>
#include<utility>
using namespace std;
int main(){
map<string,int> m1;
m1.insert(pair<string,int>("yeedrag",1));
m1["yeedrag"] = 1;//兩個等同!
}
時間複雜度:\(O(logn)\) (因為是紅黑樹)
透過關鍵字取得值
同array,只是索引值變成關鍵字
#include<iostream>
#include<map>
using namespace std;
int main(){
map<string,int> m1;
m1["yeedrag"] = 1;
cout<<m1["yeedrag"]<<endl;//1
m1["yeedrag"]++;
cout<<m1["yeedrag"]<<endl;//2
}
清空所有資料
.clear()
#include<iostream>
#include<map>
using namespace std;
int main(){
map<string,int> m1;
m1["yeedrag"] = 1;
cout<<m1["yeedrag"]<<endl;//1
m1.clear();
cout<<m1["yeedrag"]<<endl;//預設空的是0
}
時間複雜度:\(O(n)\)
例題:
給你\(n\)個數字,問可以去掉幾對數字還可以讓剩下數字的平均和原本一樣?
(可用map 或 multiset)
Sorting Algorithms
你有以下的困擾嗎?
那這堂課很適合你!
視覺化sort的網站:
先想一想怎麼做或許可行?
讓數字像泡泡一樣,
大的浮上去,小的沉下來。
Title Text
void bubble_sort(int arr[],int size){
for(int i=4;i>=1;i--){
for(int j=1;j<=i;j++){
if(arr[j]<arr[j-1]){//如果前面的比後面的大
swap(arr[j],arr[j-1]);//兩個交換
}
}
}
}
int main(){
int arr[5] = {1,5,3,4,2};
bubble_sort(arr,5);
for(int i=0;i<5;i++){
cout<<arr[i]<<" ";
} //1,2,3,4,5
}
Bubble Sort 實作
時間複雜度:\(O(N^2)\)
每一次遍歷都沿路把最大的數字交換,總共遍歷\(N\)次,所以複雜度是\(O(N*N) = O(N^2)\)
每次找出最大(小)的,把它放到正確的位置上。
一些其他的sort:
-
Heap sort \(O(nlogn)\)
-
Insertion sort \(O(N^2)\)
-
Merge sort \(O(nlogn)\)
-
Quick sort \(O(nlogn)\)
- ........etc
補充:Bogo Sort
最猛最快的sort
隨機打亂直到成功,浪漫na
void bogo_sort(int arr[],int size){
while(!is_sorted(arr,arr+size)){
random_shuffle(arr,arr+size);
}
}
最好複雜度:\(O(N\))
最差:無限w
一些其他的sort:
-
Heap sort
-
Insertion sort
-
Merge sort
-
Quick sort
- ........etc
哭喔好累 有沒有簡單易點的寫法阿?
std::sort()!!!!
整堂課裡唯一有用的地方!
還是驚人的\(O(nlogn)\)!!!
需要#include<algorithm>
sort()用法:
Array: sort(arr,arr+大小,(排序方式));
Vector: sort(vec.begin(),vec.end(),(排序方式));
sort(arr,arr+5,greater<int>()) 由大到小sort第0項到第4項
sort(arr+2,arr+4) sort第2項到第3項
sort(vec.begin(),vec.end()) 由大到小sort整個Vector
範例:
預設 or less<T>(): 小到大
greater<T>(): 大到小
sort() 自訂函數
萬一我有個pair的陣列想由第二項來sort呢?
bool cmp(pair<int,int> a,pair<int,int> b){
//如果true 則 a 在前面,反之則 b 在前面
if(a.second==b.second){//如果第二項相同,比較第一項
return a.first<b.first;
} else {
return a.second<b.second;
}
}
int main(){
pair<int,int> arr[5] = {{1,3},{2,5},{7,1},{6,4},{17,3}};
sort(arr,arr+5,cmp);
for(int i=0;i<5;i++) cout<<arr[i].first<<" "<<arr[i].second<<endl;
}
OAOb
SORT hen重要喔!
stl & sorting
By yeedrag
stl & sorting
- 871