一. 順序容器:
- 按順序存儲數(shù)據(jù)学搜;
- 插入速度快瑞佩,查找相對較慢炬丸。
-
vector 在最后插入數(shù)據(jù);
- STLvector類與數(shù)組類似蜒蕾,允許隨機詢問元素咪啡,即可使用下標(biāo)運算符[]指定元素在 vector 中的位置(索引)撤摸,從而直接訪問或操作元素.
- 將所有元素存儲在連續(xù)的存儲單元中
- deque 允許在開頭插入或刪除元素;
-
list 可在任何位置添加或刪除對象;
- 普通鏈表的 STL 實現(xiàn)
- 不能像 STLvector 中的元素那樣隨機訪問,因為list使用不連續(xù)的內(nèi)存塊組織元素
- forward_list 是單向鏈表莺掠,只能沿一個方向遍歷汁蝶。
二. 關(guān)聯(lián)容器
- 指定的順序存儲數(shù)據(jù)
- 就像詞典一樣。這將降低插入數(shù)據(jù)的速度膀估,但在查詢方面有很大的優(yōu)勢耻讽。
- set:存儲各不相同的值察纯,在插入時進行排序;容器的復(fù)雜度為對數(shù);
- map: 存儲鍵·值對,并根據(jù)唯一的鍵排序;容器的復(fù)雜度為對數(shù);
- multiset:與 set 類似针肥,但允許存儲多個值相同的項饼记,即值不需要是唯一的
STL 容器是泛型模板類,因此是通用的慰枕,可用于存儲字符串具则、整型、結(jié)構(gòu)或類對象博肋。
三. STL:string
1. 為什么需要string類
字符數(shù)組可這樣定義
char staticName[20];
聲明了一個名為staticName的字符數(shù)組(也叫字符串),其長度是固定的(靜態(tài)的)蜂厅,包含20 個元素匪凡。
這個緩沖區(qū)可存儲一個長度有限的字符串,如果試圖存儲的字符數(shù)超出限制將溢出掘猿。不能調(diào)整靜態(tài)數(shù)組的長度.
避開這種限制病游, C++支持動態(tài)分配內(nèi)存,因此可以如下定義更動態(tài)的字符數(shù)組:
char* dynamicName = new char [ArrayLength];
其長度由變量ArrayLength的值指定稠通。
而這種值是在運行階段確定的衬衬,因此該數(shù)組的長度是可變的。然而采记,如果要在運行階段改變數(shù)組的長度佣耐,必須首先輩輩放以前分配給它的內(nèi)存,再重新分配內(nèi)存來存儲數(shù)據(jù)唧龄。
2. 實例化和復(fù)制 STL string
- 類提供了很多重載的構(gòu)造函數(shù)兼砖,因此可以多種方式進行實例化和初始化
- 實例化并初始化 string 對象時奸远,無需關(guān)心字符串長度和內(nèi)存分配細節(jié)。
const char* constCStyleString = "Hello String!";
string strFromConst(constCStyleString);
string strFromConst = constCStyleString;
string str2("Hello Stringl");
- string 的構(gòu)造函數(shù)只接受輸入字符串的前 n 個字符:
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.拼接字符串
- 要拼接字符扇讽挟,可使用運算符+=懒叛,也可使用成員函數(shù) append:
string strSample1('Hello');
string strSample2("String!");
strSample1 += strSample2;
strSample1.append(strSample2);
5.在 string 中查找字符或子字符串
string 類提供了成員函數(shù) find,該函數(shù)有多個重載版本
std::string::npos 表明沒有找到要搜索的元素耽梅。如果 find 函數(shù)沒有返回,npos它將返回一個偏移量薛窥,指出子字符串或字符在 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ù)目的字符;
string strSample("Hello Stringl Wake up to a beautiful dayl");
strSample.erase (13, 28); //Hello String!
- 在給定指向字符的選代器時刪除該字符:
strSample.erase(iCharS);
- 在給定由兩個迭代器指定的范圍時刪除該范圍內(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動態(tài)數(shù)組vector類
- 是一個模板類诅迷,提供了動態(tài)數(shù)組的通用功能
- 在數(shù)組末尾添加元素所需的時間是固定的,即在末尾插入元素的所需時間不隨數(shù)組大小而異在末尾刪除元素也如此;
- 在數(shù)組中間添加或刪除元素所需的時間與該元素后面的元素個數(shù)成正比;
- 存儲的元素數(shù)是動態(tài)的众旗,而 vector類自行負責(zé)管理內(nèi)存罢杉。
1. 實例化vector
using namespace std;
vector<int> vecDynamiclntegerArray; // vector containing integers
vector<float> vecDynamicFloatArray; // vector containing floats
vector<Tuna> vecDynamicTunaArray; //包含對象
vector也有很多構(gòu)造函數(shù),初始化方式也多變
- 實例化一個存儲整型數(shù)據(jù)的 vector,使用了默認構(gòu)造函數(shù)
vector<int> vecone;
- vector 至少應(yīng)包含10個元素贡歧。注意滩租,這并沒有限制容器最終的大小,而只是設(shè)置了初始大小利朵。
vector<int> vectwo(10);
- 10個90值
vector<int> vecthree(10, 90);
- 使用一個 vector 實例化另一個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 中存儲的元素數(shù)绍弟。
- c++11支持像數(shù)組那樣初始化列表
vector<int> veclntegers = {50, 1, 987, 1001};
vector<int> vecMorelntegers {50, 1, 987, 1001};
3. 使用 insert()在指定位置插入元素
- 在開頭插入一個元素25
vecone.insert (vecone.begin(), 25);
- 指定插入位置技即、要插入的元素數(shù)以及這些元素的值(都相同):
veclntegers.insert (veclntegers.end(), 2 , 45);
- 還可將另一個 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可用于查找元素,然后在這個位置插入另一個元素(這將導(dǎo)致查找的元素向后移).
注意:
- 雖然函數(shù)insert功能眾多晌柬,但給 vector添加元素時姥份,應(yīng)首選 push_back()。
- 因為insert是低效的年碘,它會導(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ù) at()
- at()函數(shù)在運行階段檢查容蕩的大小澈歉,如果索引超出邊界(無論如何都不能這樣做).將引發(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ù)計算元素偏移量
cout<<index<<':'<<*iLocator<<endl;
++iLocator;
}
6. pop_back刪除vector末尾的元素
vector<int> vecone(10,90);
vecone.pop_back();
7. vector的大小和容量
vector的大小指的是實際存儲的元素數(shù),而vector的容量指的是在重新分配內(nèi)存以存儲更多元素
前vector能夠存儲的元素數(shù)屿衅。因此埃难,vector的大小小于或等于容量。
- 查詢 vector 當(dāng)前存儲的元素數(shù)
vector.size();
- 查詢vector的容量
vector.capacity();
五. STL 動態(tài)數(shù)組deque
- deque 是一個STL動態(tài)數(shù)組類涤久,與vector非常類似
- 支持使用方法push_back()和pop_back()在末尾插入和刪除元素
- 與Vector一樣涡尘, deque也使用運算符[]以數(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
動態(tài)數(shù)組vector和deque總結(jié)
- 在不知道需要存儲多少個元素時,務(wù)必使用動態(tài)數(shù)組vector或deque.
- 請牢記响迂, vector只能在末端擴容考抄,為此可使用方法push_back().
- 請牢記,deque可在兩端擴容蔗彤,為此可使用方法push_back()和push_front().
- pop_back()刪除集合最后一個元素
- pop_front()刪除deque開頭元素
六.STL::list
- 以模板類 std::list 的方式向程序員提供了一個雙向鏈表
- 雙向鏈表的主要優(yōu)點是川梅,插入和刪除元素的速度快疯兼,且時間是固定的
1. 實例化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());
- 聲明一個指向 list 中元素的選代器
list<int>::const_iterator isite;
list<int>::iterator isite
2.list開頭或末尾插入元素
- 與 deque 類似,要在 list 開頭插入元素贫途,可使用其成員方法 push front吧彪。
- 要在末尾插入,可使用成員方法 push_back丢早。
- 這兩個方法都接受一個參數(shù)姨裸,即要插入的值:
list<int> lione(10);
lione.push_back(-1);
lione.push_front(2001);
3.在list中間插入元素,借助insert函數(shù)
list 的特點之一是怨酝,在其中間插入元素所需的時間是固定的
有多個重載版本
版本一:第 1 個參數(shù)是插入位置傀缩,第 2 個參數(shù)是要插入的值
iterator insert(iterator pos, const T& x);
- 版本二:第 1 個參數(shù)是插入位置凫碌,最后一個參數(shù)是要插入的值扑毡,而第2個參數(shù)是要插入的元素個數(shù)。
void insert(iterator pos, size_type n, const T& x)盛险;
- 版本三: 除一個位置參數(shù)外,它還接受兩個輸入迭代器勋又,指定要將集合中相應(yīng)范圍內(nèi)的元素插入到 list 中
temp1ate <c1ass Inputlterator>
void insert(iterator pos, Inputlterator f, Inputlterator 1)
4. 刪除list中元素苦掘,借助erase函數(shù)
- erase函數(shù)有兩個重載版本
- 一個接受一個迭代器參數(shù)并刪除迭代器指向的元素
listlntegers.erase(isite)
- 另一個接受兩個選代器參數(shù)并刪除指定范圍內(nèi)的所有元素
listlntegers.erase(listlntegers.begin() , listlntegers.end());
5. 對list元素進行反轉(zhuǎn)
- list 的一個獨特之處是,指向元素的選代器在 list 的元素重新排列或插入元素后仍有效
- 使用reverse()反轉(zhuǎn)元素順序
- reverseO只是反轉(zhuǎn)list 中元素的排列順序楔壤。
- 它是一個沒有參數(shù)的簡單函數(shù)鹤啡,確保指向元素的選代器在反轉(zhuǎn)后仍有效一如果程序員保存了該迭代器。
lione.reverse();
6. 對list元素進行排序
- list 的成員函數(shù) sort()有兩個版本蹲嚣,其中一個沒有參數(shù):
listlntegers.sort(); //遞增順序
- 另一個接受一個二元謂詞函數(shù)作為參數(shù)递瑰,讓您能夠指定排序標(biāo)準(zhǔn):
bool SortPredicate_Descending(const int & lsh, const int& rsh)
{
return(lsh > rsh); //優(yōu)先找最大的,遞減
}
listlntegers.sort(SortPredicate_Descending);
注意:
- 該謂詞解釋:這個謂詞僅在第一個值比第二個值大時返回true也就是說隙畜,
- 使用該謂詞時抖部,僅當(dāng)?shù)谝粋€無素(lsh)的數(shù)字值比第二個元素(rsh)大時,sort才認為第一個元素比第二個元素小议惰。
- 基于這種解釋慎颗,sort交換元素的位置,以滿足謂詞指定的標(biāo)準(zhǔn)言询。
7. 總結(jié)
- 如果需要頻繁地插入或刪除元素(尤其是在中間插入或刪除時)俯萎,應(yīng)使用list ,而不是vetor.
- 因為在這種情況下运杭,vector需要調(diào)整其內(nèi)部緩沖區(qū)的大小夫啊,以支持數(shù)組語法,
- 還需執(zhí)行開銷高昂的復(fù)制操作辆憔,而 list 只需建立或斷開鏈接撇眯。
七.STL集合set
- 快速地查找和搜索
- set和multiset 之間的區(qū)別在于谆趾,后者可存儲重復(fù)的值,而前者只能存儲唯一的值叛本。
- 為實現(xiàn)快速搜索沪蓬, STL set 和 multiset 的內(nèi)部結(jié)構(gòu)像二叉樹
- 這意味著將元素插入到 set 或 multiset時將對其進行排序,以提高查找速度
- 如果您沒有指定排序標(biāo)準(zhǔn)来候,它們將使用默認謂詞 std::less跷叉,確保包含的元素按升序排列。
1. 實例化set對象
set<int> seone;
multiset<int> musone;
- 要聲明一個指向 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);
- 接受一個選代器作為參數(shù),刪除該迭代器指向的元素:
setObject.erase(iElement);
- 使用迭代器指定的邊界转质,可將指定范圍內(nèi)的所有元素都從 set 或 mu1tiset 中刪除:
setObject.erase(iLowerBound, iUpperBound);
八. STL映射類map
key(鍵)-- value(值)
1. 實例化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()總是返回一個選代器:
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);