一. 順序容器:
- 按順序存儲(chǔ)數(shù)據(jù);
- 插入速度快,查找相對較慢。
-
vector 在最后插入數(shù)據(jù);
- STLvector類與數(shù)組類似,允許隨機(jī)詢問元素,即可使用下標(biāo)運(yùn)算符[]指定元素在 vector 中的位置(索引),從而直接訪問或操作元素.
- 將所有元素存儲(chǔ)在連續(xù)的存儲(chǔ)單元中
- deque 允許在開頭插入或刪除元素;
-
list 可在任何位置添加或刪除對象;
- 普通鏈表的 STL 實(shí)現(xiàn)
- 不能像 STLvector 中的元素那樣隨機(jī)訪問,因?yàn)閘ist使用不連續(xù)的內(nèi)存塊組織元素
- forward_list 是單向鏈表,只能沿一個(gè)方向遍歷。
二. 關(guān)聯(lián)容器
- 指定的順序存儲(chǔ)數(shù)據(jù)
- 就像詞典一樣。這將降低插入數(shù)據(jù)的速度,但在查詢方面有很大的優(yōu)勢。
- set:存儲(chǔ)各不相同的值,在插入時(shí)進(jìn)行排序;容器的復(fù)雜度為對數(shù);
- map: 存儲(chǔ)鍵·值對,并根據(jù)唯一的鍵排序;容器的復(fù)雜度為對數(shù);
- multiset:與 set 類似,但允許存儲(chǔ)多個(gè)值相同的項(xiàng),即值不需要是唯一的
STL 容器是泛型模板類,因此是通用的,可用于存儲(chǔ)字符串、整型、結(jié)構(gòu)或類對象。
三. STL:string
1. 為什么需要string類
字符數(shù)組可這樣定義
char staticName[20];
聲明了一個(gè)名為staticName的字符數(shù)組(也叫字符串),其長度是固定的(靜態(tài)的),包含20 個(gè)元素。
這個(gè)緩沖區(qū)可存儲(chǔ)一個(gè)長度有限的字符串,如果試圖存儲(chǔ)的字符數(shù)超出限制將溢出。不能調(diào)整靜態(tài)數(shù)組的長度.
避開這種限制, C++支持動(dòng)態(tài)分配內(nèi)存,因此可以如下定義更動(dòng)態(tài)的字符數(shù)組:
char* dynamicName = new char [ArrayLength];
其長度由變量ArrayLength的值指定。
而這種值是在運(yùn)行階段確定的,因此該數(shù)組的長度是可變的。然而,如果要在運(yùn)行階段改變數(shù)組的長度,必須首先輩輩放以前分配給它的內(nèi)存,再重新分配內(nèi)存來存儲(chǔ)數(shù)據(jù)。
2. 實(shí)例化和復(fù)制 STL string
- 類提供了很多重載的構(gòu)造函數(shù),因此可以多種方式進(jìn)行實(shí)例化和初始化
- 實(shí)例化并初始化 string 對象時(shí),無需關(guān)心字符串長度和內(nèi)存分配細(xì)節(jié)。
const char* constCStyleString = "Hello String!";
string strFromConst(constCStyleString);
string strFromConst = constCStyleString;
string str2("Hello Stringl");
- string 的構(gòu)造函數(shù)只接受輸入字符串的前 n 個(gè)字符:
string strPartialCopy(constCStyleString, 5);
- 使其包含指定數(shù)量的特定字符:
string strRepeatChars(10, 'a');
3. 訪問string內(nèi)字符內(nèi)容
- 使用類似于數(shù)組的寫法:
string strSTLString('Hello String ' );
for(size_t num = 0;num<strSTLString.length();++num){
cout<<strSTLString[num]<<endl;
}
- 使用迭代器
string::const_iterator iCharacterLocator;
for (iCharacterLocator = strSTLString.begin(); iCharacterLocator != strSTLString.end ();
++ iCharacterLocator)
cout<<*iCharacterLocator<<endl;
4.拼接字符串
- 要拼接字符扇,可使用運(yùn)算符+=,也可使用成員函數(shù) append:
string strSample1('Hello');
string strSample2("String!");
strSample1 += strSample2;
strSample1.append(strSample2);
5.在 string 中查找字符或子字符串
string 類提供了成員函數(shù) find,該函數(shù)有多個(gè)重載版本
std::string::npos 表明沒有找到要搜索的元素。如果 find 函數(shù)沒有返回,npos它將返回一個(gè)偏移量,指出子字符串或字符在 string 中的位置。
string strSample("happy birthday!")
size_t charPos = strSample.find("day", 0); //從位置0開始
if (charPos != string::npos)
cout <<"First instance of \"day\" was found at position " << charPos;
else
cout <<"Substring not found." << endl;
6. 擦除string
- 在給定偏移位置和字符數(shù)時(shí)刪除指定數(shù)目的字符;
string strSample("Hello Stringl Wake up to a beautiful dayl");
strSample.erase (13, 28); //Hello String!
- 在給定指向字符的選代器時(shí)刪除該字符:
strSample.erase(iCharS);
- 在給定由兩個(gè)迭代器指定的范圍時(shí)刪除該范圍內(nèi)的字符:
strSample.erase(strSample.begin(), strSample.end());
7. 使用 auto 簡化冗長的選代器聲明
string::iterator iCharS = find(strSample.begin(), strSample.end(), 'S');
auto iCharS = find(strSample.begin(), strSample.end(), 'S');
8. 字符串反轉(zhuǎn)
string strSample("Hello Stringl We will reverse you!");
reverse(strSample.begin(), strSample.end());
9. 字符串大小寫轉(zhuǎn)換
string strInput;
getline(cin, strInput);
transform(strInput.begin(), strInput.end(), strlnput.begin(), toupper); //大寫
transform(strlnput.begin(), strlnput.end(), strlnput.begin(), tolower); //小寫
四. STL動(dòng)態(tài)數(shù)組vector類
- 是一個(gè)模板類,提供了動(dòng)態(tài)數(shù)組的通用功能
- 在數(shù)組末尾添加元素所需的時(shí)間是固定的,即在末尾插入元素的所需時(shí)間不隨數(shù)組大小而異在末尾刪除元素也如此;
- 在數(shù)組中間添加或刪除元素所需的時(shí)間與該元素后面的元素個(gè)數(shù)成正比;
- 存儲(chǔ)的元素?cái)?shù)是動(dòng)態(tài)的,而 vector類自行負(fù)責(zé)管理內(nèi)存。
1. 實(shí)例化vector
using namespace std;
vector<int> vecDynamiclntegerArray; // vector containing integers
vector<float> vecDynamicFloatArray; // vector containing floats
vector<Tuna> vecDynamicTunaArray; //包含對象
vector也有很多構(gòu)造函數(shù),初始化方式也多變
- 實(shí)例化一個(gè)存儲(chǔ)整型數(shù)據(jù)的 vector,使用了默認(rèn)構(gòu)造函數(shù)
vector<int> vecone;
- vector 至少應(yīng)包含10個(gè)元素。注意,這并沒有限制容器最終的大小,而只是設(shè)置了初始大小。
vector<int> vectwo(10);
- 10個(gè)90值
vector<int> vecthree(10, 90);
- 使用一個(gè) vector 實(shí)例化另一個(gè)vector 的內(nèi)容,即復(fù)制vector對象或其一部分
vector<int> vecfour(vecthree);
- 使用選代器
vector<int> vecfive(vecthree.cbegin (), vecthree.cbegin () + 5 );
2. push_back()在末尾插入元素
vector <int> veclntegers;
veclntegers.push_back(50);
veclntegers.push_back(1);
vecIntegers.push_back(987);
veclntegers.push_back(1001);
cout << veclntegers.size()<<endl; //4 //請注意函數(shù)size()的用法,它返回vector 中存儲(chǔ)的元素?cái)?shù)。
- c++11支持像數(shù)組那樣初始化列表
vector<int> veclntegers = {50, 1, 987, 1001};
vector<int> vecMorelntegers {50, 1, 987, 1001};
3. 使用 insert()在指定位置插入元素
- 在開頭插入一個(gè)元素25
vecone.insert (vecone.begin(), 25);
- 指定插入位置、要插入的元素?cái)?shù)以及這些元素的值(都相同):
veclntegers.insert (veclntegers.end(), 2 , 45);
- 還可將另一個(gè) vector 的內(nèi)容插入到指定位置:
vector<int> vecAnother(2, 30);
- 在vecone位置1處插入vecanother從begin到end的值
vecone.insert(vecone.begin() + 1,vecAnother.begin(), vecAnother.end());
插入位置的迭代器一般最好為:
- begin()或 end()返回的
- STL 算法(如find函數(shù))的返回位,find可用于查找元素,然后在這個(gè)位置插入另一個(gè)元素(這將導(dǎo)致查找的元素向后移).
注意:
- 雖然函數(shù)insert功能眾多,但給 vector添加元素時(shí),應(yīng)首選 push_back()。
- 因?yàn)閕nsert是低效的,它會(huì)導(dǎo)致所有元素后移
- 頻繁在容器中間插入元素 應(yīng)使用list
4. 數(shù)組語法訪問vector元素
vector<int> vecone(5,10);
for(size_t num; num<vecone.size();++num)
cout<<vecone[num]<endl;
cout<<vecone.at(num)<<endl;
注意:
- 使用[]訪問 vector 的元素時(shí),面臨越界的危險(xiǎn)
- 更安全的方法是使用成員函數(shù) at()
- at()函數(shù)在運(yùn)行階段檢查容蕩的大小,如果索引超出邊界(無論如何都不能這樣做).將引發(fā)異常
5. 使用指針(迭代器)訪問vector元素
vector<int> vecone(5,10);
auto iLocator = vecone.begin();
while(iLocator != vecone.end()
{
size_t index = distance(vecone.begin(),iLocator);//distance函數(shù)計(jì)算元素偏移量
cout<<index<<':'<<*iLocator<<endl;
++iLocator;
}
6. pop_back刪除vector末尾的元素
vector<int> vecone(10,90);
vecone.pop_back();
7. vector的大小和容量
vector的大小指的是實(shí)際存儲(chǔ)的元素?cái)?shù),而vector的容量指的是在重新分配內(nèi)存以存儲(chǔ)更多元素
前vector能夠存儲(chǔ)的元素?cái)?shù)。因此,vector的大小小于或等于容量。
- 查詢 vector 當(dāng)前存儲(chǔ)的元素?cái)?shù)
vector.size();
- 查詢vector的容量
vector.capacity();
五. STL 動(dòng)態(tài)數(shù)組deque
- deque 是一個(gè)STL動(dòng)態(tài)數(shù)組類,與vector非常類似
- 支持使用方法push_back()和pop_back()在末尾插入和刪除元素
- 與Vector一樣, deque也使用運(yùn)算符[]以數(shù)組語法訪問其元素
deque<int> deqone;
1.使用 push_front 和 pop_front 在開頭插入和刪除元素
deque<int> deqone;
deqone.push_back(3);
deqone.push_back(4);
deqone.push_back(5);
deqone.push_front(2);
deqone.push_front(1);
deqone.push_front(0); // 0,1,2,3,4,5
deque.pop_back(); // 0,1,2,3,4
deque.pop_front(); //1,2,3,4
動(dòng)態(tài)數(shù)組vector和deque總結(jié)
- 在不知道需要存儲(chǔ)多少個(gè)元素時(shí),務(wù)必使用動(dòng)態(tài)數(shù)組vector或deque.
- 請牢記, vector只能在末端擴(kuò)容,為此可使用方法push_back().
- 請牢記,deque可在兩端擴(kuò)容,為此可使用方法push_back()和push_front().
- pop_back()刪除集合最后一個(gè)元素
- pop_front()刪除deque開頭元素
六.STL::list
- 以模板類 std::list 的方式向程序員提供了一個(gè)雙向鏈表
- 雙向鏈表的主要優(yōu)點(diǎn)是,插入和刪除元素的速度快,且時(shí)間是固定的
1. 實(shí)例化list
list<int> lione(10);
list<int> litwo(10,90);
list<int> lithree(litwo);
vector<int> vecone(10,20);
list<int> lifour(vecone.begin(),vecone.end());
- 聲明一個(gè)指向 list 中元素的選代器
list<int>::const_iterator isite;
list<int>::iterator isite
2.list開頭或末尾插入元素
- 與 deque 類似,要在 list 開頭插入元素,可使用其成員方法 push front。
- 要在末尾插入,可使用成員方法 push_back。
- 這兩個(gè)方法都接受一個(gè)參數(shù),即要插入的值:
list<int> lione(10);
lione.push_back(-1);
lione.push_front(2001);
3.在list中間插入元素,借助insert函數(shù)
list 的特點(diǎn)之一是,在其中間插入元素所需的時(shí)間是固定的
有多個(gè)重載版本
版本一:第 1 個(gè)參數(shù)是插入位置,第 2 個(gè)參數(shù)是要插入的值
iterator insert(iterator pos, const T& x);
- 版本二:第 1 個(gè)參數(shù)是插入位置,最后一個(gè)參數(shù)是要插入的值,而第2個(gè)參數(shù)是要插入的元素個(gè)數(shù)。
void insert(iterator pos, size_type n, const T& x);
- 版本三: 除一個(gè)位置參數(shù)外,它還接受兩個(gè)輸入迭代器,指定要將集合中相應(yīng)范圍內(nèi)的元素插入到 list 中
temp1ate <c1ass Inputlterator>
void insert(iterator pos, Inputlterator f, Inputlterator 1)
4. 刪除list中元素,借助erase函數(shù)
- erase函數(shù)有兩個(gè)重載版本
- 一個(gè)接受一個(gè)迭代器參數(shù)并刪除迭代器指向的元素
listlntegers.erase(isite)
- 另一個(gè)接受兩個(gè)選代器參數(shù)并刪除指定范圍內(nèi)的所有元素
listlntegers.erase(listlntegers.begin() , listlntegers.end());
5. 對list元素進(jìn)行反轉(zhuǎn)
- list 的一個(gè)獨(dú)特之處是,指向元素的選代器在 list 的元素重新排列或插入元素后仍有效
- 使用reverse()反轉(zhuǎn)元素順序
- reverseO只是反轉(zhuǎn)list 中元素的排列順序。
- 它是一個(gè)沒有參數(shù)的簡單函數(shù),確保指向元素的選代器在反轉(zhuǎn)后仍有效一如果程序員保存了該迭代器。
lione.reverse();
6. 對list元素進(jìn)行排序
- list 的成員函數(shù) sort()有兩個(gè)版本,其中一個(gè)沒有參數(shù):
listlntegers.sort(); //遞增順序
- 另一個(gè)接受一個(gè)二元謂詞函數(shù)作為參數(shù),讓您能夠指定排序標(biāo)準(zhǔn):
bool SortPredicate_Descending(const int & lsh, const int& rsh)
{
return(lsh > rsh); //優(yōu)先找最大的,遞減
}
listlntegers.sort(SortPredicate_Descending);
注意:
- 該謂詞解釋:這個(gè)謂詞僅在第一個(gè)值比第二個(gè)值大時(shí)返回true也就是說,
- 使用該謂詞時(shí),僅當(dāng)?shù)谝粋€(gè)無素(lsh)的數(shù)字值比第二個(gè)元素(rsh)大時(shí),sort才認(rèn)為第一個(gè)元素比第二個(gè)元素小。
- 基于這種解釋,sort交換元素的位置,以滿足謂詞指定的標(biāo)準(zhǔn)。
7. 總結(jié)
- 如果需要頻繁地插入或刪除元素(尤其是在中間插入或刪除時(shí)),應(yīng)使用list ,而不是vetor.
- 因?yàn)樵谶@種情況下,vector需要調(diào)整其內(nèi)部緩沖區(qū)的大小,以支持?jǐn)?shù)組語法,
- 還需執(zhí)行開銷高昂的復(fù)制操作,而 list 只需建立或斷開鏈接。
七.STL集合set
- 快速地查找和搜索
- set和multiset 之間的區(qū)別在于,后者可存儲(chǔ)重復(fù)的值,而前者只能存儲(chǔ)唯一的值。
- 為實(shí)現(xiàn)快速搜索, STL set 和 multiset 的內(nèi)部結(jié)構(gòu)像二叉樹
- 這意味著將元素插入到 set 或 multiset時(shí)將對其進(jìn)行排序,以提高查找速度
- 如果您沒有指定排序標(biāo)準(zhǔn),它們將使用默認(rèn)謂詞 std::less,確保包含的元素按升序排列。
1. 實(shí)例化set對象
set<int> seone;
multiset<int> musone;
- 要聲明一個(gè)指向 set 或 mu1tiset 中元素的選代器
set<int>::const_iterator isiter;
set<int>::iterator isiter;
- 也可以指定排序謂詞
template <typename T>
struct SortDescending
{
bool operator() (const T& lhs , const T& rhs) const
{
return (lhs > rhs);
}
};
set <int, SortDescending<int> setIntegerS;
2. set插入元素
setlntegers.insert(1);
msetlntegers.insert (setlntegers.begin(), setlntegers.end());
3. set中查找元素
- set、multiset、map和multimap等關(guān)聯(lián)容器都提供了成員函數(shù) find()
set<int> setone;
setone.insert(10);
setone.insert(13);
setone.insert(9); //9,10,13
auto isiter = setone.find(9);
if (ister != setlntegers.end())
cout << "found" <<endl;
else
cout << "not found"<<endl;
4. 刪除set中的元素
- 接受鍵值
setObject.erase(key);
- 接受一個(gè)選代器作為參數(shù),刪除該迭代器指向的元素:
setObject.erase(iElement);
- 使用迭代器指定的邊界,可將指定范圍內(nèi)的所有元素都從 set 或 mu1tiset 中刪除:
setObject.erase(iLowerBound, iUpperBound);
八. STL映射類map
key(鍵)-- value(值)
1. 實(shí)例化map對象
map<key, value> mapone;
map<int, string> maptwo;
map<int, string> mapthree(maptwo);
map<int, string> mapfour(mapthree.begin(), mapthree.end())
2. map插入元素
map<int, string> mapone;
- 使用makepair函數(shù)
mapone.insert(make_pair(1, "one"));
- 使用std::pair
mapone.insert(pair<int, string>(2, "two"))
- 使用數(shù)組語法
mapone[3] = "three";
3.map查找元素
- map關(guān)聯(lián)容器都提供了成員函數(shù)find().它讓您能夠根據(jù)給定的鍵查找值。find()總是返回一個(gè)選代器:
map<int, string> mapone;
map<int, string>::const_iterator isiter = mapone.find(1); //find(key)
if(isiter != mapone.end())
{
cout<<"key: "<<isiter->first<<endl;
cout<<"value: "<<isiter->second<<endl;
}
else
cout<<"not found"<<endl;
4. map刪除元素
- 將鍵作為參數(shù),這將刪除包含指定鍵的所有鍵-值對:
mapObject.erase(key);
- 接受迭代器作為參數(shù),并刪除選代器指向的元素:
mapObject.erase(iElement);
- 使用選代器指定邊界,從而將指定范圍內(nèi)的所有元素都從 map 或 multirnap 中刪除:
mapObject.erase(iLowerBound, iUpperBound);