STL作為C++標(biāo)準(zhǔn)的重要一部分,在很大程序上改變了C++程序的結(jié)構(gòu)與使用方式,STL大大提高了軟件開發(fā)的效率,降低了開發(fā)成本成維護(hù)成本,降低了開發(fā)時間與維護(hù)時間,提高了軟件穩(wěn)定性與可移植性,隨著軟件行業(yè)的迅速發(fā)展, STL在C++程序中得到了廣泛的應(yīng)用。
上一篇內(nèi)容介紹了STL提供了六大組件,彼此之間可以組合套用,這六大組件分別是:容器、算法、迭代器、仿函數(shù)、適配器(配接器)、空間配置器。我們將詳細(xì)介紹其中三個,為接下來的學(xué)習(xí)打好基礎(chǔ)。
一、容器
容器,置物之所也。 研究數(shù)據(jù)的特定排列方式,以利于搜索或排序或其他特殊目的,這一門學(xué)科我們稱為數(shù)據(jù)結(jié)構(gòu)。大學(xué)信息類相關(guān)專業(yè)里面,與編程最有直接關(guān)系的學(xué)科,首推數(shù)據(jù)結(jié)構(gòu)與算法。幾乎可以說,任何特定的數(shù)據(jù)結(jié)構(gòu)都是為了實現(xiàn)某種特定的算法。STL容器就是將運(yùn)用最廣泛的一些數(shù)據(jù)結(jié)構(gòu)實現(xiàn)出來。 常用的數(shù)據(jù)結(jié)構(gòu):數(shù)組(array),鏈表(list),tree(樹),棧(stack),隊列(queue),集合(set),映射表(map),根據(jù)數(shù)據(jù)在容器中的排列特性,這些數(shù)據(jù)分為序列式容器和關(guān)聯(lián)式容器兩種。 序列式容器強(qiáng)調(diào)值的排序,序列式容器中的每個元素均有固定的位置,除非用刪除或插入的操作改變這個位置。Vector容器、Deque容器、List容器等。 關(guān)聯(lián)式容器是非線性的樹結(jié)構(gòu),更準(zhǔn)確的說是二叉樹結(jié)構(gòu)。各元素之間沒有嚴(yán)格的物理上的順序關(guān)系,也就是說元素在容器中并沒有保存元素置入容器時的邏輯順序。關(guān)聯(lián)式容器另一個顯著特點(diǎn)是:在值中選擇一個值作為關(guān)鍵字key,這個關(guān)鍵字對值起到索引的作用,方便查找。
總結(jié):針對于STL通用的容器分為三類:順序性容器、關(guān)聯(lián)式容器和容器適配器。
順序性容器是一種各元素之間有順序關(guān)系的線性表,除非用插入、刪除的操作改變位置,否則元素在容器中的位置與元素本身沒有關(guān)系,只與操作的時間和地點(diǎn)相關(guān)(時間:什么時候添加的元素,地點(diǎn):元素添加到了那個位置);常用的順序性容器有:vector、deque、list。
關(guān)聯(lián)式容器是采用非線性的樹結(jié)構(gòu)來存儲數(shù)據(jù),樹形結(jié)構(gòu)的底層采用的是平衡二叉搜索樹:RB-Tree(紅黑樹),哈希結(jié)構(gòu)底層實現(xiàn)為哈希表,容器內(nèi)的各元素沒有嚴(yán)格意義上的物理內(nèi)存上的順序關(guān)系。此外,關(guān)聯(lián)式容器是采用key-value形式,在樹形結(jié)構(gòu)中保存key值,然后通過哈希表訪問其value值,而順序性容器只能保存一種類型的值。常用的關(guān)聯(lián)式容器有:set和multiset、map和multimap。
容器適配器其實就是將已有的容器結(jié)構(gòu)類型,改變一下接口,使其實現(xiàn)特有的功能,比如stack容器,其實就是deque容器改變接口實現(xiàn)的,你也可以使用deque容器當(dāng)做stack容器使用,但是deque容器接口過多,為了避免誤操作,破壞了stack容器的性質(zhì),就使用容器適配器。常用的關(guān)聯(lián)式容器有:stack,queue和priority_queue。stack和queue默認(rèn)是基于deque實現(xiàn),priority_queue默認(rèn)是基于vector實現(xiàn)。
最后容器可以嵌套容器,如下圖所示。
二、算法
算法,問題之解法也。以有限的步驟,解決邏輯或數(shù)學(xué)上的問題,這一門學(xué)科我們叫做算法(Algorithms).廣義而言,我們所編寫的每個程序都是一個算法,其中的每個函數(shù)也都是一個算法,畢竟它們都是用來解決或大或小的邏輯問題或數(shù)學(xué)問題。STL收錄的算法經(jīng)過了數(shù)學(xué)上的效能分析與證明,是極具復(fù)用價值的,包括常用的排序,查找等等。特定的算法往往搭配特定的數(shù)據(jù)結(jié)構(gòu),算法與數(shù)據(jù)結(jié)構(gòu)相輔相成。
算法分為:質(zhì)變算法和非質(zhì)變算法。
質(zhì)變算法:是指運(yùn)算過程中會更改區(qū)間內(nèi)的元素的內(nèi)容。例如拷貝,替換,刪除等等 非質(zhì)變算法:是指運(yùn)算過程中不會更改區(qū)間內(nèi)的元素內(nèi)容,例如查找、計數(shù)、遍歷、尋找極值等等
總結(jié):針對于STL常用的算法有:查找算法、排序和通用算法、刪除和替換算法、排列組合算法、數(shù)值算法、生成和異變算法、關(guān)系算法、集合算法、堆算法等。(具體的算法將在接下來章節(jié)中介紹)
三、迭代器
迭代器(iterator)是一種抽象的設(shè)計概念,現(xiàn)實程序語言中并沒有直接對應(yīng)于這個概念的實物。在對市面上23種設(shè)計模式的完整描述中,其中iterator模式定義如下:提供一種方法,使之能夠依序?qū)ぴL某個容器所含的各個元素,而又無需暴露該容器的內(nèi)部表示方式。
迭代器的設(shè)計思維-STL的關(guān)鍵所在,STL的中心思想在于將容器(container)和算法(algorithms)分開,彼此獨(dú)立設(shè)計,最后再一貼膠著劑將他們撮合在一起。從技術(shù)角度來看,容器和算法的泛型化并不困難,c++的class template和function template可分別達(dá)到目標(biāo),如果設(shè)計出兩這個之間的良好的膠著劑,才是大難題。
迭代器的種類:
使用案例:
#include<iostream> #include<vector> #include<algorithm> using namespace std; //STL 中的容器 算法 迭代器 void test01(){
vector<int> v; //STL 中的標(biāo)準(zhǔn)容器之一 :動態(tài)數(shù)組
v.push_back(1); //vector 容器提供的插入數(shù)據(jù)的方法
v.push_back(3);
v.push_back(7); //迭代器
vector<int>::iterator pStart = v.begin(); //vector 容器提供了 begin()方法 返回 指向第一個元素的迭代器
vector<int>::iterator pEnd = v.end(); //vector 容器提供了 end()方法 返回指向最后 一個元素下一個位置的迭代器 //通過迭代器遍歷
while (pStart != pEnd){
cout << *pStart << " ";
pStart++; }
cout << endl; }//STL 容器不單單可以存儲基礎(chǔ)數(shù)據(jù)類型,也可以存儲類對象 class Teacher {
public:
Teacher(int age) :age(age){};
~Teacher(){};
public:
int age; };void test02(){
vector<Teacher> v; //存儲 Teacher 類型數(shù)據(jù)的容器
Teacher t1(10), t2(20), t3(30);
v.push_back(t1);
v.push_back(t2);
v.push_back(t3);
vector<Teacher>::iterator pStart = v.begin();
vector<Teacher>::iterator pEnd = v.end(); //通過迭代器遍歷
while (pStart != pEnd)
{
cout << pStart->age << " ";
pStart++;
}
cout << endl; }//存儲 Teacher 類型指針 void test03(){
vector<Teacher*> v; //存儲 Teacher 類型指針
Teacher* t1 = new Teacher(10);
Teacher* t2 = new Teacher(20);
Teacher* t3 = new Teacher(30);
v.push_back(t1);
v.push_back(t2);
v.push_back(t3); //拿到容器迭代器
vector<Teacher*>::iterator pStart = v.begin();
vector<Teacher*>::iterator pEnd = v.end();
//通過迭代器遍歷
while (pStart != pEnd)
{
cout << (*pStart)->age << " ";
pStart++;
}
cout << endl;
}
//容器嵌套容器 難點(diǎn)(不理解,可以跳過)
void test04()
{
vector< vector<int> > v;
vector<int>v1;
vector<int>v2;
vector<int>v3;
for (int i = 0; i < 5;i++)
{
v1.push_back(i);
v2.push_back(i * 10);
v3.push_back(i * 100);
}
v.push_back(v1);
v.push_back(v2);
v.push_back(v3);
for (vector< vector<int> >::iterator it = v.begin(); it != v.end();it++)
{
for (vector<int>::iterator subIt = (*it).begin(); subIt != (*it).end(); subIt ++)
{
cout << *subIt << " ";
}
cout << endl;
}
}
int main()
{
//test01();
//test02();
//test03();
test04();
system("pause");
return EXIT_SUCCESS;
}
更多關(guān)于“物聯(lián)網(wǎng)培訓(xùn)”的問題,歡迎咨詢千鋒教育在線名師。千鋒教育多年辦學(xué),課程大綱緊跟企業(yè)需求,更科學(xué)更嚴(yán)謹(jǐn),每年培養(yǎng)泛IT人才近2萬人。不論你是零基礎(chǔ)還是想提升,都可以找到適合的班型,千鋒教育隨時歡迎你來試聽。