Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 中文字幕一区二区在线视频,中文字幕免费,九九精品成人免费国产片

          整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          STL總結(jié)與常見(jiàn)面試題


          STL概述

          為了建立數(shù)據(jù)結(jié)構(gòu)和算法的一套標(biāo)準(zhǔn),并且降低他們之間的耦合關(guān)系,以提升各自的獨(dú)立性、彈性、交互操作性(相互合作性,interoperability),誕生了STL。

          STL提供了六大組件,彼此之間可以組合套用,這六大組件分別是:容器、算法、迭代器、仿函數(shù)、適配器(配接器)、空間配置器

          • 容器:各種數(shù)據(jù)結(jié)構(gòu),如vector、list、deque、set、map等,用來(lái)存放數(shù)據(jù),從實(shí)現(xiàn)角度來(lái)看,STL容器是一種class template。
          • 算法:各種常用的算法,如sort、find、copy、for_each。從實(shí)現(xiàn)的角度來(lái)看,STL算法是一種function tempalte.
          • 迭代器:扮演了容器與算法之間的膠合劑,共有五種類型,從實(shí)現(xiàn)角度來(lái)看,迭代器是一種將operator* , operator-> , operator++,operator–等指針相關(guān)操作予以重載的class template. 所有STL容器都附帶有自己專屬的迭代器,只有容器的設(shè)計(jì)者才知道如何遍歷自己的元素。原生指針(native pointer)也是一種迭代器。
          • 仿函數(shù):行為類似函數(shù),可作為算法的某種策略。從實(shí)現(xiàn)角度來(lái)看,仿函數(shù)是一種重載了operator()的class 或者class template
          • 適配器:一種用來(lái)修飾容器或者仿函數(shù)或迭代器接口的東西。
          • 空間配置器:負(fù)責(zé)空間的配置與管理。從實(shí)現(xiàn)角度看,配置器是一個(gè)實(shí)現(xiàn)了動(dòng)態(tài)空間配置、空間管理、空間釋放的class tempalte.

          STL六大組件的交互關(guān)系,容器通過(guò)空間配置器取得數(shù)據(jù)存儲(chǔ)空間,算法通過(guò)迭代器存儲(chǔ)容器中的內(nèi)容,仿函數(shù)可以協(xié)助算法完成不同的策略的變化,適配器可以修飾仿函數(shù)。

          2 STL的優(yōu)點(diǎn):

          1. STL 是 C++的一部分,因此不用額外安裝什么,它被內(nèi)建在你的編譯器之內(nèi)。
          2. STL 的一個(gè)重要特性是將數(shù)據(jù)和操作分離。數(shù)據(jù)由容器類別加以管理,操作則由可定制的算法定義。迭代器在兩者之間充當(dāng)“粘合劑”,以使算法可以和容器交互運(yùn)作
          3. 程序員可以不用思考 STL 具體的實(shí)現(xiàn)過(guò)程,只要能夠熟練使用 STL 就 OK 了。這樣他們就可以把精力放在程序開(kāi)發(fā)的別的方面。
          4. STL 具有高可重用性,高性能,高移植性,跨平臺(tái)的優(yōu)點(diǎn)。
          5. 高可重用性:STL 中幾乎所有的代碼都采用了模板類和模版函數(shù)的方式實(shí)現(xiàn),這相比于傳統(tǒng)的由函數(shù)和類組成的庫(kù)來(lái)說(shuō)提供了更好的代碼重用機(jī)會(huì)。
          6. 高性能:如 map 可以高效地從十萬(wàn)條記錄里面查找出指定的記錄,因?yàn)?map 是采用紅黑樹(shù)的變體實(shí)現(xiàn)的。
          7. 高移植性:如在項(xiàng)目 A 上用 STL 編寫(xiě)的模塊,可以直接移植到項(xiàng)目 B 上。容器和算法之間通過(guò)迭代器進(jìn)行無(wú)縫連接。STL 幾乎所有的代碼都采用了模板類或者模板函數(shù),這相比傳統(tǒng)的由函數(shù)和類組成的庫(kù)來(lái)說(shuō)提供了更好的代碼重用機(jī)會(huì)。

          3 容器

          STL容器就是將運(yùn)用最廣泛的一些數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)出來(lái)。

          常用的數(shù)據(jù)結(jié)構(gòu):數(shù)組(array) , 鏈表(list), tree(樹(shù)),棧(stack), 隊(duì)列(queue), 集合(set),映射表(map), 根據(jù)數(shù)據(jù)在容器中的排列特性,這些數(shù)據(jù)分為序列式容器和關(guān)聯(lián)式容器兩種。

          序列式容器強(qiáng)調(diào)值的排序,序列式容器中的每個(gè)元素均有固定的位置,除非用刪除或插入的操作改變這個(gè)位置。Vector容器、Deque容器、List容器等。

          關(guān)聯(lián)式容器是非線性的樹(shù)結(jié)構(gòu),更準(zhǔn)確的說(shuō)是二叉樹(shù)結(jié)構(gòu)。各元素之間沒(méi)有嚴(yán)格的物理上的順序關(guān)系,也就是說(shuō)元素在容器中并沒(méi)有保存元素置入容器時(shí)的邏輯順序。關(guān)聯(lián)式容器另一個(gè)顯著特點(diǎn)是:在值中選擇一個(gè)值作為關(guān)鍵字key,這個(gè)關(guān)鍵字對(duì)值起到索引的作用,方便查找。Set/multiset容器 Map/multimap容器


          array 是固定大小的順序容器,它們保存了一個(gè)以嚴(yán)格的線性順序排列的特定數(shù)量的元素。

          測(cè)試代碼

          #include<iostream>
          #include<array>
          using namespace std;
          
          int main() 
          {
          	array<int, 8> myArr = {1,3,4,6,9};//固定大小為8
          	cout << "myArr元素序列:";
          	for (auto i = 0; i < 8; ++i) 
          	{
          		cout << myArr[i] << " ";
          	}
          	cout << endl;
          
          	array<int, 8> myArr1 = {2,3,4,7,8,9};//固定大小為8
          	cout << "myArr1元素序列:";
          	for (auto i = 0; i < 8; ++i) 
          	{
          		cout << myArr1[i] << " ";
          	}
          	cout << endl;
          
          	myArr.swap(myArr1);   //交換兩個(gè)容器的內(nèi)容
          	cout << "交換myArr與myArr1"<< endl;
          	cout << endl;
          
          	cout << "myArr.at(3) = " << myArr.at(3) << endl;//任意訪問(wèn)
          	cout << "myArr[3] = " << myArr[3] << endl;//任意訪問(wèn)
          	cout << "myArr.front() = " << myArr.front() << endl;//獲取第一個(gè)元素
          	cout << "myArr.back() =  " << myArr.back() << endl;//獲取最后一個(gè)元素
          	cout << "myArr.data() = " << myArr.data() << endl;//獲取第一個(gè)元素的指針
          	cout << "*myArr.data() = " << *myArr.data() << endl;//獲取第一個(gè)元素的指針指向的元素
          
          	cout << "正向迭代器遍歷容器:";
          	for (auto it = myArr.begin(); it != myArr.end(); ++it) 
          	{
          		cout << *it << " ";
          	}
          	cout << endl;
          	//逆向迭代器測(cè)試
          	cout << "逆向迭代器遍歷容器:";
          	for (auto rit = myArr.rbegin(); rit != myArr.rend(); ++rit) 
          	{
          		cout << *rit << " ";
          	}
          	cout << endl;
          	//正向常迭代器測(cè)試
          	cout << "正向常迭代器遍歷容器:";
          	for (auto it = myArr.cbegin(); it != myArr.cend(); ++it) 
          	{
          		cout << *it << " ";
          	}
          	cout << endl;
          	//逆向常迭代器測(cè)試
          	cout << "逆向常迭代器遍歷容器:";
          	for (auto rit = myArr.crbegin(); rit != myArr.crend(); ++rit) 
          	{
          		cout << *rit << " ";
          	}
          	cout << endl;
          	if(myArr.empty())
          		cout << "myArr為空 " << endl;
          	else
          		cout << "myArr不為空 " << endl;
          	cout << "myArr.size() = " << myArr.size() << endl;
          	cout << "myArr.max_size() = " << myArr.max_size() << endl;
          
          	return 0;
          }
          

          運(yùn)行結(jié)果

          運(yùn)行結(jié)果

          vector

          vector 是表示可以改變大小的數(shù)組的序列容器。

          方法說(shuō)明vector構(gòu)造函數(shù)~vector析構(gòu)函數(shù),銷毀容器對(duì)象operator=將新內(nèi)容分配給容器,替換其當(dāng)前內(nèi)容,并相應(yīng)地修改其大小begin返回指向容器中第一個(gè)元素的迭代器end返回指向容器中最后一個(gè)元素之后的理論元素的迭代器rbegin返回指向容器中最后一個(gè)元素的反向迭代器rend返回一個(gè)反向迭代器,指向中第一個(gè)元素之前的理論元素cbegin返回指向容器中第一個(gè)元素的常量迭代器(const_iterator)cend返回指向容器中最后一個(gè)元素之后的理論元素的常量迭代器(const_iterator)crbegin返回指向容器中最后一個(gè)元素的常量反向迭代器(const_reverse_iterator)crend返回指向容器中第一個(gè)元素之前的理論元素的常量反向迭代器(const_reverse_iterator)size返回容器中元素的數(shù)量max_size返回容器可容納的最大元素?cái)?shù)resize調(diào)整容器的大小,使其包含 n(參數(shù))個(gè)元素capacity返回當(dāng)前為 vector 分配的存儲(chǔ)空間(容量)的大小empty返回 vector 是否為空reserve請(qǐng)求 vector 容量至少足以包含 n(參數(shù))個(gè)元素shrink_to_fit要求容器減小其 capacity(容量)以適應(yīng)其 size(元素?cái)?shù)量)operator[]返回容器中第 n(參數(shù))個(gè)位置的元素的引用at返回容器中第 n(參數(shù))個(gè)位置的元素的引用front返回對(duì)容器中第一個(gè)元素的引用back返回對(duì)容器中最后一個(gè)元素的引用data返回指向容器中第一個(gè)元素的指針assign將新內(nèi)容分配給 vector,替換其當(dāng)前內(nèi)容,并相應(yīng)地修改其 sizepush_back在容器的最后一個(gè)元素之后添加一個(gè)新元素pop_back刪除容器中的最后一個(gè)元素,有效地將容器 size 減少一個(gè)insert通過(guò)在指定位置的元素之前插入新元素來(lái)擴(kuò)展該容器,通過(guò)插入元素的數(shù)量有效地增加容器大小erase從 vector 中刪除單個(gè)元素(position)或一系列元素([first,last)),這有效地減少了被去除的元素的數(shù)量,從而破壞了容器的大小swap通過(guò) x(參數(shù))的內(nèi)容交換容器的內(nèi)容,x 是另一個(gè)類型相同、size 可能不同的 vector 對(duì)象clear從 vector 中刪除所有的元素(被銷毀),留下 size 為 0 的容器emplace通過(guò)在 position(參數(shù))位置處插入新元素 args(參數(shù))來(lái)擴(kuò)展容器emplace_back在 vector 的末尾插入一個(gè)新的元素,緊跟在當(dāng)前的最后一個(gè)元素之后get_allocator返回與vector關(guān)聯(lián)的構(gòu)造器對(duì)象的副本swap(vector)容器 x(參數(shù))的內(nèi)容與容器 y(參數(shù))的內(nèi)容交換。兩個(gè)容器對(duì)象都必須是相同的類型(相同的模板參數(shù)),盡管大小可能不同relational operators (vector)形如 vectorA > vectorB;依此比較每個(gè)元素的大小關(guān)系

          測(cè)試代碼

          #include <vector>
          #include <iostream>
          using namespace std;
          
          int main()
          {
          
          	//構(gòu)造函數(shù),復(fù)制構(gòu)造函數(shù)(元素類型要一致),
          	vector<int> vecA;  //創(chuàng)建一個(gè)空的的容器
          	vector<int> vecB(10,20); //創(chuàng)建一個(gè)10個(gè)元素,每個(gè)元素值為20
          	vector<int> vecC(vecB.begin(),vecB.end()); //使用迭代器,可以取部分元素創(chuàng)建一個(gè)新的容器
          	vector<int> vecD(vecC); //復(fù)制構(gòu)造函數(shù),創(chuàng)建一個(gè)完全一樣的容器
          
          	//重載=
          	vector<int> vecE;
          	vecE = vecB;
          
          	//vector::begin(),返回的是迭代器
          
          	vector<int> vecF(10); //創(chuàng)建一個(gè)有10個(gè)元素的容器
          	cout << "vecF:";
          	for (int i = 0; i < 10; i++)
          	{
          		vecF[i] = i;
          		cout << vecF[i]<< " ";
          	}
          	cout << endl;
          
          	//vector::begin() 返回迭代器
          	vector<int>::iterator Beginit = vecF.begin();
          	cout<< "vecF.begin():" << *Beginit << endl; 
          
          	//vector::end() 返回迭代器
          	vector<int>::iterator EndIter = vecF.end();
          	EndIter--; //向后移一個(gè)位置
          	cout <<"vecF.end():"<< *EndIter << endl; 
          
          	//vector::rbegin() 返回倒序的第一個(gè)元素,相當(dāng)于最后一個(gè)元素
          	vector<int>::reverse_iterator ReverBeIter = vecF.rbegin();
          	cout << "vecF.rbegin(): "<< *ReverBeIter << endl; 
          
          	//vector::rend() 反序的最后一個(gè)元素下一個(gè)位置,也相當(dāng)于正序的第一個(gè)元素前一個(gè)位置
          	vector<int>::reverse_iterator ReverEnIter = vecF.rend();
          	ReverEnIter--;
          	cout << "vecF.rend():"<< *ReverEnIter << endl; 
          
          	//vector::size() 返回元素的個(gè)數(shù)
          	cout << "vecF.size():"<< vecF.size() << endl; 
          
          	//vector::max_size()
          	cout << "vecF.max_size():"<< vecF.max_size() << endl; 
          
          	//vector::resize()
          	cout<< "vecF.size():" << vecF.size() << endl; 
          	vecF.resize(5);
          
          	cout<< "調(diào)整vecF大小后重新賦值:"; 
          	for(int k = 0; k < vecF.size(); k++)
          		cout << vecF[k] << "  "; 
          	cout << endl;
          
          	//vector::capacity()
          	cout<< "調(diào)整后vecF.size():"<< vecF.size() << endl; 
          	cout<< "調(diào)整后vecF.capacity():" << vecF.capacity() << endl; 
          
          	//vector::empty()
          	vecB.resize(0);
          	cout<< "vecB.resize(0)后"<< endl; 
          
          	cout  << "vecB.size():" << vecB.size() << endl; 
          	cout  << "vecB.capacity():" << vecB.capacity() << endl; 
          	if(vecB.empty())
          	    cout << "vecB為空"<< endl; 
          	else
          		cout << "vecB不為空"<< endl; 
          
          	//vector::reserve() //重新分配存儲(chǔ)空間大小
          	cout<< "vecC.capacity():" << vecC.capacity() << endl; //
          
          	vecC.reserve(4);
          	cout << "vecC.reserve(4)后vecC.capacity(): "<< vecC.capacity() << endl; //10
          	vecC.reserve(14);
          	cout << "vecC.reserve(14)后vecC.capacity(): "<< vecC.capacity() << endl; //14
          
          	//vector::operator []
          	cout << "vecF[0]:"<< vecF[0] << endl; //第一個(gè)元素是0
          
          	//vector::at()
          	try
          	{
          		cout << "vecF.size = " << vecF.size() << endl; //5
          		cout << vecF.at(6) << endl; //拋出異常
          	}
          	catch(out_of_range)
          	{	
          		cout << "at()訪問(wèn)越界" << endl;
          	}
          
          	//vector::front() 返回第一個(gè)元素的值
          	cout << "vecF.front():"<< vecF.front() << endl; //0
          
          	//vector::back()
          	cout << "vecF.back():"<< vecF.back() << endl; //4
          
          	//vector::assign()
          	cout <<"vecA.size():"<< vecA.size() << endl; //0
          	vector<int>::iterator First = vecC.begin();
          	vector<int>::iterator End = vecC.end()-2;
          	vecA.assign(First,End);
          	cout << vecA.size() << endl; //8
          	cout << vecA.capacity() << endl; //8
          
          	vecA.assign(5,3); //將丟棄原來(lái)的所有元素然后重新賦值
          	cout << vecA.size() << endl; //5
          	cout << vecA.capacity() << endl; //8
          
          	//vector::push_back()
          	cout << *(vecF.end()-1) << endl; //4
          	vecF.push_back(20);
          	cout << *(vecF.end()-1) << endl; //20
          
          	//vector::pop_back()
          	cout << *(vecF.end()-1) << endl; //20
          	vecF.pop_back();
          	cout << *(vecF.end()-1) << endl; //4
          
          	//vector::swap()
          	cout << "vecF:";
          	for (int i = 0; i < vecF.size(); i++)
          	{
          		vecF[i] = i;
          		cout << vecF[i]<< " ";
          	}
          	cout << endl;
          	cout << "vecD:";
          	for (int d = 0; d < vecD.size(); d++)
          	{
          		vecD[d] = d;
          		cout << vecD[d]<< " ";
          	}
          	cout << endl;
          
          	vecF.swap(vecD); //交換這兩個(gè)容器的內(nèi)容
          	cout <<"vecD與vecF交換后:" <<endl;
          	cout << "vecF:";
          	for(int f = 0; f < vecF.size(); f++)
          		cout << vecF[f] << " ";
          	cout << endl;
          
          	cout << "vecD:";
          	for (int d = 0; d <vecD.size(); d++)
          		cout << vecD[d] << " ";
          	cout << endl;
          	//vector::clear()
          	vecF.clear();
          	cout << "vecF.clear()后vecF.size():"<< vecF.size() << endl;     //0
          	cout << "vecF.clear()后vecF.capacity():"<< vecF.capacity() << endl; //10
          
          	return 0;
          }

          運(yùn)行結(jié)果

          運(yùn)行結(jié)果

          deque

          deque容器為一個(gè)給定類型的元素進(jìn)行線性處理,像向量一樣,它能夠快速地隨機(jī)訪問(wèn)任一個(gè)元素,并且能夠高效地插入和刪除容器的尾部元素。但它又與vector不同,deque支持高效插入和刪除容器的頭部元素,因此也叫做雙端隊(duì)列。

          deque的中控器: deque是由一段一段的定量連續(xù)空間構(gòu)成。一旦有必要在deque的前端或尾端增加新空間,便配置一段定量連續(xù)空間,串接在整個(gè)deque的頭端或尾端。deque的最大任務(wù),便是在這些分段的定量連續(xù)空間上,維護(hù)其整體連續(xù)的假象,并提供隨機(jī)存取的接口。避開(kāi)了“重新配置、復(fù)制、釋放”的輪回,代價(jià)則是復(fù)雜的迭代器結(jié)構(gòu)。

          deque采用一塊所謂的map(不是STL的map容器)作為主控。

          map是一小塊連續(xù)空間,其中每個(gè)元素(此處稱為一個(gè)節(jié)點(diǎn),node)都是指針,指向另一段(較大的)連續(xù)線性空間,稱為緩沖區(qū)。

          緩沖區(qū)才是deque的儲(chǔ)存空間主體。

          template<class T, class Alloc = alloc, size_t BufSiz = 0>  
          class deque{  
          public :  
              typedef T value_type ;  
              typedef value_type* pointer ;  
              ...  
          protected :  
              //元素的指針的指針(pointer of pointer of T)  
              // 其實(shí)就是T**,一個(gè)二級(jí)指針,維護(hù)一個(gè)二維數(shù)組
              typedef pointer* map_pointer ; 
            
          protected :  
              map_pointer map ; //指向map,map是塊連續(xù)空間,其內(nèi)的每個(gè)元素  
                                //都是一個(gè)指針(稱為節(jié)點(diǎn)),指向一塊緩沖區(qū)  
              size_type map_size ;//map內(nèi)可容納多少指針  
              ...  
          };  

          map其實(shí)是一個(gè)T**,也就是說(shuō)它是一個(gè)指針,所指之物也是一個(gè)指針,指向型別為T的一塊空間。

          方法說(shuō)明deque構(gòu)造函數(shù)push_back在當(dāng)前的最后一個(gè)元素之后 ,在 deque 容器的末尾添加一個(gè)新元素push_front在 deque 容器的開(kāi)始位置插入一個(gè)新的元素,位于當(dāng)前的第一個(gè)元素之前pop_back刪除 deque 容器中的最后一個(gè)元素,有效地將容器大小減少一個(gè)pop_front刪除 deque 容器中的第一個(gè)元素,有效地減小其大小emplace_front在 deque 的開(kāi)頭插入一個(gè)新的元素,就在其當(dāng)前的第一個(gè)元素之前emplace_back在 deque 的末尾插入一個(gè)新的元素,緊跟在當(dāng)前的最后一個(gè)元素之后

          測(cè)試代碼

          #include "stdafx.h"
          #include<iostream>
          #include<deque>
           
          using namespace std;
          int main()
          {
          	deque<int> d;
          	d.push_back( 11 );//在 deque 容器的末尾添加一個(gè)新元素
          	d.push_back(20);
          	d.push_back(35);
          	cout<<"初始化雙端隊(duì)列d:"<<endl;
          	for(int i = 0; i < d.size(); i++)
          	{
          		cout<<d.at(i)<<"\t";
          	}
          	cout<<endl;
          
          	d.push_front(10);//容器的開(kāi)始位置插入一個(gè)新的元素,位于當(dāng)前的第一個(gè)元素之前
          	d.push_front(7);
          	d.push_front(1);
           
          	cout<<"隊(duì)列d向前陸續(xù)插入10、7、1:"<<endl;
          	for(int i = 0;i < d.size();i++)
          	{
          		cout<<d.at(i)<<"\t";
          	}
          	cout<<endl;
          
          	d.pop_back(); //刪除 deque 容器中的最后一個(gè)元素,有效地將容器大小減少一個(gè)
          	d.pop_front(); //刪除 deque 容器中的第一個(gè)元素,有效地減小其大小
          	cout<<"刪除deque最后一個(gè)和第一個(gè)元素后:"<<endl;
          	for(int i = 0;i < d.size();i++)
          	{
          		cout<<d.at(i)<<"\t";
          	}
          	cout<<endl;
          	return 0;
          }

          forward_list

          在頭文件<forward_list>中,與list類似,區(qū)別就是list時(shí)雙鏈表,forward_list是單鏈表,forward_list(單向鏈表)是序列容器,允許在序列中的任何地方進(jìn)行恒定的時(shí)間插入和擦除操作。在鏈表的任何位置進(jìn)行插入/刪除操作都非常快。

          forward_list的特點(diǎn)

          • forward_list只提供錢箱迭代器,因此不支持反向迭代器,比如rbegin()等成員函數(shù)。
          • forward_list不提供size()成員函數(shù)。
          • forward_list沒(méi)有指向最末元素的錨點(diǎn),因此不提供back()、push_back()和pop_back()。
          • forward_list不提供隨機(jī)訪問(wèn),這一點(diǎn)跟list相同。
          • 插入和刪除元素不會(huì)造成“指向至其他元素”的指針,引用和迭代器失效。

          容器成員函數(shù)總結(jié)就不寫(xiě)了,太多影響閱讀,感興趣小伙伴戳http://www.cplusplus.com/reference/stl/

          list

          list雙向鏈表,是序列容器,允許在序列中的任何地方進(jìn)行常數(shù)時(shí)間插入和擦除操作,并在兩個(gè)方向上進(jìn)行迭代,可以高效地進(jìn)行插入刪除元素。

          使用list容器之前必須加上頭文件:#include;

          list容器的底層實(shí)現(xiàn):

          和 array、vector 這些容器迭代器的實(shí)現(xiàn)方式不同,由于 list 容器的元素并不是連續(xù)存儲(chǔ)的,所以該容器迭代器中,必須包含一個(gè)可以指向 list 容器的指針,并且該指針還可以借助重載的 *、++、--、==、!= 等運(yùn)算符,實(shí)現(xiàn)迭代器正確的遞增、遞減、取值等操作。

          template<tyepname T,...>
          struct __list_iterator{
              __list_node<T>* node;
              //...
              //重載 == 運(yùn)算符
              bool operator==(const __list_iterator& x){return node == x.node;}
              //重載 != 運(yùn)算符
              bool operator!=(const __list_iterator& x){return node != x.node;}
              //重載 * 運(yùn)算符,返回引用類型
              T* operator *() const {return *(node).myval;}
              //重載前置 ++ 運(yùn)算符
              __list_iterator<T>& operator ++(){
                  node = (*node).next;
                  return *this;
              }
              //重載后置 ++ 運(yùn)算符
              __list_iterator<T>& operator ++(int){
                  __list_iterator<T> tmp = *this;
                  ++(*this);
                  return tmp;
              }
              //重載前置 -- 運(yùn)算符
              __list_iterator<T>& operator--(){
                  node = (*node).prev;
                  return *this;
              }
              //重載后置 -- 運(yùn)算符
              __list_iterator<T> operator--(int){
                  __list_iterator<T> tmp = *this;
                  --(*this);
                  return tmp;
              }
              //...
          }

          stack

          stack沒(méi)有迭代器,是一種容器適配器,用于在LIFO(后進(jìn)先出)的操作,其中元素僅從容器的一端插入和提取。

          stack底層一般用list或deque實(shí)現(xiàn),封閉頭部即可,不用vector的原因應(yīng)該是容量大小有限制,擴(kuò)容耗時(shí)

          底層用deque實(shí)現(xiàn)

          //deque<T> >中間有個(gè)空格是為了兼容較老的版本
          template <class T, class Sequence = deque<T> >
          class stack {
              // 以下的 __STL_NULL_TMPL_ARGS 會(huì)開(kāi)展為 <>
              friend bool operator== __STL_NULL_TMPL_ARGS (const stack&, const stack&);
              friend bool operator< __STL_NULL_TMPL_ARGS (const stack&, const stack&);
          public:
              typedef typename Sequence::value_type value_type;
              typedef typename Sequence::size_type size_type;
              typedef typename Sequence::reference reference;
              typedef typename Sequence::const_reference const_reference;
          protected:
              Sequence c; // 底層容器
          public:
              // 以下完全利用 Sequence c 的操作,完成 stack 的操作。
              bool empty() const { return c.empty(); }
              size_type size() const { return c.size(); }
              reference top() { return c.back(); }
              const_reference top() const { return c.back(); }
              // deque 是兩頭可進(jìn)出,stack 是末端進(jìn),末端出(所以后進(jìn)者先出)。
              void push(const value_type& x) { c.push_back(x); }
              void pop() { c.pop_back(); }
          };
          
          template <class T, class Sequence>
          bool operator==(const stack<T, Sequence>& x, const stack<T, Sequence>& y) {
              return x.c == y.c;
          }
          
          template <class T, class Sequence>
          bool operator<(const stack<T, Sequence>& x, const stack<T, Sequence>& y) {
              return x.c < y.c;
          }

          底層用list實(shí)現(xiàn)

            #include<stack>  
            #include<list>  
            #include<algorithm>  
            #include <iostream>  
            using namespace std;  
              
            int main(){  
                stack<int, list<int>> istack;  
                istack.push(1);  
                istack.push(3);  
                istack.push(5);  
                  
                cout << istack.size() << endl; //3  
                cout << istack.top() << endl;//5  
                istack.pop();  
                cout << istack.top() << endl;//3  
                cout << istack.size() << endl;//2  
              
                system("pause");  
                return 0;  
            }  

          queue

          queue 是一種容器適配器,用于在FIFO(先入先出)的操作,其中元素插入到容器的一端并從另一端提取。

          隊(duì)列不提供迭代器,不實(shí)現(xiàn)遍歷操作。

          template <class T, class Sequence = deque<T> >
          class queue {
            friend bool operator== __STL_NULL_TMPL_ARGS (const queue& x, const queue& y);
            friend bool operator< __STL_NULL_TMPL_ARGS (const queue& x, const queue& y);
          public:
            typedef typename Sequence::value_type value_type;
            typedef typename Sequence::size_type size_type;
            typedef typename Sequence::reference reference;
            typedef typename Sequence::const_reference const_reference;
          protected:
            Sequence c;
          public:
            bool empty() const { return c.empty(); }
            size_type size() const { return c.size(); }
            reference front() { return c.front(); }
            const_reference front() const { return c.front(); }
            reference back() { return c.back(); }
            const_reference back() const { return c.back(); }
            void push(const value_type& x) { c.push_back(x); }
            void pop() { c.pop_front(); }
          };
          
          template <class T, class Sequence>
          bool operator==(const queue<T, Sequence>& x, const queue<T, Sequence>& y) {
            return x.c == y.c;
          }
          
          template <class T, class Sequence>
          bool operator<(const queue<T, Sequence>& x, const queue<T, Sequence>& y) {
            return x.c < y.c;
          }

          priority_queue

          優(yōu)先隊(duì)列,其底層是用堆來(lái)實(shí)現(xiàn)的。在優(yōu)先隊(duì)列中,隊(duì)首元素一定是當(dāng)前隊(duì)列中優(yōu)先級(jí)最高的那一個(gè)。

          set

          set 是按照特定順序存儲(chǔ)唯一元素的容器。

          template<class _Kty,
              class _Pr = less<_Kty>,
              class _Alloc = allocator<_Kty> >
          class set
          1. set 的 底層數(shù)據(jù)結(jié)構(gòu)是 紅黑樹(shù),一種高效的平衡檢索二叉樹(shù)。
          2. set 容器中 每一個(gè)元素就是二叉樹(shù)的每一個(gè)節(jié)點(diǎn),對(duì)于set容器的插入刪除操作,效率都比較高,原因是因?yàn)槎鏄?shù)的刪除插入元素并不需要進(jìn)行內(nèi)存拷貝和內(nèi)存移動(dòng),只是改變了指針的指向。
          3. 對(duì) set 進(jìn)行插入刪除操作 都不會(huì)引起iterator的失效,因?yàn)榈飨喈?dāng)于一個(gè)指針指向每一個(gè)二叉樹(shù)的節(jié)點(diǎn),對(duì)set的插入刪除并不會(huì)改變?cè)袃?nèi)存中節(jié)點(diǎn)的改變, 但是vector的插入刪除操作一般會(huì)發(fā)生內(nèi)存移動(dòng)和內(nèi)存拷貝,所以會(huì)發(fā)生迭代器的失效。
          4. set容器的檢索速度很快,因?yàn)椴捎枚植檎业姆椒?。

          multiset

          multiset允許元素重復(fù)而set不允許

          template<class _Kty,
          	class _Pr = less<_Kty>,
          	class _Alloc = allocator<_Kty> >
          class multiset

          map

          map 是關(guān)聯(lián)容器,按照特定順序存儲(chǔ)由 key value (鍵值) 和 mapped value (映射值) 組合形成的元素。

          由于 RB-tree 是一種平衡二叉搜索樹(shù),自動(dòng)排序的效果很不錯(cuò),所以標(biāo)準(zhǔn)的STL map 即以 RB-tree 為底層機(jī)制。又由于 map 所開(kāi)放的各種操作接口,RB-tree 也都提供了,所以幾乎所有的 map 操作行為,都只是轉(zhuǎn)調(diào) RB-tree 的操作行為。

          方法說(shuō)明map構(gòu)造函數(shù)begin返回引用容器中第一個(gè)元素的迭代器key_comp返回容器用于比較鍵的比較對(duì)象的副本value_comp返回可用于比較兩個(gè)元素的比較對(duì)象,以獲取第一個(gè)元素的鍵是否在第二個(gè)元素之前find在容器中搜索具有等于 k的鍵的元素,如果找到返回一個(gè)迭代器,否則返回 map::endcount在容器中搜索具有等于 k(參數(shù))的鍵的元素,并返回匹配的數(shù)量lower_bound返回一個(gè)非遞減序列 [first, last)中的第一個(gè)大于等于值 val的位置的迭代器upper_bound返回一個(gè)非遞減序列 [first, last)中第一個(gè)大于 val的位置的迭代器equal_range獲取相同元素的范圍,返回包含容器中所有具有與 k等價(jià)的鍵的元素的范圍邊界

          multimap

          multimap 的特性以及用法與 map 完全相同,唯一的差別在于它允許鍵值重復(fù),因此它的插入操作采用的是底層機(jī)制 RB-tree 的 insert_equal() 而非 insert_unique。

          unordered_set

          unordered_set是基于哈希表,因此要了解unordered_set,就必須了解哈希表的機(jī)制。哈希表是根據(jù)關(guān)鍵碼值而進(jìn)行直接訪問(wèn)的數(shù)據(jù)結(jié)構(gòu),通過(guò)相應(yīng)的哈希函數(shù)(也稱散列函數(shù))處理關(guān)鍵字得到相應(yīng)的關(guān)鍵碼值,關(guān)鍵碼值對(duì)應(yīng)著一個(gè)特定位置,用該位置來(lái)存取相應(yīng)的信息,這樣就能以較快的速度獲取關(guān)鍵字的信息。

          template < class Key,  
              class Hash = hash<Key>,  
              class Pred = equal_to<Key>,  
              class Alloc = allocator<Key>  
          > class unordered_set;  

          4 算法

          1. 簡(jiǎn)單查找算法,要求輸入迭代器(input iterator)
          find(beg, end, val); // 返回一個(gè)迭代器,指向輸入序列中第一個(gè)等于 val 的元素,未找到返回 end
          find_if(beg, end, unaryPred); // 返回一個(gè)迭代器,指向第一個(gè)滿足 unaryPred 的元素,未找到返回 end
          find_if_not(beg, end, unaryPred); // 返回一個(gè)迭代器,指向第一個(gè)令 unaryPred 為 false 的元素,未找到返回 end
          count(beg, end, val); // 返回一個(gè)計(jì)數(shù)器,指出 val 出現(xiàn)了多少次
          count_if(beg, end, unaryPred); // 統(tǒng)計(jì)有多少個(gè)元素滿足 unaryPred
          all_of(beg, end, unaryPred); // 返回一個(gè) bool 值,判斷是否所有元素都滿足 unaryPred
          any_of(beg, end, unaryPred); // 返回一個(gè) bool 值,判斷是否任意(存在)一個(gè)元素滿足 unaryPred
          none_of(beg, end, unaryPred); // 返回一個(gè) bool 值,判斷是否所有元素都不滿足 unaryPred
          1. 查找重復(fù)值的算法,傳入向前迭代器(forward iterator)
          adjacent_find(beg, end); // 返回指向第一對(duì)相鄰重復(fù)元素的迭代器,無(wú)相鄰元素則返回 end
          adjacent_find(beg, end, binaryPred); // 返回指向第一對(duì)相鄰重復(fù)元素的迭代器,無(wú)相鄰元素則返回 end
          search_n(beg, end, count, val); // 返回一個(gè)迭代器,從此位置開(kāi)始有 count 個(gè)相等元素,不存在則返回 end
          search_n(beg, end, count, val, binaryPred); // 返回一個(gè)迭代器,從此位置開(kāi)始有 count 個(gè)相等元素,不存在則返回 end
          1. 查找子序列算法,除 find_first_of(前兩個(gè)輸入迭代器,后兩個(gè)前向迭代器) 外,都要求兩個(gè)前向迭代器
          search(beg1, end1, beg2, end2); // 返回第二個(gè)輸入范圍(子序列)在爹一個(gè)輸入范圍中第一次出現(xiàn)的位置,未找到則返回 end1
          search(beg1, end1, beg2, end2, binaryPred); // 返回第二個(gè)輸入范圍(子序列)在爹一個(gè)輸入范圍中第一次出現(xiàn)的位置,未找到則返回 end1
          find_first_of(beg1, end1, beg2, end2); // 返回一個(gè)迭代器,指向第二個(gè)輸入范圍中任意元素在第一個(gè)范圍中首次出現(xiàn)的位置,未找到則返回end1
          find_first_of(beg1, end1, beg2, end2, binaryPred); // 返回一個(gè)迭代器,指向第二個(gè)輸入范圍中任意元素在第一個(gè)范圍中首次出現(xiàn)的位置,未找到則返回end1
          find_end(beg1, end1, beg2, end2); // 類似 search,但返回的最后一次出現(xiàn)的位置。如果第二個(gè)輸入范圍為空,或者在第一個(gè)輸入范圍為空,或者在第一個(gè)輸入范圍中未找到它,則返回 end1
          find_end(beg1, end1, beg2, end2, binaryPred); // 類似 search,但返回的最后一次出現(xiàn)的位置。如果第二個(gè)輸入范圍為空,或者在第一個(gè)輸入范圍為空,或者在第一個(gè)輸入范圍中未找到它,則返回 end1
          1. 其他只讀算法,傳入輸入迭代器
          for_each(beg, end, unaryOp); // 對(duì)輸入序列中的每個(gè)元素應(yīng)用可調(diào)用對(duì)象 unaryOp,unaryOp 的返回值被忽略
          mismatch(beg1, end1, beg2); // 比較兩個(gè)序列中的元素。返回一個(gè)迭代器的 pair,表示兩個(gè)序列中第一個(gè)不匹配的元素
          mismatch(beg1, end1, beg2, binaryPred); // 比較兩個(gè)序列中的元素。返回一個(gè)迭代器的 pair,表示兩個(gè)序列中第一個(gè)不匹配的元素
          equal(beg1, end1, beg2); // 比較每個(gè)元素,確定兩個(gè)序列是否相等。
          equal(beg1, end1, beg2, binaryPred); // 比較每個(gè)元素,確定兩個(gè)序列是否相等。
          1. 二分搜索算法,傳入前向迭代器或隨機(jī)訪問(wèn)迭代器(random-access iterator),要求序列中的元素已經(jīng)是有序的
          lower_bound(beg, end, val); // 返回一個(gè)非遞減序列 [beg, end) 中的第一個(gè)大于等于值 val 的位置的迭代器,不存在則返回 end
          lower_bound(beg, end, val, comp); // 返回一個(gè)非遞減序列 [beg, end) 中的第一個(gè)大于等于值 val 的位置的迭代器,不存在則返回 end
          upper_bound(beg, end, val); // 返回一個(gè)非遞減序列 [beg, end) 中第一個(gè)大于 val 的位置的迭代器,不存在則返回 end
          upper_bound(beg, end, val, comp); // 返回一個(gè)非遞減序列 [beg, end) 中第一個(gè)大于 val 的位置的迭代器,不存在則返回 end
          equal_range(beg, end, val); // 返回一個(gè) pair,其 first 成員是 lower_bound 返回的迭代器,其 second 成員是 upper_bound 返回的迭代器
          binary_search(beg, end, val); // 返回一個(gè) bool 值,指出序列中是否包含等于 val 的元素。對(duì)于兩個(gè)值 x 和 y,當(dāng) x 不小于 y 且 y 也不小于 x 時(shí),認(rèn)為它們相等。
          1. 只寫(xiě)不讀算法,要求輸出迭代器(output iterator)
          fill(beg, end, val); // 將 val 賦予每個(gè)元素,返回 void
          fill_n(beg, cnt, val); // 將 val 賦予 cnt 個(gè)元素,返回指向?qū)懭氲捷敵鲂蛄凶钣幸粋€(gè)元素之后位置的迭代器
          genetate(beg, end, Gen); // 每次調(diào)用 Gen() 生成不同的值賦予每個(gè)序列,返回 void
          genetate_n(beg, cnt, Gen); // 每次調(diào)用 Gen() 生成不同的值賦予 cnt 個(gè)序列,返回指向?qū)懭氲捷敵鲂蛄凶钣幸粋€(gè)元素之后位置的迭代器

          7.使用輸入迭代器的寫(xiě)算法,讀取一個(gè)輸入序列,將值寫(xiě)入到一個(gè)輸出序列(dest)中

          copy(beg, end, dest); // 從輸入范圍將元素拷貝所有元素到 dest 指定定的目的序列
          copy_if(beg, end, dest, unaryPred); // 從輸入范圍將元素拷貝滿足 unaryPred 的元素到 dest 指定定的目的序列
          copy_n(beg, n, dest); // 從輸入范圍將元素拷貝前 n 個(gè)元素到 dest 指定定的目的序列
          move(beg, end, dest); // 對(duì)輸入序列中的每個(gè)元素調(diào)用 std::move,將其移動(dòng)到迭代器 dest 開(kāi)始始的序列中
          transform(beg, end, dest, unaryOp); // 調(diào)用給定操作(一元操作),并將結(jié)果寫(xiě)到dest中
          transform(beg, end, beg2, dest, binaryOp); // 調(diào)用給定操作(二元操作),并將結(jié)果寫(xiě)到dest中
          replace_copy(beg, end, dest, old_val, new_val); // 將每個(gè)元素拷貝到 dest,將等于 old_val 的的元素替換為 new_val
          replace_copy_if(beg, end, dest, unaryPred, new_val); // 將每個(gè)元素拷貝到 dest,將滿足 unaryPred 的的元素替換為 new_val
          merge(beg1, end1, beg2, end2, dest); // 兩個(gè)輸入序列必須都是有序的,用小于號(hào)運(yùn)算符將合并后的序列寫(xiě)入到 dest 中
          merge(beg1, end1, beg2, end2, dest, comp); // 兩個(gè)輸入序列必須都是有序的,使用給定的比較操作(comp)將合并后的序列寫(xiě)入到 dest 中

          8.劃分算法,要求雙向選代器(bidirectional iterator)

          is_partitioned(beg, end, unaryPred); // 如果所有滿足謂詞 unaryPred 的元素都在不滿足 unarypred 的元素之前,則返回 true。若序列為空,也返回 true
          partition_copy(beg, end, dest1, dest2, unaryPred); // 將滿足 unaryPred 的元素拷貝到到 dest1,并將不滿足 unaryPred 的元素拷貝到到 dest2。返回一個(gè)迭代器 pair,其 first 成員表示拷貝到 dest1 的的元素的末尾,second 表示拷貝到 dest2 的元素的末尾。
          partitioned_point(beg, end, unaryPred); // 輸入序列必須是已經(jīng)用 unaryPred 劃分過(guò)的。返回滿足  unaryPred 的范圍的尾后迭代器。如果返回的迭代器不是 end,則它指向的元素及其后的元素必須都不滿足 unaryPred
          stable_partition(beg, end, unaryPred); // 使用 unaryPred 劃分輸入序列。滿足 unaryPred 的元素放置在序列開(kāi)始,不滿足的元素放在序列尾部。返回一個(gè)迭代器,指向最后一個(gè)滿足 unaryPred 的元素之后的位置如果所有元素都不滿足 unaryPred,則返回 beg
          partition(beg, end, unaryPred); // 使用 unaryPred 劃分輸入序列。滿足 unaryPred 的元素放置在序列開(kāi)始,不滿足的元素放在序列尾部。返回一個(gè)迭代器,指向最后一個(gè)滿足 unaryPred 的元素之后的位置如果所有元素都不滿足 unaryPred,則返回 beg
          1. 排序算法,要求隨機(jī)訪問(wèn)迭代器(random-access iterator)
          sort(beg, end); // 排序整個(gè)范圍
          stable_sort(beg, end); // 排序整個(gè)范圍(穩(wěn)定排序)
          sort(beg, end, comp); // 排序整個(gè)范圍
          stable_sort(beg, end, comp); // 排序整個(gè)范圍(穩(wěn)定排序)
          is_sorted(beg, end); // 返回一個(gè) bool 值,指出整個(gè)輸入序列是否有序
          is_sorted(beg, end, comp); // 返回一個(gè) bool 值,指出整個(gè)輸入序列是否有序
          is_sorted_until(beg, end); // 在輸入序列中査找最長(zhǎng)初始有序子序列,并返回子序列的尾后迭代器
          is_sorted_until(beg, end, comp); // 在輸入序列中査找最長(zhǎng)初始有序子序列,并返回子序列的尾后迭代器
          partial_sort(beg, mid, end); // 排序 mid-beg 個(gè)元素。即,如果 mid-beg 等于 42,則此函數(shù)將值最小的 42 個(gè)元素有序放在序列前 42 個(gè)位置
          partial_sort(beg, mid, end, comp); // 排序 mid-beg 個(gè)元素。即,如果 mid-beg 等于 42,則此函數(shù)將值最小的 42 個(gè)元素有序放在序列前 42 個(gè)位置
          partial_sort_copy(beg, end, destBeg, destEnd); // 排序輸入范圍中的元素,并將足夠多的已排序元素放到 destBeg 和 destEnd 所指示的序列中
          partial_sort_copy(beg, end, destBeg, destEnd, comp); // 排序輸入范圍中的元素,并將足夠多的已排序元素放到 destBeg 和 destEnd 所指示的序列中
          nth_element(beg, nth, end); // nth 是一個(gè)迭代器,指向輸入序列中第 n 大的元素。nth 之前的元素都小于等于它,而之后的元素都大于等于它
          nth_element(beg, nth, end, comp); // nth 是一個(gè)迭代器,指向輸入序列中第 n 大的元素。nth 之前的元素都小于等于它,而之后的元素都大于等于它
          1. 使用前向迭代器的重排算法。普通版本在輸入序列自身內(nèi)部重拍元素,_copy 版本完成重拍后寫(xiě)入到指定目的序列中,而不改變輸入序列
          remove(beg, end, val); // 通過(guò)用保留的元素覆蓋要?jiǎng)h除的元素實(shí)現(xiàn)刪除 ==val 的元素,返回一個(gè)指向最后一個(gè)刪除元素的尾后位置的迭代器
          remove_if(beg, end, unaryPred); // 通過(guò)用保留的元素覆蓋要?jiǎng)h除的元素實(shí)現(xiàn)刪除滿足 unaryPred 的元素,返回一個(gè)指向最后一個(gè)刪除元素的尾后位置的迭代器
          remove_copy(beg, end, dest, val); // 通過(guò)用保留的元素覆蓋要?jiǎng)h除的元素實(shí)現(xiàn)刪除 ==val 的元素,返回一個(gè)指向最后一個(gè)刪除元素的尾后位置的迭代器
          remove_copy_if(beg, end, dest, unaryPred); // 通過(guò)用保留的元素覆蓋要?jiǎng)h除的元素實(shí)現(xiàn)刪除滿足 unaryPred 的元素,返回一個(gè)指向最后一個(gè)刪除元素的尾后位置的迭代器
          unique(beg, end); // 通過(guò)對(duì)覆蓋相鄰的重復(fù)元素(用 == 確定是否相同)實(shí)現(xiàn)重排序列。返回一個(gè)迭代器,指向不重復(fù)元素的尾后位置
          unique (beg, end, binaryPred); // 通過(guò)對(duì)覆蓋相鄰的重復(fù)元素(用 binaryPred 確定是否相同)實(shí)現(xiàn)重排序列。返回一個(gè)迭代器,指向不重復(fù)元素的尾后位置
          unique_copy(beg, end, dest); // 通過(guò)對(duì)覆蓋相鄰的重復(fù)元素(用 == 確定是否相同)實(shí)現(xiàn)重排序列。返回一個(gè)迭代器,指向不重復(fù)元素的尾后位置
          unique_copy_if(beg, end, dest, binaryPred); // 通過(guò)對(duì)覆蓋相鄰的重復(fù)元素(用 binaryPred 確定是否相同)實(shí)現(xiàn)重排序列。返回一個(gè)迭代器,指向不重復(fù)元素的尾后位置
          rotate(beg, mid, end); // 圍繞 mid 指向的元素進(jìn)行元素轉(zhuǎn)動(dòng)。元素 mid 成為為首元素,隨后是 mid+1 到到 end 之前的元素,再接著是 beg 到 mid 之前的元素。返回一個(gè)迭代器,指向原來(lái)在 beg 位置的元素
          rotate_copy(beg, mid, end, dest); // 圍繞 mid 指向的元素進(jìn)行元素轉(zhuǎn)動(dòng)。元素 mid 成為為首元素,隨后是 mid+1 到到 end 之前的元素,再接著是 beg 到 mid 之前的元素。返回一個(gè)迭代器,指向原來(lái)在 beg 位置的元素
          1. 使用雙向迭代器的重排算法
          reverse(beg, end); // 翻轉(zhuǎn)序列中的元素,返回 void
          reverse_copy(beg, end, dest);; // 翻轉(zhuǎn)序列中的元素,返回一個(gè)迭代器,指向拷貝到目的序列的元素的尾后位置
          1. 使用隨機(jī)訪問(wèn)迭代器的重排算法
          random_shuffle(beg, end); // 混洗輸入序列中的元素,返回 void
          random_shuffle(beg, end, rand); // 混洗輸入序列中的元素,rand 接受一個(gè)正整數(shù)的隨機(jī)對(duì)象,返回 void
          shuffle(beg, end, Uniform_rand); // 混洗輸入序列中的元素,Uniform_rand 必須滿足均勻分布隨機(jī)數(shù)生成器的要求,返回 void
          1. 最小值和最大值
          min(val1, va12); // 返回 val1 和 val2 中的最小值,兩個(gè)實(shí)參的類型必須完全一致。參數(shù)和返回類型都是 const的引引用,意味著對(duì)象不會(huì)被拷貝。下略
          min(val1, val2, comp);
          min(init_list);
          min(init_list, comp);
          max(val1, val2);
          max(val1, val2, comp);
          max(init_list);
          max(init_list, comp);
          minmax(val1, val2); // 返回一個(gè) pair,其 first 成員為提供的值中的較小者,second 成員為較大者。下略
          minmax(vall, val2, comp);
          minmax(init_list);
          minmax(init_list, comp);
          min_element(beg, end); // 返回指向輸入序列中最小元素的迭代器
          min_element(beg, end, comp); // 返回指向輸入序列中最小元素的迭代器
          max_element(beg, end); // 返回指向輸入序列中最大元素的迭代器
          max_element(beg, end, comp); // 返回指向輸入序列中最大元素的迭代器
          minmax_element(beg, end); // 返回一個(gè) pair,其中 first 成員為最小元素,second 成員為最大元素
          minmax_element(beg, end, comp); // 返回一個(gè) pair,其中 first 成員為最小元素,second 成員為最大元素
          1. 字典序比較,根據(jù)第一對(duì)不相等的元素的相對(duì)大小來(lái)返回結(jié)果。如果第一個(gè)序列在字典序中小于第二個(gè)序列,則返回 true。否則,返回 fa1se。如果個(gè)序列比另一個(gè)短,且所有元素都與較長(zhǎng)序列的對(duì)應(yīng)元素相等,則較短序列在字典序中更小。如果序列長(zhǎng)度相等,且對(duì)應(yīng)元素都相等,則在字典序中任何一個(gè)都不大于另外一個(gè)。
          lexicographical_compare(beg1, end1, beg2, end2);
          lexicographical_compare(beg1, end1, beg2, end2, comp);

          5 如何選擇合適的容器

          需要根據(jù)容器的特點(diǎn)和使用場(chǎng)景而定,可能滿足需求的不止一種容器。

          按是否有序關(guān)聯(lián)性分為:

          1. 序列式容器:array、vector、deque、list 和 forward_list;
          2. 關(guān)聯(lián)式容器:map、multimap、set 和 multiset;
          3. 無(wú)序關(guān)聯(lián)式容器:unordered_map、unordered_multimap、unordered_set 和 unordered_multiset;
          4. 容器適配器:stack、queue 和 priority_queue。 根據(jù)容器底層采用是否是連續(xù)的存儲(chǔ)空間分為:
          5. 采用連續(xù)的存儲(chǔ)空間:array、vector、deque;
          6. 采用分散的存儲(chǔ)空間:list、forward_list 以及所有的關(guān)聯(lián)式容器和哈希容器。

          注意:deque 容器歸為使用連續(xù)存儲(chǔ)空間的這一類,是存在爭(zhēng)議的。因?yàn)?deque 容器底層采用一段一段的連續(xù)空間存儲(chǔ)元素,但是各段存儲(chǔ)空間之間并不一定是緊挨著的。

          選擇容器流程圖(來(lái)源于網(wǎng)絡(luò))

          選擇容器的幾點(diǎn)建議:

          • 如果只是存儲(chǔ)確定或不確定的對(duì)象,而不去刪除它們,可以選用vector。就是因?yàn)関ector是數(shù)組的替代品,是連續(xù)內(nèi)存的,不適合頻繁的刪除。
          • 如果在容器的指定位置插入新元素,則只能選擇序列式容器,不選擇關(guān)聯(lián)式容器和哈希容器。
          • 如果頻繁的插入和刪除,可以選用list(鏈表),內(nèi)存不是連續(xù)的,可以方便的插入和刪除,但是不支持索引訪問(wèn)。
          • 數(shù)據(jù)量很大,不在乎他們的排序,要求效率,對(duì)容器中各元素的存儲(chǔ)位置沒(méi)有要求,可以考慮使用哈希容器,反之就要避免使用哈希容器。
          • 如果是隨機(jī)訪問(wèn)迭代器,選擇 array、vector、deque。
          • 如果是雙向迭代器,考慮 list 序列式容器以及所有的關(guān)聯(lián)式容器。
          • 如果必須是前向迭代器,考慮 forward_list序列式容器以及所有的哈希容器。
          • 如果插入或刪除操作時(shí),容器中的其它元素不移動(dòng)?選擇不是array、vector、deque的其它容器。

          6 面試中常出現(xiàn)的STL問(wèn)題

          1. vector的底層原理

          vector底層是一個(gè)動(dòng)態(tài)數(shù)組,包含三個(gè)迭代器,start和finish之間是已經(jīng)被使用的空間范圍,end_of_storage是整塊連續(xù)空間包括備用空間的尾部。

          當(dāng)空間不夠裝下數(shù)據(jù)(vec.push_back(val))時(shí),會(huì)自動(dòng)申請(qǐng)另一片更大的空間(1.5倍或者2倍),然后把原來(lái)的數(shù)據(jù)拷貝到新的內(nèi)存空間,接著釋放原來(lái)的那片空間【vector內(nèi)存增長(zhǎng)機(jī)制】。

          當(dāng)釋放或者刪除(vec.clear())里面的數(shù)據(jù)時(shí),其存儲(chǔ)空間不釋放,僅僅是清空了里面的數(shù)據(jù)。

          因此,對(duì)vector的任何操作一旦引起了空間的重新配置,指向原vector的所有迭代器會(huì)都失效了

          1. vector中的reserve和resize的區(qū)別
          • reserve是直接擴(kuò)充到已經(jīng)確定的大小,可以減少多次開(kāi)辟、釋放空間的問(wèn)題(優(yōu)化push_back),就可以提高效率,其次還可以減少多次要拷貝數(shù)據(jù)的問(wèn)題。reserve只是保證vector中的空間大小(capacity)最少達(dá)到參數(shù)所指定的大小n。reserve()只有一個(gè)參數(shù)。
          • resize()可以改變有效空間的大小,也有改變默認(rèn)值的功能。capacity的大小也會(huì)隨著改變。resize()可以有多個(gè)參數(shù)。
          1. vector中的size和capacity的區(qū)別
          • size表示當(dāng)前vector中有多少個(gè)元素(finish - start);
          • capacity函數(shù)則表示它已經(jīng)分配的內(nèi)存中可以容納多少元素(end_of_storage - start);
          1. vector中erase方法與algorithn中的remove方法區(qū)別
          • vector中erase方法真正刪除了元素,迭代器不能訪問(wèn)了
          • remove只是簡(jiǎn)單地將元素移到了容器的最后面,迭代器還是可以訪問(wèn)到。因?yàn)閍lgorithm通過(guò)迭代器進(jìn)行操作,不知道容器的內(nèi)部結(jié)構(gòu),所以無(wú)法進(jìn)行真正的刪除。
          1. vector迭代器失效的情況
          • 當(dāng)插入一個(gè)元素到vector中,由于引起了內(nèi)存重新分配,所以指向原內(nèi)存的迭代器全部失效。
          • 當(dāng)刪除容器中一個(gè)元素后,該迭代器所指向的元素已經(jīng)被刪除,那么也造成迭代器失效。erase方法會(huì)返回下一個(gè)有效的迭代器,所以當(dāng)我們要?jiǎng)h除某個(gè)元素時(shí),需要it=vec.erase(it);。
          1. 正確釋放vector的內(nèi)存(clear(), swap(), shrink_to_fit())
          • vec.clear():清空內(nèi)容,但是不釋放內(nèi)存。
          • vector<int>().swap(vec):清空內(nèi)容,且釋放內(nèi)存,想得到一個(gè)全新的vector。
          • vec.shrink_to_fit():請(qǐng)求容器降低其capacity和size匹配。
          • vec.clear();vec.shrink_to_fit();:清空內(nèi)容,且釋放內(nèi)存。
          1. list的底層原理
          • ist的底層是一個(gè)雙向鏈表,使用鏈表存儲(chǔ)數(shù)據(jù),并不會(huì)將它們存儲(chǔ)到一整塊連續(xù)的內(nèi)存空間中。恰恰相反,各元素占用的存儲(chǔ)空間(又稱為節(jié)點(diǎn))是獨(dú)立的、分散的,它們之間的線性關(guān)系通過(guò)指針來(lái)維持,每次插入或刪除一個(gè)元素,就配置或釋放一個(gè)元素空間。
          • list不支持隨機(jī)存取,如果需要大量的插入和刪除,而不關(guān)心隨即存取
          1. 什么情況下用vector,什么情況下用list,什么情況下用deque
          • vector可以隨機(jī)存儲(chǔ)元素(即可以通過(guò)公式直接計(jì)算出元素地址,而不需要挨個(gè)查找),但在非尾部插入刪除數(shù)據(jù)時(shí),效率很低,適合對(duì)象簡(jiǎn)單,對(duì)象數(shù)量變化不大,隨機(jī)訪問(wèn)頻繁。除非必要,我們盡可能選擇使用vector而非deque,因?yàn)閐eque的迭代器比vector迭代器復(fù)雜很多。
          • list不支持隨機(jī)存儲(chǔ),適用于對(duì)象大,對(duì)象數(shù)量變化頻繁,插入和刪除頻繁,比如寫(xiě)多讀少的場(chǎng)景。
          • 需要從首尾兩端進(jìn)行插入或刪除操作的時(shí)候需要選擇deque。
          1. priority_queue的底層原理
          • priority_queue:優(yōu)先隊(duì)列,其底層是用堆來(lái)實(shí)現(xiàn)的。在優(yōu)先隊(duì)列中,隊(duì)首元素一定是當(dāng)前隊(duì)列中優(yōu)先級(jí)最高的那一個(gè)。
          1. map 、set、multiset、multimap的底層原理

          map 、set、multiset、multimap的底層實(shí)現(xiàn)都是紅黑樹(shù),epoll模型的底層數(shù)據(jù)結(jié)構(gòu)也是紅黑樹(shù),linux系統(tǒng)中CFS進(jìn)程調(diào)度算法,也用到紅黑樹(shù)。

          紅黑樹(shù)的特性:

          • 每個(gè)結(jié)點(diǎn)或是紅色或是黑色;
          • 根結(jié)點(diǎn)是黑色;
          • 每個(gè)葉結(jié)點(diǎn)是黑的;
          • 如果一個(gè)結(jié)點(diǎn)是紅的,則它的兩個(gè)兒子均是黑色;
          • 每個(gè)結(jié)點(diǎn)到其子孫結(jié)點(diǎn)的所有路徑上包含相同數(shù)目的黑色結(jié)點(diǎn)。
          1. 為何map和set的插入刪除效率比其他序列容器高
          • 因?yàn)椴恍枰獌?nèi)存拷貝和內(nèi)存移動(dòng)
          1. 為何map和set每次Insert之后,以前保存的iterator不會(huì)失效?
          • 因?yàn)椴迦氩僮髦皇墙Y(jié)點(diǎn)指針換來(lái)?yè)Q去,結(jié)點(diǎn)內(nèi)存沒(méi)有改變。而iterator就像指向結(jié)點(diǎn)的指針,內(nèi)存沒(méi)變,指向內(nèi)存的指針也不會(huì)變。
          1. 當(dāng)數(shù)據(jù)元素增多時(shí)(從10000到20000),map的set的查找速度會(huì)怎樣變化?
          • RB-TREE用二分查找法,時(shí)間復(fù)雜度為logn,所以從10000增到20000時(shí),查找次數(shù)從log10000=14次到log20000=15次,多了1次而已。
          1. map 、set、multiset、multimap的特點(diǎn)
          • set和multiset會(huì)根據(jù)特定的排序準(zhǔn)則自動(dòng)將元素排序,set中元素不允許重復(fù),multiset可以重復(fù)。
          • map和multimap將key和value組成的pair作為元素,根據(jù)key的排序準(zhǔn)則自動(dòng)將元素排序(因?yàn)榧t黑樹(shù)也是二叉搜索樹(shù),所以map默認(rèn)是按key排序的),map中元素的key不允許重復(fù),multimap可以重復(fù)。
          • map和set的增刪改查速度為都是logn,是比較高效的。
          1. 為何map和set的插入刪除效率比其他序列容器高,而且每次insert之后,以前保存的iterator不會(huì)失效?
          • 存儲(chǔ)的是結(jié)點(diǎn),不需要內(nèi)存拷貝和內(nèi)存移動(dòng)。
          • 插入操作只是結(jié)點(diǎn)指針換來(lái)?yè)Q去,結(jié)點(diǎn)內(nèi)存沒(méi)有改變。而iterator就像指向結(jié)點(diǎn)的指針,內(nèi)存沒(méi)變,指向內(nèi)存的指針也不會(huì)變。
          1. 為何map和set不能像vector一樣有個(gè)reserve函數(shù)來(lái)預(yù)分配數(shù)據(jù)?
          • 在map和set內(nèi)部存儲(chǔ)的已經(jīng)不是元素本身了,而是包含元素的結(jié)點(diǎn)。也就是說(shuō)map內(nèi)部使用的Alloc并不是map<Key, Data, Compare, Alloc>聲明的時(shí)候從參數(shù)中傳入的Alloc。
          1. set的底層實(shí)現(xiàn)實(shí)現(xiàn)為什么不用哈希表而使用紅黑樹(shù)?
          • set中元素是經(jīng)過(guò)排序的,紅黑樹(shù)也是有序的,哈希是無(wú)序的
          • 如果只是單純的查找元素的話,那么肯定要選哈希表了,因?yàn)楣1碓诘淖詈貌檎視r(shí)間復(fù)雜度為O(1),并且如果用到set中那么查找時(shí)間復(fù)雜度的一直是O(1),因?yàn)閟et中是不允許有元素重復(fù)的。而紅黑樹(shù)的查找時(shí)間復(fù)雜度為O(lgn)
          1. hash_map與map的區(qū)別?什么時(shí)候用hash_map,什么時(shí)候用map? 構(gòu)造函數(shù):hash_map需要hash function和等于函數(shù),而map需要比較函數(shù)(大于或小于)。

          存儲(chǔ)結(jié)構(gòu):hash_map以hashtable為底層,而map以RB-TREE為底層。

          總的說(shuō)來(lái),hash_map查找速度比map快,而且查找速度基本和數(shù)據(jù)量大小無(wú)關(guān),屬于常數(shù)級(jí)別。而map的查找速度是logn級(jí)別。但不一定常數(shù)就比log小,而且hash_map還有hash function耗時(shí)。

          如果考慮效率,特別當(dāng)元素達(dá)到一定數(shù)量級(jí)時(shí),用hash_map。

          考慮內(nèi)存,或者元素?cái)?shù)量較少時(shí),用map。

          1. 迭代器失效的問(wèn)題

          插入操作:

          • 對(duì)于vector和string,如果容器內(nèi)存被重新分配,iterators,pointers,references失效;如果沒(méi)有重新分配,那么插入點(diǎn)之前的iterator有效,插入點(diǎn)之后的iterator失效;
          • 對(duì)于deque,如果插入點(diǎn)位于除front和back的其它位置,iterators,pointers,references失效;當(dāng)我們插入元素到front和back時(shí),deque的迭代器失效,但reference和pointers有效;
          • 對(duì)于list和forward_list,所有的iterator,pointer和refercnce有效。

          刪除操作:

          • 對(duì)于vector和string,刪除點(diǎn)之前的iterators,pointers,references有效;off-the-end迭代器總是失效的;
          • 對(duì)于deque,如果刪除點(diǎn)位于除front和back的其它位置,iterators,pointers,references失效;當(dāng)我們插入元素到front和back時(shí),off-the-end失效,其他的iterators,pointers,references有效;
          • 對(duì)于list和forward_list,所有的iterator,pointer和refercnce有效。
          • 對(duì)于關(guān)聯(lián)容器map來(lái)說(shuō),如果某一個(gè)元素已經(jīng)被刪除,那么其對(duì)應(yīng)的迭代器就失效了,不應(yīng)該再被使用,否則會(huì)導(dǎo)致程序無(wú)定義的行為。
          1. 線程不安全的情況
          • 在對(duì)同一個(gè)容器進(jìn)行多線程的讀寫(xiě)、寫(xiě)操作時(shí);
          • 在每次調(diào)用容器的成員函數(shù)期間都要鎖定該容器;
          • 在每個(gè)容器返回的迭代器(例如通過(guò)調(diào)用begin或end)的生存期之內(nèi)都要鎖定該容器;
          • 在每個(gè)在容器上調(diào)用的算法執(zhí)行期間鎖定該容器。

          參考資料

          http://www.cplusplus.com/reference/stl/ https://blog.csdn.net/qq_23350817/article/details/87930715 https://blog.csdn.net/bizhu12/article/details/6769976 http://c.biancheng.net/view/7385.htmlhttps://blog.csdn.net/daaikuaichuan/article/details/80717222


          :內(nèi)存泄露是什么意思?如何檢測(cè)與避免內(nèi)存泄漏?(提問(wèn)概率:★★★★)

          . 引入Three.js庫(kù)

          如果使用npm,可以通過(guò)以下命令安裝Three.js:

          npm install three

          然后在你的JavaScript文件中引入它:

          import * as THREE from 'three';

          如果直接在網(wǎng)頁(yè)中使用,可以通過(guò)<script>標(biāo)簽引入:

          <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>

          2. 創(chuàng)建場(chǎng)景、相機(jī)和渲染器

          // 創(chuàng)建一個(gè)場(chǎng)景
          const scene = new THREE.Scene();
          
          // 創(chuàng)建一個(gè)相機(jī),設(shè)置透視投影
          const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
          
          // 創(chuàng)建一個(gè)WebGL渲染器
          const renderer = new THREE.WebGLRenderer();
          renderer.setSize(window.innerWidth, window.innerHeight);
          document.body.appendChild(renderer.domElement); // 將渲染器的DOM元素添加到頁(yè)面中

          3. 設(shè)置燈光

          // 添加環(huán)境光
          const ambientLight = new THREE.AmbientLight(0xffffff, 0.4);
          scene.add(ambientLight);
          
          // 添加一個(gè)點(diǎn)光源
          const pointLight = new THREE.PointLight(0xffffff, 0.8);
          pointLight.position.set(5, 5, 5);
          scene.add(pointLight);

          4. 使用STLLoader加載模型

          Three.js提供了STLLoader來(lái)加載.stl文件。確保你已經(jīng)引入了STLLoader模塊。

          // 創(chuàng)建STLLoader實(shí)例
          const stlLoader = new THREE.STLLoader();
          
          // 異步加載.stl文件
          stlLoader.load(
              'path/to/your/model.stl', // 替換為你的.stl文件路徑
              function (geometry) {
                  // 創(chuàng)建材質(zhì)
                  const material = new THREE.MeshPhongMaterial({ color: 0x00ff00, specular: 0xffffff, shininess: 30 });
                  // 創(chuàng)建網(wǎng)格(mesh)并添加到場(chǎng)景中
                  const stlMesh = new THREE.Mesh(geometry, material);
                  scene.add(stlMesh);
              },
              function (xhr) {
                  // 可以在這里添加加載進(jìn)度的邏輯
              },
              function (error) {
                  // 可以在這里添加錯(cuò)誤處理的邏輯
              }
          );

          5. 添加控制器

          使用OrbitControls允許用戶與3D模型交互。

          // 創(chuàng)建控制器
          const controls = new THREE.OrbitControls(camera, renderer.domElement);
          controls.target.set(0, 0, 0); // 設(shè)置控制器的目標(biāo)點(diǎn)
          controls.update(); // 更新控制器

          6. 動(dòng)畫(huà)循環(huán)

          創(chuàng)建一個(gè)動(dòng)畫(huà)循環(huán),用于連續(xù)渲染場(chǎng)景。

          function animate() {
              // 更新控制器
              controls.update();
          
              // 渲染場(chǎng)景
              renderer.render(scene, camera);
          
              // 使用requestAnimationFrame創(chuàng)建一個(gè)循環(huán)
              requestAnimationFrame(animate);
          }
          
          // 開(kāi)始動(dòng)畫(huà)循環(huán)
          animate();

          7. 調(diào)整相機(jī)位置

          為了更好地查看模型,你可能需要調(diào)整相機(jī)的位置。

          camera.position.set(0, 50, 100); // 可以調(diào)整這些值
          camera.lookAt(scene.position); // 使相機(jī)指向場(chǎng)景的中心

          8. 響應(yīng)窗口大小變化

          為了確保渲染器適應(yīng)不同窗口大小,添加以下事件監(jiān)聽(tīng)器。

          window.addEventListener('resize', () => {
              camera.aspect = window.innerWidth / window.innerHeight;
              camera.updateProjectionMatrix();
              renderer.setSize(window.innerWidth, window.innerHeight);
          });

          將上述代碼整合到一個(gè)HTML頁(yè)面中,并確保替換path/to/your/model.stl為你的.stl文件的實(shí)際路徑。這樣,你就能夠在網(wǎng)頁(yè)上渲染.stl文件了。


          主站蜘蛛池模板: 亚洲国产精品一区二区第一页| 精品日本一区二区三区在线观看| 无码日韩AV一区二区三区| 中文字幕在线观看一区二区 | 相泽南亚洲一区二区在线播放 | 成人一区专区在线观看| 亚洲一区精品中文字幕| 国产亚洲情侣一区二区无| 精品一区二区91| 国产成人高清亚洲一区久久| 无码少妇丰满熟妇一区二区| 亚拍精品一区二区三区| 无码精品黑人一区二区三区| 日本大香伊一区二区三区| 综合久久久久久中文字幕亚洲国产国产综合一区首 | 一区二区高清在线| 日本一区二区三区精品视频| 日本韩国一区二区三区| 在线免费视频一区| 尤物精品视频一区二区三区| 日韩视频在线一区| 日本高清无卡码一区二区久久 | 国产精品一区二区av不卡| 无码人妻AⅤ一区二区三区水密桃| 国产精品一区二区在线观看| 韩国精品一区视频在线播放| 午夜爽爽性刺激一区二区视频| 国产伦精品一区二区三区不卡| 交换国产精品视频一区| 亚洲熟妇无码一区二区三区| 亚洲熟女www一区二区三区| 精品国产精品久久一区免费式| 欧洲精品码一区二区三区| 四虎精品亚洲一区二区三区 | 精品一区二区三区东京热| 97一区二区三区四区久久| 无码人妻aⅴ一区二区三区有奶水| 精品国产日韩亚洲一区91| 人妻体内射精一区二区| 国产成人无码一区二区三区| 精品欧洲AV无码一区二区男男 |