日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++容器

發(fā)布時間:2025/10/17 c/c++ 14 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++容器 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
什么是容器
首先,我們必須理解一下什么是容器,在C++ 中容器被定義為:在數(shù)據(jù)存儲上,有一種對象類型,它可以持有其它對象或指向其它對像的指針,這種對象類型就叫做容器。很簡單,容器就是保存其它對象的對象,當然這是一個樸素的理解,這種“對象”還包含了一系列處理“其它對象”的方法,因為這些方法在程序的設(shè)計上會經(jīng)常被用到,所以容器也體現(xiàn)了一個好處,就是“容器類是一種對特定代碼重用問題的良好的解決方案”。
容器還有另一個特點是容器可以自行擴展。在解決問題時我們常常不知道我們需要存儲多少個對象,也就是說我們不知道應(yīng)該創(chuàng)建多大的內(nèi)存空間來保存我們的對象。顯然,數(shù)組在這一方面也力不從心。容器的優(yōu)勢就在這里,它不需要你預先告訴它你要存儲多少對象,只要你創(chuàng)建一個容器對象,并合理的調(diào)用它所提供的方法,所有的處理細節(jié)將由容器來自身完成。它可以為你申請內(nèi)存或釋放內(nèi)存,并且用最優(yōu)的算法來執(zhí)行您的命令。
容器是隨著面向?qū)ο笳Z言的誕生而提出的,容器類在面向?qū)ο笳Z言中特別重要,甚至它被認為是早期面向?qū)ο笳Z言的基礎(chǔ)。在現(xiàn)在幾乎所有的面向?qū)ο蟮恼Z言中也都伴隨著一個容器集,在C++ 中,就是標準模板庫(STL )。
和其它語言不一樣,C++ 中處理容器是采用基于模板的方式。標準C++ 庫中的容器提供了多種數(shù)據(jù)結(jié)構(gòu),這些數(shù)據(jù)結(jié)構(gòu)可以與標準算法一起很好的工作,這為我們的軟件開發(fā)提供了良好的支持!
通用容器的分類
STL 對定義的通用容器分三類:順序性容器、關(guān)聯(lián)式容器和容器適配器。
順序性容器 是一種各元素之間有順序關(guān)系的線性表,是一種線性結(jié)構(gòu)的可序群集。順序性容器中的每個元素均有固定的位置,除非用刪除或插入的操作改變這個位置。這個位置和元素本身無關(guān),而和操作的時間和地點有關(guān),順序性容器不會根據(jù)元素的特點排序而是直接保存了元素操作時的邏輯順序。比如我們一次性對一個順序性容器追加三個元素,這三個元素在容器中的相對位置和追加時的邏輯次序是一致的。
關(guān)聯(lián)式容器 和順序性容器不一樣,關(guān)聯(lián)式容器是非線性的樹結(jié)構(gòu),更準確的說是二叉樹結(jié)構(gòu)。各元素之間沒有嚴格的物理上的順序關(guān)系,也就是說元素在容器中并沒有保存元素置入容器時的邏輯順序。但是關(guān)聯(lián)式容器提供了另一種根據(jù)元素特點排序的功能,這樣迭代器就能根據(jù)元素的特點“順序地”獲取元素。
關(guān)聯(lián)式容器另一個顯著的特點是它是以鍵值的方式來保存數(shù)據(jù),就是說它能把關(guān)鍵字和值關(guān)聯(lián)起來保存,而順序性容器只能保存一種(可以認為它只保存關(guān)鍵字,也可以認為它只保存值)。這在下面具體的容器類中可以說明這一點。
容器適配器 是一個比較抽象的概念, C++的解釋是:適配器是使一事物的行為類似于另一事物的行為的一種機制。容器適配器是讓一種已存在的容器類型采用另一種不同的抽象類型的工作方式來實現(xiàn)的一種機制。其實僅是發(fā)生了接口轉(zhuǎn)換。那么你可以把它理解為容器的容器,它實質(zhì)還是一個容器,只是他不依賴于具體的標準容器類型,可以理解是容器的模版?;蛘甙阉斫鉃槿萜鞯慕涌?#xff0c;而適配器具體采用哪種容器類型去實現(xiàn),在定義適配器的時候可以由你決定。
下表列出STL 定義的三類容器所包含的具體容器類:
標準容器類
特點
順序性容器
vector ? ? ? ? ?從后面快速的插入與刪除,直接訪問任何元素
deque ? ? ? ??從前面或后面快速的插入與刪除,直接訪問任何元素
list ? ? ? ? ? ? ? ?雙鏈表,從任何地方快速插入與刪除
關(guān)聯(lián)容器
set ? ? ? ? ? ? ??快速查找,不允許重復值
multiset ? ? ?快速查找,允許重復值
map ? ? ? ? ? ?一對多映射,基于關(guān)鍵字快速查找,不允許重復值
multimap ??一對多映射,基于關(guān)鍵字快速查找,允許重復值
容器適配器
stack ? ?后進先出
queue ? ? ??先進先出
priority_queue ? ? ? ?最高優(yōu)先級元素總是第一個出列
vector ,deque 和 list
順序性容器:
向量 vector :
是一個線性順序結(jié)構(gòu)。相當于數(shù)組,但其大小可以不預先指定,并且自動擴展。它可以像數(shù)組一樣被操作,由于它的特性我們完全可以將vector 看作動態(tài)數(shù)組。
在創(chuàng)建一個vector 后,它會自動在內(nèi)存中分配一塊連續(xù)的內(nèi)存空間進行數(shù)據(jù)存儲,初始的空間大小可以預先指定也可以由vector 默認指定,這個大小即capacity ()函數(shù)的返回值。當存儲的數(shù)據(jù)超過分配的空間時vector 會重新分配一塊內(nèi)存塊,但這樣的分配是很耗時的,在重新分配空間時它會做這樣的動作:
首先,vector 會申請一塊更大的內(nèi)存塊;
然后,將原來的數(shù)據(jù)拷貝到新的內(nèi)存塊中;
其次,銷毀掉原內(nèi)存塊中的對象(調(diào)用對象的析構(gòu)函數(shù));
最后,將原來的內(nèi)存空間釋放掉。
如果vector 保存的數(shù)據(jù)量很大時,這樣的操作一定會導致糟糕的性能(這也是vector 被設(shè)計成比較容易拷貝的值類型的原因)。所以說vector 不是在什么情況下性能都好,只有在預先知道它大小的情況下vector 的性能才是最優(yōu)的。
vector 的特點:
(1) 指定一塊如同數(shù)組一樣的連續(xù)存儲,但空間可以動態(tài)擴展。即它可以像數(shù)組一樣操作,并且可以進行動態(tài)操作。通常體現(xiàn)在push_back() pop_back() 。
(2) 隨機訪問方便,它像數(shù)組一樣被訪問,即支持[ ] 操作符和vector.at()
(3) 節(jié)省空間,因為它是連續(xù)存儲,在存儲數(shù)據(jù)的區(qū)域都是沒有被浪費的,但是要明確一點vector 大多情況下并不是滿存的,在未存儲的區(qū)域?qū)嶋H是浪費的。
(4) 在內(nèi)部進行插入、刪除操作效率非常低,這樣的操作基本上是被禁止的。Vector 被設(shè)計成只能在后端進行追加和刪除操作,其原因是vector 內(nèi)部的實現(xiàn)是按照順序表的原理。
(5) 只能在vector 的最后進行push 和pop ,不能在vector 的頭進行push 和pop 。
(6) 當動態(tài)添加的數(shù)據(jù)超過vector 默認分配的大小時要進行內(nèi)存的重新分配、拷貝與釋放,這個操作非常消耗性能。 所以要vector 達到最優(yōu)的性能,最好在創(chuàng)建vector 時就指定其空間大小。
雙向鏈表list
是一個線性鏈表結(jié)構(gòu),它的數(shù)據(jù)由若干個節(jié)點構(gòu)成,每一個節(jié)點都包括一個信息塊(即實際存儲的數(shù)據(jù))、一個前驅(qū)指針和一個后驅(qū)指針。它無需分配指定的內(nèi)存大小且可以任意伸縮,這是因為它存儲在非連續(xù)的內(nèi)存空間中,并且由指針將有序的元素鏈接起來。
由于其結(jié)構(gòu)的原因,list 隨機檢索的性能非常的不好,因為它不像vector 那樣直接找到元素的地址,而是要從頭一個一個的順序查找,這樣目標元素越靠后,它的檢索時間就越長。檢索時間與目標元素的位置成正比。
雖然隨機檢索的速度不夠快,但是它可以迅速地在任何節(jié)點進行插入和刪除操作。因為list 的每個節(jié)點保存著它在鏈表中的位置,插入或刪除一個元素僅對最多三個元素有所影響,不像vector 會對操作點之后的所有元素的存儲地址都有所影響,這一點是vector 不可比擬的。
list 的特點:
(1) 不使用連續(xù)的內(nèi)存空間這樣可以隨意地進行動態(tài)操作;
(2) 可以在內(nèi)部任何位置快速地插入或刪除,當然也可以在兩端進行push 和pop 。
(3) 不能進行內(nèi)部的隨機訪問,即不支持[ ] 操作符和vector.at() ;
(4) 相對于verctor 占用更多的內(nèi)存。
雙端隊列deque
是一種優(yōu)化了的、對序列兩端元素進行添加和刪除操作的基本序列容器。它允許較為快速地隨機訪問,但它不像vector 把所有的對象保存在一塊連續(xù)的內(nèi)存塊,而是采用多個連續(xù)的存儲塊,并且在一個映射結(jié)構(gòu)中保存對這些塊及其順序的跟蹤。向deque 兩端添加或刪除元素的開銷很小。它不需要重新分配空間,所以向末端增加元素比vector 更有效。
實際上,deque 是對vector 和list 優(yōu)缺點的結(jié)合,它是處于兩者之間的一種容器。
deque 的特點:
(1) 隨機訪問方便,即支持[ ] 操作符和vector.at() ,但性能沒有vector 好;
(2) 可以在內(nèi)部進行插入和刪除操作,但性能不及l(fā)ist ;
(3) 可以在兩端進行push 、pop ;
三者的比較
下圖描述了vector 、list 、deque 在內(nèi)存結(jié)構(gòu)上的特點:
vector 是一段連續(xù)的內(nèi)存塊,而deque 是多個連續(xù)的內(nèi)存塊, list 是所有數(shù)據(jù)元素分開保存,可以是任何兩個元素沒有連續(xù)。
vector 的查詢性能最好,并且在末端增加數(shù)據(jù)也很好,除非它重新申請內(nèi)存段;適合高效地隨機存儲。
list 是一個鏈表,任何一個元素都可以是不連續(xù)的,但它都有兩個指向上一元素和下一元素的指針。所以它對插入、刪除元素性能是最好的,而查詢性能非常差;適合 大量地插入和刪除操作而不關(guān)心隨機存取的需求。
deque 是介于兩者之間,它兼顧了數(shù)組和鏈表的優(yōu)點,它是分塊的鏈表和多個數(shù)組的聯(lián)合。所以它有被list 好的查詢性能,有被vector 好的插入、刪除性能。 如果你需要隨即存取又關(guān)心兩端數(shù)據(jù)的插入和刪除,那么deque 是最佳之選。
關(guān)聯(lián)容器
set, multiset, map, multimap 是一種非線性的樹結(jié)構(gòu),具體的說采用的是一種比較高效的特殊的平衡檢索二叉樹—— 紅黑樹結(jié)構(gòu)。(至于什么是紅黑樹,我也不太理解,只能理解到它是一種二叉樹結(jié)構(gòu))
因為關(guān)聯(lián)容器的這四種容器類都使用同一原理,所以他們核心的算法是一致的,但是它們在應(yīng)用上又有一些差別,先描述一下它們之間的差別。
set ,又稱集合,實際上就是一組元素的集合,但其中所包含的元素的值是唯一的,且是按一定順序排列的,集合中的每個元素被稱作集合中的實例。因為其內(nèi)部是通過鏈表的方式來組織,所以在插入的時候比vector 快,但在查找和末尾添加上被vector 慢。
multiset ,是多重集合,其實現(xiàn)方式和set 是相似的,只是它不要求集合中的元素是唯一的,也就是說集合中的同一個元素可以出現(xiàn)多次。
map ,提供一種“鍵- 值”關(guān)系的一對一的數(shù)據(jù)存儲能力。其“鍵”在容器中不可重復,且按一定順序排列(其實我們可以將set 也看成是一種鍵- 值關(guān)系的存儲,只是它只有鍵沒有值。它是map 的一種特殊形式)。由于其是按鏈表的方式存儲,它也繼承了鏈表的優(yōu)缺點。
multimap , 和map 的原理基本相似,它允許“鍵”在容器中可以不唯一。
關(guān)聯(lián)容器的特點是明顯的,相對于順序容器,有以下幾個主要特點:
1, 其內(nèi)部實現(xiàn)是采用非線性的二叉樹結(jié)構(gòu),具體的說是紅黑樹的結(jié)構(gòu)原理實現(xiàn)的;
2, set 和map 保證了元素的唯一性,mulset 和mulmap 擴展了這一屬性,可以允許元素不唯一;
3, 元素是有序的集合,默認在插入的時候按升序排列。
基于以上特點,
1, 關(guān)聯(lián)容器對元素的插入和刪除操作比vector 要快,因為vector 是順序存儲,而關(guān)聯(lián)容器是鏈式存儲;比list 要慢,是因為即使它們同是鏈式結(jié)構(gòu),但list 是線性的,而關(guān)聯(lián)容器是二叉樹結(jié)構(gòu),其改變一個元素涉及到其它元素的變動比list 要多,并且它是排序的,每次插入和刪除都需要對元素重新排序;
2, 關(guān)聯(lián)容器對元素的檢索操作比vector 慢,但是比list 要快很多。vector 是順序的連續(xù)存儲,當然是比不上的,但相對鏈式的list 要快很多是因為list 是逐個搜索,它搜索的時間是跟容器的大小成正比,而關(guān)聯(lián)容器 查找的復雜度基本是Log(N) ,比如如果有1000 個記錄,最多查找10 次,1,000,000 個記錄,最多查找20 次。容器越大,關(guān)聯(lián)容器相對list 的優(yōu)越性就越能體現(xiàn);
3, 在使用上set 區(qū)別于vector,deque,list 的最大特點就是set 是內(nèi)部排序的,這在查詢上雖然遜色于vector ,但是卻大大的強于list 。
4, 在使用上map 的功能是不可取代的,它保存了“鍵- 值”關(guān)系的數(shù)據(jù),而這種鍵值關(guān)系采用了類數(shù)組的方式。數(shù)組是用數(shù)字類型的下標來索引元素的位置,而map 是用字符型關(guān)鍵字來索引元素的位置。在使用上map 也提供了一種類數(shù)組操作的方式,即它可以通過下標來檢索數(shù)據(jù),這是其他容器做不到的,當然也包括set 。(STL 中只有vector 和map 可以通過類數(shù)組的方式操作元素,即如同ele[1] 方式)
容器適配器
STL 中包含三種適配器:棧stack 、隊列queue 和優(yōu)先級priority_queue 。
適配器是容器的接口,它本身不能直接保存元素,它保存元素的機制是調(diào)用另一種順序容器去實現(xiàn),即可以把適配器看作“它保存一個容器,這個容器再保存所有元素”。
STL 中提供的三種適配器可以由某一種順序容器去實現(xiàn)。默認下stack 和queue 基于deque 容器實現(xiàn),priority_queue 則基于vector 容器實現(xiàn)。當然在創(chuàng)建一個適配器時也可以指定具體的實現(xiàn)容器,創(chuàng)建適配器時在第二個參數(shù)上指定具體的順序容器可以覆蓋適配器的默認實現(xiàn)。
由于適配器的特點,一個適配器不是可以由任一個順序容器都可以實現(xiàn)的。
棧stack 的特點是后進先出,所以它關(guān)聯(lián)的基本容器可以是任意一種順序容器,因為這些容器類型結(jié)構(gòu)都可以提供棧的操作有求,它們都提供了push_back 、pop_back 和back 操作;
隊列queue 的特點是先進先出,適配器要求其關(guān)聯(lián)的基礎(chǔ)容器必須提供pop_front 操作,因此其不能建立在vector 容器上;
優(yōu)先級隊列priority_queue 適配器要求提供隨機訪問功能,因此不能建立在list 容器上。

總結(jié)

以上是生活随笔為你收集整理的C++容器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。