C++STL总结笔记(一)—— 容器和容器适配器
文章目錄
- 前言
- 一、概念
- 1.1 順序容器
- 1.2 容器適配器
- 1.3 關聯容器
- 二、程序示例
- 1. vector和Set自定義數據類型的訪問
- 2.vector容器嵌套
- 3.list容器排序
- 4.pair對組的使用
- 總結
前言
STL是C++中的基于數據結構和算法的標準模板庫,可以大量節約系統開發時間,增加程序復用性。
STL的六大件包括容器、算法、迭代器、仿函數、適配器和空間配置器,其中幾乎所有代碼均使用了模板類和模板函數的概念。
一、概念
容器從字面意思理解就是放東西的器件,C++中的容器是指將對象放入存儲對象的模板類型里。
容器有以下幾種:
1.1 順序容器
順序容器也叫序列式容器,是各元素之間存在順序關系的線性表,其中元素的位置固定,但可用刪除或插入的操作進行改變,這種操作稱為質變算法。
順序容器由vector(向量)、list(列表)、deque(隊列)組成。
vector是最常見的容器類型,訪問其中的數據有很多方法,這里使用迭代器完成,一般使用iterator迭代器,它是指針的泛化,聲明的對象可以用*+對象完成查看。與普通數組的不同之處在于vector是可以動態擴展的數據結構,沒有長度的限制,其原理是重新開辟新空間來拷貝原來的數組內容,然后刪除原有空間。
其缺陷在于對頭部進行插入或刪除時效率較低。
deque(double-ended queue:雙端隊列)是一種對兩端元素進行添加和刪除操作的容器,又稱雙端數組,應用方式基本和vector一樣。
其特點:
1: 采用多個連續的內存存儲數據,并且在一個映射結構中保存對這些內存和順序的跟蹤,索引數組是存儲每段數組的首地址。
2:和vevtor不同,deque向兩端插入或刪除元素時效率較高,但中間效率較低。
3:deque在訪問元素時比vector慢。
4:deque的迭代器也支持隨機訪問數組元素。
工作原理:
deque是由一個中控器來維護緩沖區的地址,其中緩沖區存放數據。
list叫雙向鏈表,其數據元素是通過鏈表指針串連成的線性表,由節點表示元素位置,節點由三部分組成,前驅元素指針域、數據域和后繼元素指針域。前驅元素指針域保存了前驅元素的首地址;數據域則是本節點的數據;后繼元素指針域則保存了后繼元素的首地址。迭代器也是雙向迭代器。
缺點:
1:由于list元素節點并不要求在一段連續的內存中,故不支持快速隨機存取,只能通過“++”或“–”操作將迭代器移動到后繼/前驅節點元素處。
2:遍歷速度慢,是用指針進行讀取的。
3:占用內存大。
優點:
1:可以快速的插入和刪除數據。原因是list是通過指針指向來串聯的,插入元素的時候只需要讓前后的指針指向新的元素節點即可,不需移動元素位置。
2:采用動態分配內存,不會浪費。
1.2 容器適配器
容器適配器包括stack,queue,priority_queue三種,可以讓基本的容器類型采用另一種更適配于當前工作要求的工作方式實現。三種適配器都需滿足一定的約束條件,也可以可理解為加了限制條件的容器。
stack稱為棧容器,是以deque為底層容器,封閉一些功能而形成一種具有“先進后出”特性,并不允許遍歷行為的容器適配器,所以stack沒有迭代器。
#include<stack>stack<int>s;//從棧頂入棧s.push(1);s.push(2);//判斷棧頂是否為空,出棧while (!s.empty()){cout << s.top() << endl;s.pop();}cout << s.size()<<endl;queue又稱隊列,必須符合先進先出原則,也不允許遍歷成員,所以也沒有迭代器。
#include<iostream> #include<string> #include<queue> #include<algorithm> using namespace std;void test() {queue<int>s;//從隊頂入隊s.push(1);s.push(2);//判斷隊頭是否為空,出隊while (!s.empty()){cout << s.front()<< endl;cout << s.back()<<endl;s.pop();}cout << s.size() << endl; }int main() {test();system("pause"); }priority_queue稱為優先隊列,自定義數據的優先級, 讓優先級高的排在隊列前面, 可以優先出隊。
#include <queue>priority_queue<int> a;for (int i = 0; i < 10; i++){a.push(i);}while (!a.empty()){cout << a.top() << ' ';a.pop();}cout << endl;1.3 關聯容器
關聯容器是一種二叉樹的結構,沒有嚴格的順序關系,元素位置會按照二叉樹的排序方式進行,在排序的時候按照升序排列。
主要包含有三種,set(集合),multiset(多重集合),map,multimap。
set和multiset均可以進行快速查找數據,但區別在于set容器不允許有重復值,multiset可以有。
set在內存中是通過鏈表進行排序的,所以插入時比vector和deque要快,但是比list慢;在訪問元素上比vector 慢,比list快,原因是list 是逐個搜索,它搜索的時間是跟容器的大小成正比,而關聯容器 查找的復雜度是Log(N) ,比vector少。
map 提供一種“鍵-值”關系的一對一的數據存儲能力,所有元素都是pair類型。
pair的第一個元素是鍵值,第二個為value值。
鍵值即索引值,在容器中不可重復,其內部按鏈表的方式存儲,故也繼承了鏈表的優缺點,在插入時所有元素都會根據鍵值自動排序。
與set相似,multimap可以實現重復數據的存儲。
二、程序示例
1. vector和Set自定義數據類型的訪問
class Person { public:Person(string name, int age){this->Name = name;this->Age = age;}string Name;int Age; }; //存數據 void test() {//vectorvector<Person> v;Person p1("sun", 4);Person p2("aun", 3);Person p3("cun", 2);Person p4("dun", 1);v.push_back(p1);v.push_back(p2);v.push_back(p3);v.push_back(p4);for (vector<Person>::iterator i = v.begin(); i != v.end(); i++){cout << (*i).Name <<" " <<(*i).Age<<endl;cout << i->Name << " " << i->Age << endl;}//setset<Person> s;Person p1("sun", 4);Person p2("aun", 3);Person p3("cun", 2);Person p4("dun", 1); }//存指針 void test1() {vector<Person*> v;Person p1("sun", 4);Person p2("aun", 3);Person p3("cun", 2);Person p4("dun", 1);v.push_back(&p1);v.push_back(&p2);v.push_back(&p3);v.push_back(&p4);for (vector<Person*>::iterator i = v.begin(); i != v.end(); i++){cout << (*(*i)).Name <<" " << (*(*i)).Age<< endl;cout << (*i)->Name << " " << (*i)->Age << endl;} }2.vector容器嵌套
void test() {vector<vector<int>>doublev;//創建內層容器vector<int>doublev1;//放數據for (int i = 0; i < 3; i++){doublev1.push_back(i + 1);}//放入外層容器doublev.push_back(doublev1);//遍歷數據for (vector<vector<int>>::iterator i = doublev.begin(); i != doublev.end(); i++){for (vector<int>::iterator j = (*i).begin(); j != (*i).end(); j++){cout << *j << endl;cout << &j << endl;//內層嵌套的迭代器指針地址}cout << &i << endl;//外層嵌套的迭代器指針地址} }3.list容器排序
class Cat { public:Cat(string name, int color,int age){this->Name = name;this->Color = color;this->Age = age;}public:string Name;int Color;int Age; };//指定排序規則 bool Compare(Cat& c1, Cat& c2) {if (c1.Color == c2.Color){return c1.Age < c2.Age;}else{return c1.Color < c2.Color;} }void test() {list<Cat>L;Cat cat1("小100", 76, 3);Cat cat2("小200", 32, 2);Cat cat3("小300", 32, 4);Cat cat4("小400", 32, 3);Cat cat5("小500", 54, 1);//插入L.push_back(cat1);L.push_back(cat2);L.push_back(cat3);L.push_back(cat4);L.push_back(cat5);for (list<Cat>::iterator i = L.begin(); i != L.end(); i++){cout << (*i).Name << " " << (*i).Color << " " << (*i).Age << endl;}L.sort(Compare);for (list<Cat>::iterator i = L.begin(); i != L.end(); i++){cout << (*i).Name << " " << (*i).Color << " " << (*i).Age << endl;} }int main() {test();system("pause"); }4.pair對組的使用
pair是一個模板結構體類型,set集合的insert方法就是pair類模板定義的,pair的參數類型有兩種,一個是迭代器,另外一個是bool類。bool返回迭代器是否應用方法成功,pair里的對象可以由pair的兩個函數first和second訪問。
multiset只返回迭代器類型,故可以重復插入。
//set pair<iterator, bool> insert(value_type&& _Val) {const auto _Result = _Emplace(_STD move(_Val));return {iterator(_Result.first, _Get_scary()), _Result.second}; } //pair定義 struct pair { // store a pair of values using first_type = _Ty1; using second_type = _Ty2;//multiset iterator insert(value_type&& _Val) {return iterator(_Emplace(_STD move(_Val)).first, _Get_scary()); } // pair<set<int>::iterator, bool> p = s.insert(4); if (p.second)//first返回迭代器,second返回bool {cout << "插入成功" << endl; }pair既可以將2個數據組合成一組數據,也可以讓函數返回2個數據,具體應用如下:
pair<string, int> p1(string("a"), 3);cout << p1.first << p1.second << endl;pair<string, int> p2 = make_pair(string("a"), 3);cout << p2.first << p2.second << endl;總結
容器的構造函數和成員函數的調用規則基本是類似的,但每種都會存在一點差別,重點記憶vector, list,map三種的調用方式。
總結
以上是生活随笔為你收集整理的C++STL总结笔记(一)—— 容器和容器适配器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Des与3Des加密解密
- 下一篇: C++STL总结笔记(二)——仿函数(函