C++ STL容器基本使用

一. 順序容器:

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

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

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

  1. 在不知道需要存儲(chǔ)多少個(gè)元素時(shí),務(wù)必使用動(dòng)態(tài)數(shù)組vector或deque.
  2. 請牢記, vector只能在末端擴(kuò)容,為此可使用方法push_back().
  3. 請牢記,deque可在兩端擴(kuò)容,為此可使用方法push_back()和push_front().
  4. pop_back()刪除集合最后一個(gè)元素
  5. 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);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容