一、簡介 1.起源StandardTemplateLibrary StandardTemplateLibrary:標準模板庫是一個基于泛型的C++類模板庫由AlexanderStepanov于1994年開發(fā) 其目的是為了提供一致通用和高效的數(shù)據(jù)結(jié)構(gòu)和算法,,同時不限制用戶所處理的數(shù)據(jù)類型和編程范式,。STL的原型最初由AndrewKoenig和其它C++專家小組進行設(shè)計并在1995年C++標準委員會的推薦下成為C++標準庫的一部分。 2.發(fā)展歷程 STL的發(fā)展經(jīng)過了一系列的演化過程,。最初是由AlexanderStepanov開發(fā)的SGI-STL(SiliconGraphicsSTL)版本,,后來被許多廠商和開源社區(qū)所采用并發(fā)揚光大。出于對SGI擁有版權(quán)的限制后來形成了多個同源的STL版本,,如STLport,、ApacheSTL等。隨著C++標準的不斷發(fā)展變化,,STL自2000年起多次進行了升級,,包括C++03的修訂版和C++11、C++14,、C++17等標準,。 3.組成部分與內(nèi)部實現(xiàn)原理 STL包含迭代器、容器,、算法,、仿函數(shù)和適配器等五個主要部分。 容器可分為序列式和關(guān)聯(lián)式兩種,,算法主要是對容器中元素進行操作和處理,,仿函數(shù)則是封裝了自定義函數(shù)的類模板。 內(nèi)部實現(xiàn)主要基于模板和泛型編程,,利用C++模板的特性將數(shù)據(jù)類型和算法進行解耦,,使得STL可適用于各種數(shù)據(jù)類型和編程范式,。 下面通過具體的代碼實現(xiàn)來驗證STL強大能力: 使用vector容器存儲元素并使用for循環(huán)不斷向容器中壓入元素 使用transform算法將vector容器中的所有元素都擴大2倍 使用find算法查找vector容器中是否存在元素5若存在則將元素5修改為-5 最終輸出查找前后、變換前后的vector容器元素,,證明STL提供的容器和算法確實可以在效率和正確性上帶來極大的便利,。 ```cpp include include include usingnamespacestd; intmain{ //聲明一個vector容器 vectorvec; //將元素壓入vector容器 for(inti=0;i<10;i++){ vec.push_back(i); } //原始vector容器元素 for(autoi:vec){ cout< } cout< //將vector容器內(nèi)的所有元素*2 transform(vec.begin,vec.end,vec.begin,[](intelem){returnelem*2;}); //變換后的vector容器元素 for(autoi:vec){ cout< } cout< //查找vector容器中元素5的位置 autofind_it=find(vec.begin,vec.end,5); //如果找到,則將元素5修改為-5 if(find_it!=vec.end){ *find_it=-5; } //查找后的vector容器元素 for(autoi:vec){ cout< } cout< return0; } ##4.優(yōu)點和局限性 ###4.1優(yōu)點 STL采用了統(tǒng)一的模板式的編程方式,,具有代碼重用可移植性好高效性等優(yōu)點,。而且STL已經(jīng)成為C++標準庫的一部分也具有了代碼穩(wěn)定標準化易維護等特點。 ###4.2局限 局限性是對于一些復(fù)雜的數(shù)據(jù)結(jié)構(gòu)和算法有時會需要自定義容器和迭代器等部分,,并且STL的使用也需要一定的學(xué)習(xí)門檻和理解成本,。 總體來說優(yōu)點遠大于缺點,不僅提高了程序員的開發(fā)效率也推動了C++語言的廣泛應(yīng)用 #二,、容器 ##1.定義 C++STL中的容器是一種存儲多個元素的數(shù)據(jù)結(jié)構(gòu),,每個容器都有自己的特性和使用場景。 按照元素的存儲方式可以將其分為以下四種類型: -序列容器(sequencecontainer) -關(guān)聯(lián)容器(associativecontainer) -無序關(guān)聯(lián)容器(unorderedassociativecontainer) -容器適配器(containeradapter) ##2.序列容器 序列容器中的元素按照某個順序依次被存儲,,常見的幾種序列容器如下: ###2.1vector -容器特性:動態(tài)數(shù)組支持隨機訪問 -存儲結(jié)構(gòu):連續(xù)的內(nèi)存空間支持在末尾添加元素 -元素存取方法:使用下標`[]`或迭代器訪問 -使用場景:在需要大量的末尾添加元素以及隨機訪問元素的情況下使用 代碼實現(xiàn)如下: ```cpp #include #include usingnamespacestd; intmain{ //定義一個vector容器 vector //在vector末尾添加元素 vec.push_back(1);//序列號1 vec.push_back(2);//序列號2 vec.push_back(3);//序列號3 //輸出vector中的元素 for(autoi:vec){ cout< } cout< return0; } 2.2deque 容器特性:雙端隊列支持隨機訪問和在隊頭和隊尾添加和刪除元素 存儲結(jié)構(gòu):連續(xù)的內(nèi)存塊支持在末尾和頭部添加元素 元素存取方法:使用[]或者迭代器訪問,。 使用場景:當(dāng)需要在隊頭隊尾添加和刪除元素的時候使用。 代碼實現(xiàn)如下: #include 2.3list 容器特性:雙向鏈表不支持隨機訪問 存儲結(jié)構(gòu):雙向鏈表支持在任意位置添加或刪除元素 元素存取方法:只支持前向迭代器訪問 使用場景:當(dāng)需要在任意位置添加或刪除元素的時候使用 代碼實現(xiàn)如下: #include 2.4forward_list 容器特性:單向鏈表不支持反向遍歷 存儲結(jié)構(gòu):單向鏈表支持在任意位置添加或刪除元素 元素存取方法:只支持前向迭代器訪問 使用場景:當(dāng)需要在任意位置添加或刪除元素,,而且只需要單向遍歷容器的時候使用 代碼實現(xiàn)如下: #include 3.關(guān)聯(lián)容器 關(guān)聯(lián)容器中的元素是按照某種方式進行排序的,,因此支持基于排序的元素存儲和訪問。 常見的幾種關(guān)聯(lián)容器有: 3.1set與multiset 容器特性:基于紅黑樹的關(guān)聯(lián)容器,,元素按照從小到大的順序進行排序,,每個元素值都必須唯一,multiset可以存儲多個相同元素 存儲結(jié)構(gòu):內(nèi)部使用紅黑樹進行實現(xiàn),,支持查找、插入,、刪除元素 元素存取方法:只能通過迭代器訪問,,不支持隨機訪問 使用場景:當(dāng)需要存儲唯一元素,而且需要按照從小到大的順序進行排序的場景 代碼實現(xiàn)如下: #include 3.2map與multimap 容器特性:基于紅黑樹的關(guān)聯(lián)容器,,存儲元素為鍵值對(key-valuepair),,每個鍵值對的鍵都必須唯一,map只能存儲一個鍵值對,,multimap可以存儲多個相同的鍵值對 存儲結(jié)構(gòu):內(nèi)部使用紅黑樹進行實現(xiàn),,支持查找、插入,、刪除元素 元素存取方法:只能通過迭代器訪問,,不支持隨機訪問 使用場景:當(dāng)需要存儲唯一鍵值對,而且需要按照鍵進行排序的場景 代碼實現(xiàn)如下: #include 4.無序關(guān)聯(lián)容器 無序關(guān)聯(lián)容器中的元素是按照哈希表存儲的,,因此支持常數(shù)時間的查找,、插入和刪除操作,。 常見的幾種無序關(guān)聯(lián)容器有: 4.1unordered_set與unordered_multiset 容器特性:基于哈希表的關(guān)聯(lián)容器,元素?zé)o順序,,每個元素值都必須唯一,,unordered_multiset可以存儲多個相同元素 存儲結(jié)構(gòu):內(nèi)部使用哈希表進行實現(xiàn),支持常數(shù)時間的查找,、插入,、刪除元素 元素存取方法:只能通過迭代器訪問,不支持隨機訪問 使用場景:當(dāng)需要存儲唯一元素,,而且不需要按照順序進行排序的場景 代碼實現(xiàn)如下: #include 4.2unordered_mapun與ordered_multimap 容器特性:基于哈希表的關(guān)聯(lián)容器,,存儲元素為鍵值對(key-valuepair),每個鍵值對的鍵都必須唯一,,unordered_map只能存儲一個鍵值對,,unordered_multimap可以存儲多個相同的鍵值對 存儲結(jié)構(gòu):內(nèi)部使用哈希表進行實現(xiàn),支持常數(shù)時間的查找,、插入,、刪除元素 元素存取方法:只能通過迭代器訪問,不支持隨機訪問 使用場景:當(dāng)需要存儲唯一鍵值對,,而且不需要按照鍵進行排序的場景 代碼實現(xiàn)如下: #include 5.容器適配器 容器適配器是一種特殊的容器,,它們的底層實現(xiàn)可以基于其他容器完成。 常見的幾種容器適配器有: 5.1stack 容器特性:棧,,底層實現(xiàn)可以基于vector,、deque或list完成 存儲結(jié)構(gòu):可以使用vector、deque或list中的一種作為底層實現(xiàn) 元素存取方法:只支持棧頂元素的訪問和刪除 使用場景:當(dāng)需要實現(xiàn)棧結(jié)構(gòu)時,,使用stack容器適配器可以非常方便 代碼實現(xiàn)如下: #include 5.2queue 容器特性:隊列,,底層實現(xiàn)可以基于deque或list完成 存儲結(jié)構(gòu):可以使用deque或list作為底層實現(xiàn) 元素存取方法:只支持隊首元素和隊尾元素的訪問和刪除 使用場景:當(dāng)需要實現(xiàn)先進先出的數(shù)據(jù)結(jié)構(gòu)時,使用queue容器適配器可以非常方便 代碼實現(xiàn)如下: #include 5.3priority_queue 容器特性:優(yōu)先隊列,,底層實現(xiàn)可以基于vector或deque完成 存儲結(jié)構(gòu):可以使用vector或deque作為底層實現(xiàn) 元素存取方法:支持插入和訪問優(yōu)先級最高的元素,,不支持刪除特定元素 使用場景:當(dāng)需要根據(jù)優(yōu)先級存儲元素時,使用priority_queue容器適配器可以非常方便 代碼實現(xiàn)如下: #include 三,、迭代器 迭代器是ST中用來操作容器內(nèi)部元素的一種統(tǒng)一方式,,它將容器中元素的訪問和操作抽象出來,使得程序員可以使用一種統(tǒng)一的方式操作各種容器元素,。 1.1定義 迭代器是一種模板類型可以定義指向容器元素的指針,,通過重載運算符來實現(xiàn)對容器中元素的訪問、修改等操作,。 迭代器可以分為以下幾種: 輸入迭代器(inputiterator):支持從容器中讀取元素,,一旦讀取,就不能重復(fù)讀取 輸出迭代器(outputiterator):支持向容器中寫入元素,一旦寫入,,就不能重復(fù)寫入 前向迭代器(forwarditerator):支持讀寫,、前移操作,對容器進行單向遍歷 雙向迭代器(bidirectionaliterator):支持讀寫,、前移,、后移操作,對容器進行雙向遍歷 隨機訪問迭代器(randomaccessiterator):支持讀寫,、前移,、后移、加法,、減法,、下標等操作,對容器進行隨機訪問 1.2常見應(yīng)用 主要應(yīng)用場景是對容器內(nèi)部元素進行遍歷,、訪問,、操作等。STL中的算法函數(shù)和容器的成員函數(shù)都可以用迭代器實現(xiàn),,比如STL中的sort函數(shù),,要求傳入的容器必須是支持隨機訪問迭代器的。 迭代器的使用方法簡單只需要使用迭代器訪問容器中的元素即可 展示迭代器的兩種基本使用方式如下: 使用cbegin和cend訪問vector中的元素,,在訪問元素時,,可以通過解引用的方式訪問迭代器指向的元素,也就是'*iter' 使用begin和end訪問和修改vector中的元素,,在修改元素時,,需要使用指針運算符來對迭代器所指向的元素進行修改,也就是'*iter=new_value' #include 1.3應(yīng)用技巧 迭代器的應(yīng)用技巧包括迭代器間的算術(shù)運算,、逆向迭代器,、插入迭代器、流迭代器等,。 這些技巧可以大大簡化代碼的編寫提高程序的效率 1.3.1迭代器間的算術(shù)運算 迭代器間的算術(shù)運算包括加法和減法,,可以通過運算得到目標迭代器在容器中的位置 如下所示: autoiter=ivec.begin;autoiter2=iter+3;//iter2指向ivec中第4個元素autoiter3=iter2-2;//iter3指向ivec中第2個元素 注意的:加法和減法操作運用在容器中的迭代器類型必須支持該運算,只有隨機訪問迭代器支持加減運算 1.3.2逆向迭代器 逆向迭代器是一種反向遍歷容器的迭代器,,可以通過rbegin和rend函數(shù)來訪問 如下所示: for(autoiter=ivec.rbegin;iter!=ivec.rend;++iter){cout<<*iter<<'';}cout< 注意:逆向迭代器操作和普通迭代器不同,逆向迭代器的++操作實際上是--,,--操作實際上是++,。并且逆向迭代器只能被隨機訪問迭代器進行算術(shù)運算。 1.3.3插入迭代器 插入迭代器是一種特殊的迭代器可以在容器中插入元素,,有back_inserter,、front_inserter和inserter三種類型。 back_inserter示例如下: vector 1.3.4流迭代器 流迭代器是一種迭代器類型,可以使用iostream對象來進行輸入和輸出 如下所示: #include 注意:輸出迭代器可以通過繼承std::iterator類來實現(xiàn),,使得輸出操作與容器對象的類型無關(guān) 四,、算法 1.1STL中常見算法及其應(yīng)用場景 STL中提供了許多常見的算法實現(xiàn),包括查找,、排序,、變序、合并等,。這些算法適用于大部分容器類型如vector,、list、set,、map 1.1.1查找 find:在指定區(qū)間查找特定元素,,返回指向該元素的迭代器。 binary_search:在有序區(qū)間查找特定元素,,返回bool類型結(jié)果,。 count:在指定區(qū)間計數(shù)特定元素的個數(shù)。 應(yīng)用場景:常用于查找,、比較操作 1.1.2排序 sort:排序指定區(qū)間的元素,。 stable_sort:排序指定區(qū)間的元素,保持穩(wěn)定性,。 partial_sort:部分排序,,將指定區(qū)間元素排在前面,其余元素排序用默認比較函數(shù)處理,。 應(yīng)用場景:常用于排序操作 1.1.3變序 reverse:將指定區(qū)間的元素反轉(zhuǎn),。 rotate:讓指定區(qū)間的元素旋轉(zhuǎn)。 shuffle:調(diào)用隨機數(shù)引擎并按照指定方式隨機重排區(qū)間內(nèi)的元素,。 應(yīng)用場景:常用于計算機圖形學(xué),、游戲開發(fā) 1.1.4合并 merge:將兩個已經(jīng)排好序的序列合并成一個排序的序列。 merge_backward:將兩個已經(jīng)排好序的序列合并成一個排序的序列,,但合并后的元素保持原序列的穩(wěn)定性,。 應(yīng)用場景:常見于歸并排序 1.1.5算術(shù)操作 accumulate:計算指定區(qū)間元素的總和。 inner_product:計算指定區(qū)間兩個元素序列的內(nèi)積,。 adjacent_difference:計算相鄰元素之間的差值,。 partial_sum:由相鄰元素的和序列輸出指定序列部分和。 應(yīng)用場景:常用于數(shù)學(xué)計算,、統(tǒng)計分析等 1.2復(fù)雜度分析與優(yōu)化 大多數(shù)STL算法的復(fù)雜度都處于時間復(fù)雜度為O(nlogn)的級別,,因此在處理大量數(shù)據(jù)時,時間復(fù)雜度的優(yōu)化尤為重要,。 下面介紹幾種常見的算法復(fù)雜度分析: 1.2.1排序算法 排序算法的復(fù)雜度主要取決于比較次數(shù),,因此需要盡可能減少比較次數(shù)以提高排序效率。常見的排序算法包括快速排序、歸并排序和堆排序,,其中快速排序相對來說效率更高,,但在極端情況下會出現(xiàn)O(n2)的最壞情況。 1.2.2查找算法 查找算法的時間復(fù)雜度與數(shù)據(jù)結(jié)構(gòu)有關(guān),,常見的查找算法有線性查找,、二分法查找、哈希表查找等等,。其中二分法查找適用于已經(jīng)排序的序列,,時間復(fù)雜度為O(logn);哈希表查找適用于無序序列時間復(fù)雜度可達到O(1),。 1.2.3變序算法 變序算法的性能優(yōu)化方法主要是減少數(shù)據(jù)訪問次數(shù),,例如在計算機圖形學(xué)中常用的octree空間索引算法,通過將數(shù)據(jù)存儲在八叉樹結(jié)構(gòu)中可以實現(xiàn)高效的空間數(shù)據(jù)查詢,。 1.3基于范型編程的算法設(shè)計 范型編程是一種基于模板和泛型的編程思想,,可以有效地提高代碼復(fù)用性和可擴展性。STL正是基于此思想設(shè)計的,,因此STL的大多數(shù)算法都是基于范型編程的,。 基于范型編程的算法設(shè)計主要體現(xiàn)在:使用模板參數(shù)代替實際數(shù)值類型,可以適用于多種不同數(shù)據(jù)類型的處理,;使用STL的迭代器實現(xiàn)容器的訪問和操作,,可以適用于多種不同容器類型的處理。 例如在STL中sort函數(shù)使用迭代器實現(xiàn)對任意容器的排序操作 代碼如下: template 其中RandomAccessIterator是隨機訪問迭代器,,可以適用于多種不同容器類型的處理,。 使用sort函數(shù)進行排序的代碼示例: #include 五、小結(jié)回顧 本文主要介紹了StandardTemplateLibrary中的三個核心組件:容器,、迭代器和算法,。容器是用于存儲和管理數(shù)據(jù)的對象,包括vector,、list,、set、map等,。而迭代器是容器的訪問方式用于遍歷容器中的元素,。最后介紹了STL算法的基本分類、應(yīng)用場景以及復(fù)雜度分析,,STL是C++編程中重要掌握部分其知識對于提高程序開發(fā)效率和編程能力至關(guān)重要,,讓我們下篇文章繼續(xù)學(xué)習(xí)。 |
|