STL
講者:思諾&娟
-
STL=Standard Template Library=標準模板庫
-
包含演算法/容器/迭代器
-
其中,有很多好用的”容器”,例如:queue/vector/set
-
每種容器都有自己的特性,可以善加利用
-
注意時間複雜度,STL裡面的函式常常不是O(1)
STL是甚麼?
-
後進先出(例如:一堆書本)
-
從最頂端進行存取 / 刪除 / 新增 資料
Stack(堆疊)
指令
#include <stack>
stack <int> stk;
stk.top(); //回傳stack頂端的值
stk.pop(); //刪除stack頂端的資料
stk.push(); // 將新值加入stack
stk.size(); // 輸出stack的大小例題:c123:rails
現在火車從A方向來,預定從B方向離開。火車共有N節車廂(N <=1000),並且各車廂依次以1到N來編號。你可以假設各車廂在進站之前可以單獨與其他車廂分離,也可以單獨離開車站到往B方向的鐵軌上。你也可以假設在任何時間火車站都可以容納所有的車廂。但是一旦一節車廂進站後,就不能再回到A方向的鐵軌上了,並且一旦離開車站往B方向後,也不能再回到車站。
現在你的任務是寫一個程式,判斷火車能否以一特定的排列方式在B方向的鐵軌上。

範例講解
以測資4 5 3 7 6 2 1為例
B軌道 車站 A軌道
4 5 3 2 1 6 7
4 5 3 2 1 6 7
4 5 3 6 2 1 7
4 5 3 7 6 2 1
可行!
範例測資:
5
1 2 3 4 5
5 4 3 2 1
5 4 1 2 3
0
7
4 5 3 7 6 2 1
0
0
思考思路
當我們輸出的車廂還沒到的時候,就把他們先存在車站(一個stack)
參考答案
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
while (cin >> n)
{
if (n == 0)
{
cout << endl;
break;
}
while (1)
{
stack <int> stk;
int rail[1005];
cin >> rail[0];
if (rail[0] == 0) {cout << endl; break;}
// 輸入要輸出的軌道
for (int i=1; i<n; i++)
cin >> rail[i];
int ra = 0;
//=======================
for (int a=1; a<=n; a++)
{
stk.push(a);
while (!stk.empty() && stk.top() == rail[ra])
{
stk.pop();
ra++;
}
}
if (stk.empty()) cout << "Yes" << endl;
else cout << "No" << endl;
}
}
}-
先進先出(類似排隊)
-
從最前端存取、刪除資料,從最後端新增資料
Queue(佇列)
指令:
#include <queue>
queue <int> q;
q.front(); //回傳 queue 最前端的值
q.pop(); //刪除 queue 最前端的資料
q.push(); //將一個新的值加入 queue 的最後端
q.size(); //回傳 queue 的大小
-
雙端佇列,也就是說包含了Stack和Queue的功能,可取代這兩者
Deque(雙端佇列)
Deque(雙端佇列)
#include <deque>
deque <int> dq;
dq.empty(); //測試 deque 是否為空。(回傳布林值)
dq.size(); //查詢目前 deque 中有幾個元素。
dq.push_front();//在 deque 的前端加入一個元素。
dq.push_back(); //在 deque 的後端加入一個元素。
dq.pop_front(); //移除目前 deque 中最前端元素。
dq.pop_back(); //移除目前 deque 中最後端元素。
dq.front(); //取得目前 deque 中最前端元素。
dq.back(); //取得目前 deque 中最後端元素。
dq.insert(iterator, n, val); //插入位置/次數/值-
存取、刪除 最頂端的資料 (為預設的極值)
-
維持極值
Priority_queue(優先佇列)
-
關於宣告:預設為由大至小排列,但可以再進行更改
指令
#include<queue>
priority_queue <int> pq; //由大至小
priority_queue <T, vector<T>, greater<T> > pq; //由小至大
priority_queue<T, vector<T>, cmp> pq;
pq.push(); //輸入
pq.top(); //存取最大權重值
pq.pop(); //刪除最大權重值
pq.size(); //回傳 pioraity_queue 的大小查找資料
可插入/刪除/選取資料
會自動進行排序(由小到大)/不會選到重覆的
Set(集合)
指令
set <int> s;
s.insert(); //新增
s.erase(); //刪除
s.count(); //查詢是否存在於集合中
s.empty(); //判斷是否為空的set
指令
s.lower_bound(x);
//用二分搜找出"大於或等於"x的最小值的位置
s.upper_bound(x);
//用二分搜找出"大於"x的最小值的位置
//vector用法
auto it = lower_bound(v.begin(), v.end(), val);
auto it = upper_bound(v.begin(), v.end(), val);
lower_bound 跟 upper_bound(有經過排序的vector也可以用!)
休息&討論
- 跟struct很像,但把兩個東西綁在一起
- 包含兩個數值 前面的稱為first, 後面的稱為second
- 兩個數值可以為不同種類的數據類型
- 比較時,會先比first再比較second
Pair
指令
#include <utility>
pair <T1, T2> p1 // 宣告
make_pair (v1, v2) //直接使用v1 / v2來創建這個pair
//pair的操作
p1.front = 1;
p1.second = 2;-
使用關鍵字Key去索引該關鍵字的值value
-
為一對一的功能
-
可以修改value, 不能修改Key
-
包含插入、修改、刪除、尋找
Map(映射)
指令
#include<map>
map <string, int> mp; //宣告一個 key為string, value為int 的map
//插入的方法
mp[key] = value; //也可進行更改
mp.insert(pair<string, int>(Hi, 1) );
//查詢
mp.find(); //返回資料所在位置,若無則返回與end()函數相同
mp.count();
mp.erase(); //刪除
mp.clear(); //清空
-
可改變容量的陣列(比較好用的陣列)
Vector(陣列)
指令
#include<vector>
vector <int> adj;
adj.push_back(); //新增尾部元素
adj.pop_back(); //刪除尾部元素- 全名Disjoint Sets
-
用以處理不交集的合併和查詢問題
可以查詢兩點是否相通
透過不斷尋找源頭進行
DSU(併查集)
指令
find, 查詢一個元素所在的集合
union, 合併兩個元素所在的集合
p[M] = {-1}; //先將陣列進行初始化
int find_root (int x) //找尋源頭
{
if (par[x] != x) //若x的源頭不等於x代表還有源頭,繼續找
return find_root(par[x]);
return x;
}指令
void union(int x, int y)
{
int rx = find_root(x);
int ry = find_root(y);
par[rx] = ry;
}- 砍半砍半在砍半
- 甚麼樣的性質可以這樣做?
- 單調性
- 甚麼時候停止?
二分搜
- 000000001111111111111
- 甚麼時候開始是1?
- 左閉右閉
二分搜
int l, r;
while(l < r)
{
int m = (l+r)/2;
if (f(m))
r = m;
else
l = m+1;
}
ans = l;- 000000001111111111111
- 甚麼時候開始是1?
- 左閉右閉
二分搜
int l, r;
while(l < r)
{
int m = (l+r)/2;
if (f(m))
r = m;
else
l = m+1;
}
ans = l;Serif
By yujuan
Serif
- 277