前言:
STL(Standard Template Library),中文名標準模板庫,是一個高效的C++程序庫,包含很多常用的基本數據結構和基本算法,爲C++程序員們提供了一個可擴展的應用框架,高度體現了軟件的可複用性。
STL有六大組件:容器(containers)、迭代器(iterators)、空間配置器(allocator)、配接器(adapters)、算法(algorithms)、仿函數(functors)。其中主要的是容器(用來管理某類對象的集合)、迭代器(用來在一個對象集合的元素上進行遍歷操作)、算法(用來處理對象集合中的元素)三部分。
STL的基本觀念就是將數據(數據由容器進行管理)和操作分離(由算法進行)。而迭代器在兩者間充當粘合劑,是任何算法都可以和任何容器交互運作。
以下我只介紹了編程中常用到的容器。參考了資料,希望對大家有幫助,如果有錯的地方,多多指點!!!
一、vector的常見用法詳解
vector翻譯爲向量,一般叫變長數組,也就是長度根據需要而自動改變的數組。
1、vector的定義:vector<typename> name
(1)如果typename爲整型、字符型、浮點型;
vector<int>name;
vector<double>name;
vector<char>name;
(2)如果typename爲結構類型;
vector<node>name;
(3)如果typename爲容器(vector、map、set...),定義的時候一定要在>>符號之間加上空格,因爲一些使用c++11之前標準的編譯器會把它視爲移位操作,導致編譯錯誤。
vector<vector<int> >name;
(4)數組a[]中的每一個元素都是一個vector
vector<typename>a[size];
2、vector容器內元素的訪問
(1)通過下標訪問,如vector<int>a,a[0]....a[a.size()-1].
(2)迭代器(iterator)訪問,可以理解爲一種類似指針的東西
vector<typename>::iterator it;
這樣就得到了迭代器it,且可以通過*it來訪問vector裏的元素。
vector<int>a;
a.push_back(8);
a.push_back(8);
a.push_back(5);
a.push_back(2);
a.push_back(0);
vector<int>::iterator it=a.begin();///a.begin()爲取首元素地址,而it指向這個地址
for(int i=0;i<a.size();i++)
printf("%d ",*(it+i));///等價於a[i]
///vector迭代器不支持it<a.end()寫法
for(vector<int>::iterator it=a.begin();it!=a.end();it++)
printf("%d ",*it);
在常用STL容器中,只有vector和string允許使用a.begin()+i的寫法。普及地,a.end()是尾元素地址地下一個元素。
3、vector常用函數實例解釋
vector<int>a;
///push_back()在vector後面添加一個元素
a.push_back(8);
a.push_back(8);
a.push_back(5);
a.push_back(2);
a.push_back(0);
a.push_back(1);
///刪除vector尾元素
a.pop_back();
int n=a.size();///獲取vector元素個數
a.clear();///清空vector中的所有元素
a.insert(a.begin()+2,1);///將1插入到a[2]位置
a.erase(a.begin()+2);///刪除a[2]這個元素
a.erase(first,last);///刪除區間[first,last)內的所有元素
4、vector的常見用途
(1)儲存數據
①vector可以作爲數組使用,而且在一些元素個數不確定的場合可以很好地節省空間。
②有些場合需要根據一些條件把部分數據輸出在同一行,數據中間用空格隔開。由於輸出數據地個數是不確定地,爲了更方便地處理最後一個滿足條件地數據後面不輸出額外地空格,可以先用vector記錄所有需要輸出地數據,最後一次性輸出。
(2)用鄰接表存儲圖
使用鄰接表可以讓一些對指針不太熟悉地讀者有一個比較方便地寫法。
二、set的常見用法詳解
set翻譯爲集合,是一個內部自動有序且不含重複元素的容器。set的頭文件爲#include<set>,set內元素自動遞增排序,且自動去除了重複元素。
1、set的定義寫法和vector基本一致,typename可以爲int、char、double、結構體、STL容器。
set<int>name;
set<double>name;
set<char>name;
set<node>name;
set<vector<int> >name;
set<int>a[size];
2、set容器內元素的訪問:只能通過迭代器iterator訪問。
set<int>a;
a.insert(8);
a.insert(8);
a.insert(5);
a.insert(2);
a.insert(0);
for(set<int>::iterator it=a.begin();it!=a.end();it++)
printf("%d",*it);
由於除了vector和string之外的STL容器都不支持*(it+i)的訪問方式,通過*it來訪問set裏的元素。
3、set常見函數實例解析
set<int>a;
a.insert(8);///把8插入set容器中,自動去重和遞增排序
a.insert(5);
a.insert(2);
set<int>::iterator it = a.find(2);///在set中查找2,返回對應值爲2的迭代器
printf("%d",*it);///2
a.erase(it);///it爲所要刪除元素的迭代器
a.erase(it,a.end());///刪除區間之間的信息
int n = a.size();///返回容器的個數
a.clear();///清空set容器的所有元素
4、set的常見用途
(1)set最重要的作用就是去重並按升序排序,因此噴到需要去重但卻不方便直接開數組的情況。
(2)set中的元素是唯一的,如果需要處理不唯一情況,則需要使用multiset。
三、string常見用法詳解
1、string的定義:string str;其也可以初始化。
2、string中的內容的訪問
(1)通過下標訪問:
string str="abcd";
for(int i=0;i<str.length;i++)
printf("%c",str[i]);
printf("%s\n",str.c_str());
(2)通過迭代器訪問
string str="abcd";
string::iterator it;///string不像其他STL容器那樣需要參數
for(string::iterator it = str.begin();it!=str.end();it++)
printf("%c",*it);
///string也可以和vector一樣直接對迭代器加減某個數字
3、string常用函數實例解析
(1)string的加法
string str1="abc";
string str2="xyz";
string str;
str=str1+str2;///賦值於str
str1+=str2;///str2拼接在str1後
(2)string的比較
string str1="a";
string str2="aa";
string str3="abc";
string str4="xyz";
if(str1<str2) ...;///如果字典序str1<str2
if(str1!=str2) ...;///如果str1!=str2
if(str4>=str3) ...;///如果字典序str4>=str3
(3)length()或size()(容器元素的個數)、clear()(清空容器)。
(4)insert()(它有很多種寫法),下面介紹常用的:
string str="abcxyz";
string str1="bao";
str.insert(3,str1);///在str[3]插入字符串str1
str.insert(it,first,last);///it插入[first,last)區間的子字符串
(5)erase(),與之前的容器的差不多。就是多了一個刪除區間元素的方法
str.erase();///刪除單個元素
str.erase(first,last);///刪除區間[first,last)內的元素
str.erase(pos,length);///刪除從起始位置pos的length個元素
(6)string::npos
string::npos用以作爲find函數失配時的返回值,是一個常數,本身的值爲-1或4294967295(unsigned_int最大值)
(7)substr(pos,len)、find()、replace()
string str="Hello World!";
str1=" ";
str.substr(3,5)///str.substr(pos,len)從pos開始、長度爲len的子串
str.find(str1);///返回str出現子串str1第一次出現的位置。如果str1不是str子串,那麼就返回string::npos
str.find(str2,pos);///從str固定位置pos開始匹配,返回值與上面一樣
str2="Hi!";
str.replace(pos,len,str2);///從str位置pos開始、長度爲len的子串替換str2
str.replace(it1,it2,str2);///用str的迭代器[it1,it2)範圍內的子串替換str2
四、map的常見用法詳解
map翻譯爲映射,也是常用的STL容器。在定義數組時,其實(如int a[10];)就是定義了從int型到int型的映射,比如a[3]=10;(從3映射到10),比如一個字典,提供了很多字符串和頁碼(字符串-->頁碼),如果用數組來定義會顯得不方便。這時就考慮map吧,選擇它沒錯,map可以將任何基本類型(包括STL容器)映射到任何基本類型(包括STL容器)。
1、map的定義
map<typename1,typename2> mp;///<>內填寫兩個類型,其中第一個是映射前的類型typename1,一個是映射後的類型typename2
注意:如果字符串到整型的映射,必須是string而不能用char數組。(map<string,int>mp或map<set<int>,string>)
2、map容器內元素的訪問
(1)下標訪問:map中的鍵是唯一的,比如map<char,int>mp,mp['c']=20。
(2)通過迭代器訪問:map的迭代器的定義和其他容器的定義都是一樣的,但是其迭代器的使用方式與其他STL容器的不同。使用it->first訪問鍵,使用it->second訪問鍵。
map<char,int> mp;
mp['m']=20;
mp['n']=30;
for(map<char,int>::iterator it = mp.begin();it!=mp.end();it++)
printf(%d %d\n,it->first,it->second);
3、map常見函數實例解析
map<char,int> mp;
mp['m']=20;
mp['n']=30;
mp.find(key);///返回鍵爲key的映射的迭代器
map<char,int>::iterator it = mp.find('m');
mp.erase(it);///刪除m
mp.erase(first,last);///刪除區間[first,last);
int len = mp.size();///獲取容器內的個數
mp.clear();///清空容器
4、map的容器常見用途
(1)需要建立字符或字符串與整數之間映射的題目,使用map可以減少代碼量
(2)判斷大整數或其他類型數據是否存在的題目,可以把map當bool數組用。
(3)字符串和字符串的映射也有可能會遇到。
map的鍵和值是唯一的,如果一個鍵需要對應多個值,就只能用multimap。
五、queue的常見用法詳解
queue翻譯爲隊列,在STL中主要則是實現了一個先進先出的容器。
1、queue的定義:queue<typename> name;
2、queue容器內元素的訪問(只能通過front()來訪問隊首元素,或是通過back()來訪問隊尾元素)
3、queue常用函數實例解析
queue<int>q;
q.push(1);
q.push(3);
q.push(2);///2入隊
printf(%d %d %d\n,q.front(),q.back(),q.size());///可以分別獲得隊首元素和隊尾元素,獲取隊列內元素個數
q.pop();///隊首元素出隊
if(!q.empty()) ...;///檢測隊列是否爲空
注意:使用front()和pop()函數前,必須用empty()判斷隊列是否爲空。
4、queue的常見用途
(1)方便實現廣度優先搜索
(2)STL的容器中還有兩種容器跟隊列有關,分別是雙端隊列deque和優先隊列priority_queue,前者是首尾皆可插入和刪除的隊列,後者是使用堆實現的默認將當前隊列最大元素置於隊首的容器。
六、priority_queue的常見用法詳解
priority_queue又稱爲優先隊列,其底層用堆來實現的,在優先隊列中,隊首元素一定是當前隊列中優先級最高的那一個。
1、priority_queue的定義:priority_queue<typename>name;
2、priority_queue容器內元素的訪問
和隊列不同,priority_queue只能通過top()函數來訪問隊首元素(也可以稱爲堆頂元素),也就是優先級別最高的元素。
3、priority_queue常用函數實例解析
priority_queue<int>q;
q.push(1);
q.push(3);
q.push(2);///2入隊
printf(%d %d\n,q.top(),q.size());///可以分別獲得隊首元素,獲取隊列內元素個數
q.pop();///隊首元素出隊
if(!q.empty()) ...;///檢測隊列是否爲空<int>q;
4、priority_queue內元素優先級的設置
(1)基本數據類型的優先級設置
基本數據類型就是int型、double型、char型等可以直接使用的數據類型,優先隊列對他們優先級設置一般是數字大的優先級越高
priority_queue<int,vector<int>,less<int> >q;///等價priority_queue<int>q
q.push(2);
q.push(3);
q.push(1);
printf("%d\n",q.top());///輸出3
vector<int>來自承載底層數據結構堆的容器,less<int>表示數字越大的優先級越大,greater<int>表示優先級別越小。
(2)結構體的優先級設置
struct fruit{
string name;
int price;
friend bool operator < (fruit f1,fruit f2){///重載,不能是大於號,否則會編譯出錯
return f1.price < f2.price;///價格高的水果優先級高(從低到高),否則>就是價格低的水果優先級低(從高到低)
}
///如果結構內的數據比較龐大,可以在參數使用引用,const fruit f1、const fruit f2
}
friend這個是友元,是減少系統開銷,提高效率的。注意:優先隊列的這個函數與sort中的cmp效果相反。
5、priority_queue的常見用途
(1)貪心問題
(2)Dijkstra算法進行優化
七、stack的常見用法詳解
stack翻譯爲棧,是STL中實現的先進先出的容器。
1、stack常見函數實例
stack<int>st;
st.push(1);
st.push(3);
st.push(2);///入棧
int x=st.top();///取棧頂元素
st.pop();///刪除棧頂元素
int n = st.size();
if(!st.empty()) ....;///判斷棧是否爲空
2、stack的常見用途
用來模擬實現一些遞歸,防止程序對棧內存的限制,而導致程序運行出錯
八、pair的常見用法詳解
pair是一個非常實用容器,當想要將兩個元素綁在一起作爲一個合成元素、又不想因此定義結構體,使用pair可以很方便地作爲一個代替品,pair實際上可以看作一個內部有兩個元素地結構體,且兩個元素地類型是可以指定的。(頭文件utility,map頭文件會自動添加utility頭文件)
struct pair{
typename1 first;
typename2 second;
}
1、pair的定義
pair有兩個參數,分別對應first和second的數據類型,它們可以是任意基本數據類型或容器。
2、pair中元素的訪問
pair中只有兩個元素,分別是first和second,只需要按正常結構體的方式去訪問即可。
///pair<typename1,typename2>name;
pair<string,int>p;
p.first="Hello";
p.second=3;///初始化
pair<string,int>p("Hello",3);///初始化
///臨時構建一個pair
p=pair<string,int>("Hello",3);
p=make_pair("Hello",3);///使用自帶函數
3、pair常用函數實例解析
比較操作數:比較規則(==,!=,<,<=,>,>=)先以first的大小爲標準,只有當first相等纔去判斷second的大小。
pair<int,int>x(1,2);
pair<int,int>y(1,1);
pair<int,int>z(2,3);
if(x>y) ....;///first相等,比較second
if(y<z) ....;///比較first
4、pair的常見用途
(1)是來代替二元結構體及其函數,可以節省編碼時間。
(2)作爲map鍵值對來進行插入。
map<string,int>mp;
mp.insert(make_pair("Hello",3));
mp.insert(pair<string,int>("Hi",5));
for(map<string,int>::iterator it=mp.begin();it!=mp.end();it++)
cout<<it->first<<" "<<it->second<<endl;
九、參考資料
1、https://blog.csdn.net/TeFuirnever/article/details/104438908?utm_source=app(【C++100問】深度總結STL基本容器的使用)
2、《算法筆記》