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重要喔!

Made with Slides.com