如何去存一個資料
Photo Credit: 112CS 蔡欣穆教授的DSA
先進先出的專有名詞:FIFO (First In First Out)
函式庫 | #include <queue> |
---|---|
宣告 | std::queue<T> Q; |
enqueue(放屁股) | Q.push(T); |
dequeue(拿頭) | Q.pop(); |
看前面是誰 | Q.front(); |
現在裡面有幾個? | Q.size(); |
現在是不是空的? | Q.empty() |
T可以帶入所有型態,包括你自己寫的struct。
以上全O(1)操作。
#include <iostream>
#include <queue>
using namespace std;
struct crood{
int x,y;
crood(int _x,int _y){
x = _x, y = _y;
}
};
int main(){
queue<crood> Q;
Q.push(crood(1,1));
Q.push(crood(3,3));
cout << Q.front().x << endl;
Q.pop();
cout << Q.front().x << endl;
}
// 輸出 1 3
先進先出的專有名詞:LIFO (Last In First Out)
函式庫 | #include <stack> |
---|---|
宣告 | std::stack<T> S; |
enqueue(放屁股) | S.push(T); |
dequeue(拿頭) | S.pop(); |
看屁股是誰 | S.top(); |
現在裡面有幾個? | S.size(); |
現在是不是空的? | S.empty() |
T可以帶入所有型態,包括你自己寫的struct。
以上全O(1)操作。
#include <iostream>
#include <stack>
using namespace std;
struct crood{
int x,y;
crood(int _x,int _y){
x = _x, y = _y;
}
};
int main(){
stack<crood> S;
S.push(crood(1,1));
S.push(crood(3,3));
cout << S.top().x << endl;
S.pop();
cout << S.top().x << endl;
}
// 輸出 3 1
它唸作Deck,不唸De-queue
函式庫 | #include <deque> |
---|---|
宣告 | std::deque<T> D; |
放頭 | D.push_front(T); |
放屁股 | D.push_back(T); |
拿頭 | D.pop_front(T); |
拿屁股 | D.pop_back(); |
看頭是誰 | D.front(); |
看屁股是誰 | D.back(); |
現在是不是空的? | D.empty(); |
#include <iostream>
#include <deque>
using namespace std;
struct crood{
int x,y;
crood(int _x,int _y){
x = _x, y = _y;
}
};
int main(){
deque<crood> D;
D.push_back(crood(1,1));
D.push_back(crood(2,2));
D.push_front(crood(3,3));
cout << D.front().x << endl;
D.pop_front();
cout << D.front().x << endl;
D.pop_front();
cout << D.front().x << endl;
}
// 輸出 3 1 2
函式庫 | #include <vector> |
---|---|
一般宣告 先宣告N個東西 先宣告N個c的東西 |
std::vector<T> V; std::vector<T> V(N); std::vector<T> V(N,c); |
enqueue(放屁股) | V.push_back(T); |
dequeue(拿屁股) | V.pop_back(); |
清空整個vector | V.clear(); |
現在裡面有幾個? | V.size(); |
現在是不是空的? | V.empty(); |
在vector的iter插入x | V.insert(iter,x); |
在iter刪除東西 | V.erase(iter); |
存取第k個東西 | V[k] |
開頭的iterator | V.begin() |
結尾的iterator(指向最後一個元素+1) | V.end() |
#include <iostream>
#include <vector>
using namespace std;
int main(){
vector<int> V(5,-1);
for(int i=0;i<5;i++)
V.push_back(i);
V[2] = -10;
V.pop_back();
for(int i=0;i<V.size();i++)
cout << V[i] << " ";
}
// 輸出-1 -1 -10 -1 -1 0 1 2 3
Photo Credit: 112CS 蔡欣穆教授的DSA
假設宣告了 ... | vector<int> V | int ary[N] |
---|---|---|
拿到一個container的開頭iter/ptr | V.begin() | ary |
拿到一個container的結尾iter/ptr | V.end() | ary+N |
這一個iterator指到的東西是什麼? | *(iter) | *ptr |
下一個iterator是誰? | iter + 1 | ptr + 1 |
讓它變成下一個iterator | iter++ | ptr ++ |
iterator/ptr的型態? | vector<int>::iterator | ptr |
在vector的iter插入x | V.insert(iter,x); |
---|---|
在iter刪除東西 | V.erase(iter); |
在vector的地k個插入x | V.insert(V.begin()+k,x); |
---|---|
在vector的第k個刪除 | V.erase(V.begin()+k); |
#include <iostream>
#include <vector>
using namespace std;
int main(){
vector<int> V(5,-1);
for(int i=0;i<5;i++)
V.push_back(i);
vector<int>::iterator iter;
V.insert(V.begin()+1, -10);
V.erase(V.begin());
for(iter = V.begin(); iter != V.end() ; iter++)
cout << *(iter) << " ";
cout << endl;
}
// 輸出-10 -1 -1 -1 -1 0 1 2 3 4
#include <iostream>
#include <vector>
using namespace std;
int main(){
vector<int> V(1),V2(1024,77);
vector<int>::iterator iter=V.begin()+2047;
for(int i=0;i<=2048;i++)
V.push_back(i);
cout << *iter << endl;
}
自動偵測型態並且幫你填補。
假設宣告了 ... | auto會幫你填.... |
---|---|
auto i = 0; | int |
auto s = "aoa"; | char * |
auto d = 0.0; | double |
auto c = 'X'; | char |
auto iter = std::vector<int>.begin() | std::vector<int>::iterator |
auto iter = std::list<int>.begin() | std::vector<list>::iterator |
vector<int> V(5,-1);
std::vector<int>::iterator iter;
for(iter = V.begin(); iter != V.end() ; iter++){
int i = *(iter);
// 做一些事情
}
vector<int> V(5,-1);
for( int i : V){
// 做一些事情
}
for( auto i : container ){
// 做一些事情
}
所以對於所有container可以寫成這樣
函式庫 | #include <list> |
---|---|
宣告 | std::list<T> L; |
放頭 | L.push_front(T); |
放屁股 | L.push_back(T); |
拿頭 | L.pop_front(T); |
拿屁股 | L.pop_back(); |
頭的iterator | L.begin(); |
結尾的iterator (最後一個+1) | L.end(); |
iterator指向下一個 | iter ++ ; **list的iter不能+=1** |
iterator指到上一個 | iter -- ; |
在iter插入x | L.insert(iter,x); |
在iter刪除x | L.erase(iter); |
#include <iostream>
#include <list>
using namespace std;
int main(){
list<int> L;
L.push_back(1); // front (1) - end
L.push_front(0); // front (0) - 1 - end
L.push_back(3); // front (0) - 1 - 3 - end
list<int>::iterator iter;
iter = L.begin(); // front/iter (0) - 1 - 3 - end
cout << *iter << endl;
L.insert(iter,5); // front(5) - iter(0) - 1 - 3 - end
iter++; // front(5) - 0 - iter(1) - 3 - end
L.erase(iter); // front(5) - 0 - 3 - end
for(auto i: L)
cout << i << " ";
cout << endl;
}
// 輸出 5 0 3
名稱 | 拿front |
拿end | 放front | 放end | 看front | 看end |
---|---|---|---|---|---|---|
stack | S.pop() | S.push() | S.top() | |||
queue | Q.pop() |
Q.push() | Q.front() | |||
deque | Q.pop_front() |
Q.pop_back() | Q.push_front() | Q.push_back() | Q.front() | Q.back() |
vector | Q.pop_back() | Q.push_back() | Q.front() | Q.back() | ||
list | Q.pop_front() |
Q.pop_back() | Q.push_front() | Q.push_back() |
名稱 | empty() | size() | clear() | 開頭iter: begin() | 結尾iter: end() |
---|---|---|---|---|---|
stack | O | O | X | 沒有iterator | 沒有iterator |
queue | O | O | X | 沒有iterator | 沒有iterator |
deque | O | O | O | O | O |
vector | O | O | O | O | O |
list | O | O | O | O | O |
相對的,vector就快很多。
因此對一個情境找到一個最適當的資料結構才是最好的。
* Challenge 1難度 > Challenge 2難度 >> HW難度
宣告: std::pair<int,int>
做出一個pair:std::make_pair(a,b);
這個要用stack來做。
但是小於k的勇者們這次溝通完就用不到了。因為這個勇者會阻斷他根後面勇者的溝通
這是一個特判。
#include <iostream>
#include <stack>
using namespace std;
int T,n,x;
int main(){
cin >> T;
while(T--){
long long ans = 0;
scanf("%d",&n);
stack<pair<int,int> > S;
while(n--){
scanf("%d",&x);
while(!S.empty() && S.top().first < x)
ans+=S.top().second,S.pop();
int tmp = 0;
if(!S.empty() && S.top().first == x){
ans += tmp = S.top().second;
S.pop();
}
if(!S.empty())
ans++;
S.push(make_pair(x,tmp+1));
}
cout << ans << endl;
}
return 0;
}
假如現在做[0,3],那麼下一個就是[1,4],再下一個就是[2,5]
所以你的container會是一個非嚴格遞增數列。 -> 答案都會是deque.front()
#include <iostream>
#include <deque>
using namespace std;
int ans[10000000];
int main(){
deque<pair<int,int> > D;
int n,k,q,i,x;
cin >> n >> k;
cin >> x;
D.push_back(make_pair(x,0));
for(int i=1;i<n;i++){
cin >> x;
while(!D.empty() && D.back().first > x)
D.pop_back();
D.push_back(make_pair(x,i));
if(D.front().second == i-k)
D.pop_front();
ans[i] = D.front().first;
}
scanf("%d",&q);
while(q--){
cin >> i;
cout << ans[i+k-1] << endl;
}
}