學了這么長時間的STL庫,現在我覺得是有必要對過去的題目和所遇到的問題做一下整理了,以便於之后更好的展開練習:
一、 為什么要用STL庫?
1、簡單粗暴(省事)。
2、便於解決復雜的問題(在貪心題目中顯而易見)。
3、使其思路更加廣泛,解決問題的角度更多。
二、 怎么用STL庫?
1、設身處地的利用某個函數的特點進行解決問題。(下面會進行介紹各個函數的特點)
2、做好第一點就足夠了。
三、 各個函數的特點以及適合解決哪些問題?
1、 vector:
vector的強大之處就在於可以通過它完成建立鄰接表,達到存圖、存樹的效果,之后利用DFS或者BFS的方式進行解決問題。
最短路(包括其優化)中也會用到Vector.
位置的不同也可以通過其進行存儲:例如那道字符串的題目。
(一個鍵對應好幾個不同的值時,選擇這個會很合適)。
2、 set:
set集合的強大之處莫過於它的去重、排序。
尤其是去重,實在是十分之重要,當然,排序也很重要。
3、 map:
鍵值對:既一個鍵對應一個值(若要引用鍵或者值則需要迭代器)
迭代器:map<int,int>::iterator it;(遍歷時也需要)
鍵:it->first,值:it->second;
Map會根據鍵的大小進行自動排序,當有相同元素出現時,用數組的方式的話並不會替代之前已經存在的鍵值,用insert的方式進行插入的時候會替代已經存在的鍵值。
4、 queue:
利用隊列實現BFS是隊列的一個強大功能。
單調隊列也可以解決某些問題。
5、 stack
單調棧的應用極其廣泛。
單調棧適合解決不可排序的一組數,用來簡化時間復雜度。
利用某段數的單調性實現其效果。
6、 priority_queue:
優先級隊列內部是通過堆進行實現的。
下面會進行詳細介紹。
四:各個函數的相關實現及其屬性和方法。
Vector:
1.push_back 在數組的最后添加一個數據
2.pop_back 去掉數組的最后一個數據
3.at 得到編號位置的數據
4.begin 得到數組頭的指針
5.end 得到數組的最后一個單元+1的指針
6.front 得到數組頭的引用
7.back 得到數組的最后一個單元的引用
8.max_size 得到vector最大可以是多大
9.capacity 當前vector分配的大小
10.size 當前使用數據的大小
11.resize 改變當前使用數據的大小,如果它比當前使用的大,者填充默認值
12.reserve 改變當前vecotr所分配空間的大小
13.erase 刪除指針指向的數據項
14.clear 清空當前的vector
15.rbegin 將vector反轉后的開始指針返回(其實就是原來的end-1)
16.rend 將vector反轉構的結束指針返回(其實就是原來的begin-1)
17.empty 判斷vector是否為空
18.swap 與另一個vector交換數據
3.2 詳細的函數實現功能:其中vector<int> c.
c.clear() 移除容器中所有數據。
c.empty() 判斷容器是否為空。
c.erase(pos) 刪除pos位置的數據
c.erase(beg,end) 刪除[beg,end)區間的數據
c.front() 傳回第一個數據。
c.insert(pos,elem) 在pos位置插入一個elem拷貝
c.pop_back() 刪除最后一個數據。
c.push_back(elem) 在尾部加入一個數據。
c.resize(num) 重新設置該容器的大小
c.size() 回容器中實際數據的個數。
c.begin() 返回指向容器第一個元素的迭代器
c.end() 返回指向容器最后一個元素的迭代器
set:
begin() 返回set容器的第一個迭代器
end() 返回set容器的最后一個迭代器
clear() 刪除set容器中的所有的元素
empty() 判斷set容器是否為空
max_size() 返回set容器可能包含的元素最大個數
size() 返回當前set容器中的元素個數
rbegin 返回的值和end()相同
rend() 返回的值和rbegin()相同
判斷某個元素是否出現在set集合中的兩種方法:
1、COUNT() 用來查找SET中某個某個鍵值出現的次數。這個函數在SET並不是很實用,因為一個鍵值在SET只可能出現0或1次,這樣就變成了判斷某一鍵值是否在SET出現過了。
示例代碼:
#include <iostream>
#include <set>
using namespace std;
int main() {
set<int> s;
s.insert(1);
s.insert(2);
s.insert(3);
s.insert(1);
cout<<"set 中 1 出現的次數是 :"<<s.count(1)<<endl;
cout<<"set 中 4 出現的次數是 :"<<s.count(4)<<endl;
return 0;
}
2、 FIND() ,返回給定值值得定位器,如果沒找到則返回END()。
#include <iostream>
#include <set>
using namespace std;
int main() {
int a[] = {1,2,3};
set<int> s(a,a+3);
set<int>::iterator iter;
if((iter = s.find(2)) != s.end()) {
cout<<*iter<<endl;
}
return 0;
}
#Set中的刪除操作:#
1、erase(iterator) ,刪除定位器iterator指向的值
2、erase(first,second),刪除定位器first和second之間的值
3、erase(key_value),刪除鍵值key_value的值
#include <iostream>
#include <set>
using namespace std;
int main() {
set<int> s;
set<int>::const_iterator iter;
set<int>::iterator first;
set<int>::iterator second;
for(int i = 1 ; i <= 10 ; ++i) {
s.insert(i);
} //第一種刪除
s.erase(s.begin()); //第二種刪除
first = s.begin();
second = s.begin();
second++;
second++;
s.erase(first,second); //第三種刪除
s.erase(8);
cout<<"刪除后 set 中元素是 :";
for(iter = s.begin() ; iter != s.end() ; ++iter) {
cout<<*iter<<" ";
}
cout<<endl;
return 0;
}
二分查找:
lower_bound(key_value) ,返回第一個大於等於key_value的定位器
upper_bound(key_value),返回最后一個大於等於key_value的定位器
#include <iostream>
#include <set>
using namespace std;
int main() {
set<int> s;
s.insert(1);
s.insert(3);
s.insert(4);
cout<<*s.lower_bound(2)<<endl;
cout<<*s.lower_bound(3)<<endl;
cout<<*s.upper_bound(3)<<endl;
return 0;
}
Map:
begin() 返回指向map頭部的迭代器
clear() 刪除所有元素
count() 返回指定元素出現的次數
empty() 如果map為空則返回true
end() 返回指向map末尾的迭代
equal_range() 返回特殊條目的迭代器
erase() 刪除一個元素
find() 查找一個元素
get_allocator() 返回map的配置器
insert() 插入元素
key_comp() 返回比較元素key的函數
lower_bound() 返回鍵值>=給定元素的第一個位置
max_size() 返回可以容納的最大元素個數
rbegin() 返回一個指向map尾部的逆向迭代器
rend() 返回一個指向map頭部的逆向迭代器
size() 返回map中元素的個數
swap() 交換兩個map
upper_bound() 返回鍵值>給定元素的第一個位置
value_comp() 返回比較元素value的函數
Queue:
back()返回最后一個元素
empty()如果隊列空則返回真
front()返回第一個元素
pop()刪除第一個元素
push()在末尾加入一個元素
size()返回隊列中元素的個數
訪問:
q.front(),即最早被壓入隊列的元素。
q.back(),即最后被壓入隊列的元素。
Privority_queue:
入隊 q.push();
出隊 q.pop();
求隊列中元素個數 q.size();
判斷隊列是否為空 q.empty();若為空返回true,否則返回false
獲得首元素 q.top();
返回q的第一個元素 q.top();
返回q的末尾元素 q.back();
優先級里最重要的東西:排序:
默認的優先隊列 priority_queue <int> q;排序是由大到小的:
#include<stdio.h>
#include<queue>
using namespace std;
int main()
{
priority_queue<int> q;
int num[5]={19,2,4,3,6};
for(int i=0;i<5;i++)
q.push(num[i]);
for(int i=0;i<5;i++)
{
int temp=q.top();
printf("%d ",temp);
q.pop();
}
return 0;
}
默認的優先隊列(結構體,重載小於)
#include<stdio.h>
#include<queue>
using namespace std;
struct node
{
int x,y;
bool operator < (const node & a) const {
return x<a.x;
}
}s;
struct node
{
int x;
int y;
int time;
friend bool operator < (node n1, node n2) // 也可以用友元函數friend
{
return n1.time>n2.time;
}
};
priority_queue <node> q;
int main()
{
printf("讀入:\n");
for(int i=0;i<5;i++)
{
scanf("%d%d",&s.x,&s.y);
q.push(s);
}
printf("輸出:\n");
while(!q.empty())
{
node temp=q.top();
printf("(%d,%d) ",temp.x,temp.y);
q.pop();
}
return 0;
}
less是從大到小,greater是從小到大:
//升序隊列
priority_queue <int,vector<int>,greater<int> > q;
//降序隊列
priority_queue <int,vector<int>,less<int> >q;
//greater和less是std實現的兩個仿函數(就是使一個類的使用看上去像一個函數。其實現就是類中實現一個operator(),這個類就有了類似函數的行為,就是一個仿函數類了)
優先級與結構體:
#include <iostream>
#include <queue>
using namespace std;
struct Node{
int x, y;
Node(int a=0, int b=0):
x(a),y(b){}
};
bool operator<(Node a, Node b){//返回true時,說明a的優先級低於b
//x值較大的Node優先級低(x小的Node排在隊前)
//x相等時,y大的優先級低(y小的Node排在隊前)
if( a.x== b.x ) return a.y< b.y; //優先級隊列中的結構體與之前的覆寫函數有些許的不同,< 代表從大的先出隊
return a.x< b.x;
}
int main(){
priority_queue<Node> q;
for( int i= 0; i< 5; ++i ){
int a,b;
scanf("%d%d",&a,&b);
q.push({a,b});
}
while( !q.empty() ){
cout << q.top().x << ' ' << q.top().y << endl;
q.pop();
}
return 0;
}
Stack:
入棧,如例:s.push(x);
出棧,如例:s.pop();注意,出棧操作只是刪除棧頂元素,並不返回該元素。
訪問棧頂,如例:s.top()
判斷棧空,如例:s.empty() ,當棧空時,返回true。
訪問棧中的元素個數,如例:s.size() 。