C++ STL容器基本使用

一. 順序容器:

  • 按順序存儲數(shù)據(jù)学搜;
  • 插入速度快瑞佩,查找相對較慢炬丸。
  • vector 在最后插入數(shù)據(jù);
    1. STLvector類與數(shù)組類似蜒蕾,允許隨機詢問元素咪啡,即可使用下標(biāo)運算符[]指定元素在 vector 中的位置(索引)撤摸,從而直接訪問或操作元素.
    2. 將所有元素存儲在連續(xù)的存儲單元中
  • deque 允許在開頭插入或刪除元素;
  • list 可在任何位置添加或刪除對象;
    1. 普通鏈表的 STL 實現(xiàn)
    2. 不能像 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());

插入位置的迭代器一般最好為:

  1. begin()或 end()返回的
  2. 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é)

  1. 在不知道需要存儲多少個元素時,務(wù)必使用動態(tài)數(shù)組vector或deque.
  2. 請牢記响迂, vector只能在末端擴容考抄,為此可使用方法push_back().
  3. 請牢記,deque可在兩端擴容蔗彤,為此可使用方法push_back()和push_front().
  4. pop_back()刪除集合最后一個元素
  5. 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);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市赂弓,隨后出現(xiàn)的幾起案子绑榴,更是在濱河造成了極大的恐慌,老刑警劉巖盈魁,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件翔怎,死亡現(xiàn)場離奇詭異,居然都是意外死亡杨耙,警方通過查閱死者的電腦和手機赤套,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來珊膜,“玉大人容握,你說我怎么就攤上這事「ò幔” “怎么了唯沮?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長堪遂。 經(jīng)常有香客問我介蛉,道長,這世上最難降的妖魔是什么溶褪? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任币旧,我火速辦了婚禮,結(jié)果婚禮上猿妈,老公的妹妹穿的比我還像新娘吹菱。我一直安慰自己巍虫,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布鳍刷。 她就那樣靜靜地躺著占遥,像睡著了一般。 火紅的嫁衣襯著肌膚如雪输瓜。 梳的紋絲不亂的頭發(fā)上瓦胎,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機與錄音尤揣,去河邊找鬼搔啊。 笑死,一個胖子當(dāng)著我的面吹牛北戏,可吹牛的內(nèi)容都是我干的负芋。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼嗜愈,長吁一口氣:“原來是場噩夢啊……” “哼旧蛾!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起芝硬,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蚜点,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后拌阴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡奶镶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年迟赃,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片厂镇。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡纤壁,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出捺信,到底是詐尸還是另有隱情酌媒,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布迄靠,位于F島的核電站秒咨,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏掌挚。R本人自食惡果不足惜雨席,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望吠式。 院中可真熱鬧陡厘,春花似錦抽米、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至谤饭,卻和暖如春标捺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背网持。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工宜岛, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人功舀。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓萍倡,卻偏偏與公主長得像,于是被迫代替她去往敵國和親辟汰。 傳聞我的和親對象是個殘疾皇子列敲,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容