暑假資讀 [3]
講師
- 227 張庭瑋
- 什麼都不會
- handle: alvingogo
- DC: Alvin Chang#6995
資料結構
什麼是資料結構
資料結構+演算法=程式
--Anonymous
Standard Template Library(STL)
- C++ 標準模板庫
- 裡面有很多 C++ 幫你寫好的東西
- 要用之前要 include
- 可以去 https://cplusplus.com/ 找
關於那些 include
#include <iostream>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <ctime>
#include <cstring>
#include <set>
#include <map>
#include <cstdlib>
#include <cmath>
#include <deque>
#include <utility>
#include <numeric>
#include <climits>
using namespace std;
int main(){
return 0;
}
#include <bits/stdc++.h>
using namespace std;
int main(){
return 0;
}
你要哪個
iterator
iterator
- 中文稱迭代器
- 有點類似 pointer,儲存記憶體位置
- 作用在 STL 的各種 container 上
- 可以利用 ++ 跟 -- 運算子,作用就是找到下一個位置的元素
- 常見的 iterator 有 begin() 跟 end()
vector
雖然第二堂課講過了但是可以再講一些觀念
vector
- 又稱 dynamic array
- 大小不是固定不變,可以任意更改
- 比一般的陣列好用
- 傳進函式裡面的方法也比一般的陣列好用
事實是我根本不會把陣列傳進函式
宣告
#include <bits/stdc++.h>
using namespace std;
int main(){
int n;
cin >> n;
vector<int> a;
vector<int> b(10);
vector<int> c(n);
vector<int> d(n,10);
vector<int> e={1,2,3};
vector<int> f=d;
vector<int> g(d.begin()+2,d.end());
vector<vector<int> > two;
return 0;
}
一些函式
#include <bits/stdc++.h>
using namespace std;
int main(){
int n;
cin >> n;
vector<int> v(n);
v[0]=1;
fill(v.begin,v.end(),0);
iota(v.begin(),v.end(),0); //用來讓 v 的元素被設成 0,1,2,3...
v.resize(10);
v.reserve(100);
v.resize(15,3);
v.clear();
v.push_back(48763);
v.emplace_back(8763);
v.pop_back();
unsigned int a=v.size();
bool b=v.empty();
int c=count(v.begin(),v.end(),1);
return 0;
}
push_back
- vector 有兩個重要的數字,分別叫做 capacity 跟 size
- capacity 永遠 >= size
- push_back 的時候會檢查目前的 size 是不是 < capacity, 如果是就直接在後面放入一個元素,否則跟系統要兩倍大的 capacity,把目前的東西複製過去,再在後面放一個元素
reserve & resize
- reserve(n) 是針對 capacity 的,如果目前的 capacity < n,跟系統要大小為 n 的 capacity,把目前的東西複製過去
- resize(n) 是針對 size 的,如果目前的 size < n,就把 size 變成 n,然後後面補 0 (或你想要的東西),如果 n > capacity 則會先照上面那一套流程做
注意事項
- push_back 有點慢
- 只有 size 裡面才是可以用 [] 存取的資料,capacity 只是預留空間而已,裡面的東西是不確定的
遍歷
int main(){
int n;
cin >> n;
vector<int> v(n);
for(int i=0;i<n;i++){
cin >> v[i];
}
return 0;
}
int main(){
int n;
cin >> n;
vector<int> v(n);
for(int &h:v){
cin >> h;
}
return 0;
}
pair
pair
- 是一種結構
- 只能放兩個東西
- 那兩個東西可以是不一樣的型態
- 用 first 跟 second 存取
宣告
#include <bits/stdc++.h>
#define fs first
#define sc second
using namespace std;
int main(){
pair<int,int> a;
pair<int,double> b={1,-1.23};
pair<char,double> c('Y',0.48763);
pair<int,pair<int,int> > d=make_pair(1,make_pair(2,3));
pair<string,vector<pair<int,int> > > v;
vector<pair<int,int> > g(10,{2,3});
return 0;
}
取值
#include <bits/stdc++.h>
using namespace std;
int main(){
pair<int,int> a(1,2);
int b=a.first,c=a.second;
return 0;
}
stack, queue, deque
stack
- 又稱堆疊
- 常用的比喻是洗盤子跟拿盤子
- 是一種後進先出的資料結構
queue
- 又稱佇列
- 就跟排隊一樣是先進先出
deque
- 又稱雙向佇列
- 關於他的念法我們專門再做一個表單讓大家吵架
- 有點像 stack 跟 queue 的結合,哪邊先進去或出來都可以
很抽象嗎 來看 code
#include <bits/stdc++.h>
using namespace std;
int main(){
stack<int> s;
s.push(10);
s.push(20);
cout << s.top() << "\n"; //20
s.pop();
cout << s.top() << "\n"; //10
return 0;
}
#include <bits/stdc++.h>
using namespace std;
int main(){
deque<int> dq;
dq.push_back(10);
dq.push_back(20);
cout << dq.back() << "\n"; //20
dq.pop_back();
cout << dq.front() << "\n"; //10
dq.push_front(15);
dq.push_back(30);
cout << dq.front() << "\n"; //15
return 0;
}
#include <bits/stdc++.h>
using namespace std;
int main(){
queue<int> q;
q.push(10);
q.push(20);
cout << q.front() << "\n"; //10
q.pop();
cout << q.front() << "\n"; //20
return 0;
}
stack, queue, deque
也有 size 跟 empty 這些函數
其實這三個東西都是可以用 vector 寫出來的
有興趣可以寫寫看
題單
priority_queue
priority_queue
- 中文叫做優先佇列
- 可以支援三種操作:加入一個數、刪除最大(小)值、取得最大(小)值,都是 O(logn)
- 預設是只能取最大值,
除非你是 YTP - 不說了 直接看 code
priority_queue
#include <bits/stdc++.h>
using namespace std;
int main(){
priority_queue<int> pq;
pq.push(3);
pq.push(6);
cout << pq.top() << "\n"; //6
pq.pop();
cout << pq.top() << "\n"; //3
return 0;
}
size 跟 empty 也可以用
set
set
- 跟數學上的集合很相似
- 可支援的操作是加入元素、刪除元素、查詢一個元素是否在集合裡面 也都是 O(logn)
- 會自動幫我們排序
- 常數有點大 使用要小心
code
#include <bits/stdc++.h>
using namespace std;
int main(){
set<int> s;
s.insert(3);
s.insert(6);
s.insert(8);
s.insert(4);
s.erase(6);
s.find(3);
s.erase(s.find(3));
for(auto h:s){
}
for(set<int>::iterator it=s.begin();it!=s.end();it++){
}
bool a=s.empty();
int z=s.size();
return 0;
}
multiset
- 跟 set 類似
- 元素可重複,依然會自動排序
- 刪除方法要特別注意
- 具體而言 erase(value) 會刪除所有值為 value 的元素
- 有時候我們只想刪一個就得用 erase(find(value))
lower_bound
- 可以找到 >= 他的最小元素
- 在 vector set map 等等的都可以用
vector<int> v;
set<int> s;
cout << v[lower_bound(v.begin(),v.end(),3)-v.begin()] << "\n";
cout << *s.lower_bound(4) << "\n";
map & unordered_map
map
- 中文似乎叫做映射(?
- 由兩個東西組成:key 跟 value
- 可以利用陣列取值的方式
- 一樣會自動排序
map
#include <bits/stdc++.h>
using namespace std;
int main(){
map<int,int> m;
m[3]=1;
if(m.find(5)==m.end()){ //find key
m[5]=2;
}
m.insert({2,2});
m.erase(3);
for(auto h:m){//key
}
for(map<int,int>::iterator it=m.begin();it!=m.end();it++){
}
int a=m.size();
bool b=m.empty();
return 0;
}
unordered_map
- 是一種 hash table
- 會依據輸入的數值做 hash
- 不會自動幫你排序
- 使用小心,hash 很容易碰撞
- 有時候寧可犧牲一個 log 也不願用 unordered_map
- 我很久沒用了(?
- code 就不放了 跟 map 的幾乎一模一樣
題單時間
STL
By alvingogo
STL
- 447