STL相關(guān)知識(shí)

組成:容器宴咧,迭代器,算法

各種容器的元素在內(nèi)存中的儲(chǔ)存方式

1档桃、vector(向量):相當(dāng)于數(shù)組,但其大小可以不預(yù)先指定堪嫂,并且自動(dòng)擴(kuò)展。它可以像數(shù)組一樣被操作木柬,由于它的特性我們完全可以將vector 看作動(dòng)態(tài)數(shù)組皆串。在創(chuàng)建一個(gè)vector 后,它會(huì)自動(dòng)在內(nèi)存中分配一塊連續(xù)的眉枕。內(nèi)存空間進(jìn)行數(shù)據(jù)存儲(chǔ)恶复,初始的空間大小可以預(yù)先指定也可以由vector 默認(rèn)指定,這個(gè)大小即capacity ()函數(shù)的返回值速挑。當(dāng)存儲(chǔ)的數(shù)據(jù)超過分配的空間時(shí)vector 會(huì)重新分配一塊內(nèi)存塊谤牡,但這樣的分配是很耗時(shí)的,效率非常低姥宝。
2翅萤、deque(隊(duì)列):它不像vector 把所有的對象保存在一塊連續(xù)的內(nèi)存塊,而是采用多個(gè)連續(xù)的存儲(chǔ)塊腊满,并且在一個(gè)映射結(jié)構(gòu)中保存對這些塊及其順序的跟蹤套么。向deque 兩端添加或刪除元素的開銷很小,它不需要重新分配空間糜烹。
3违诗、list(列表):是一個(gè)線性鏈表結(jié)構(gòu),它的數(shù)據(jù)由若干個(gè)節(jié)點(diǎn)構(gòu)成疮蹦,每一個(gè)節(jié)點(diǎn)都包括一個(gè)信息塊(即實(shí)際存儲(chǔ)的數(shù)據(jù))、一個(gè)前驅(qū)指針和一個(gè)后驅(qū)指針茸炒。它無需分配指定的內(nèi)存大小且可以任意伸縮愕乎,這是因?yàn)樗鎯?chǔ)在非連續(xù)的內(nèi)存空間中,并且由指針將有序的元素鏈接起來壁公。
4感论、set, multiset, map, multimap 是一種非線性的樹結(jié)構(gòu),具體的說采用的是一種比較高效的特殊的平衡檢索二叉樹—— 紅黑樹結(jié)構(gòu)紊册。

hashset與set相比較比肄,它里面的元素不一定是經(jīng)過排序的快耿,而是按照所用的hash函數(shù)分派的,它能提供更快的搜索速度(當(dāng)然跟hash函數(shù)有關(guān))
Stl容器的參數(shù)allocate是用來做什么的芳绩?這是一個(gè)函數(shù)對象掀亥,用來指定小于運(yùn)算過程。Map的Key有什么要求妥色?開始我答不能重復(fù)搪花,他繼續(xù)問,答必須重載<運(yùn)算符嘹害,OK
1.C++ STL 之所以得到廣泛的贊譽(yù)撮竿,也被很多人使用,不只是提供了像vector, string, list等方便的容器笔呀,更重要的是STL封裝了許多復(fù)雜的數(shù)據(jù)結(jié)構(gòu)算法和大量常用數(shù)據(jù)結(jié)構(gòu)操作幢踏。vector封裝數(shù)組,list封裝了鏈表许师,map和set封裝了二叉樹等
2.標(biāo)準(zhǔn)關(guān)聯(lián)容器set, multiset, map, multimap內(nèi)部采用的就是一種非常高效的平衡檢索二叉樹:紅黑樹房蝉,也成為RB樹(Red-BlackTree)。RB樹的統(tǒng)計(jì)性能要好于一般的 平衡二叉樹
3.STL map和set的使用雖不復(fù)雜枯跑,但也有一些不易理解的地方惨驶,如:
map: type pair <constKey, T> ,很多不同的 const Key 對應(yīng)的 T 對象的一個(gè)集合敛助,所有的記錄集中只要 const Key 不一樣就可以粗卜, T 無關(guān)! set: type const Key. 只存單一的對 const Key 纳击,沒有 map 的 T 對像续扔!可以看成 map 的一個(gè)特例

(1)為何map和set的插入刪除效率比用其他序列容器高?焕数,樹

答:因?yàn)閷τ陉P(guān)聯(lián)容器來說纱昧,不需要做內(nèi)存拷貝和內(nèi)存移動(dòng)。說對了堡赔,確實(shí)如此识脆。map和set容器內(nèi)所有元素都是以節(jié)點(diǎn)的方式來存儲(chǔ),其節(jié)點(diǎn)結(jié)構(gòu)和鏈表差不多善已,指向父節(jié)點(diǎn)和子節(jié)點(diǎn)

(2)為何每次insert之后灼捂,以前保存的iterator不會(huì)失效?

答:iterator這里就相當(dāng)于指向節(jié)點(diǎn)的指針换团,內(nèi)存沒有變悉稠,指向內(nèi)存的指針怎么會(huì)失效呢(當(dāng)然被刪除的那個(gè)元素本身已經(jīng)失效了)。相對于vector來說艘包,每一次刪除和插入的猛,指針都有可能失效耀盗,調(diào)用push_back在尾部插入也是如此。因?yàn)闉榱吮WC內(nèi)部數(shù)據(jù)的連續(xù)存放卦尊,iterator指向的那塊內(nèi)存在刪除和插入過程中可能已經(jīng)被其他內(nèi)存覆蓋或者內(nèi)存已經(jīng)被釋放了叛拷。即使時(shí)push_back的時(shí)候,容器內(nèi)部空間可能不夠猫牡,需要一塊新的更大的內(nèi)存胡诗,只有把以前的內(nèi)存釋放,申請新的更大的內(nèi)存淌友,復(fù)制已有的數(shù)據(jù)元素到新的內(nèi)存煌恢,最后把需要插入的元素放到最后,那么以前的內(nèi)存指針自然就不可用了震庭。特別時(shí)在和find等算法在一起使用的時(shí)候瑰抵,牢記這個(gè)原則:不要使用過期的iterator。

(3)為何map和set不能像vector一樣有個(gè)reserve函數(shù)來預(yù)分配數(shù)據(jù)器联?

答:我以前也這么問二汛,究其原理來說時(shí),引起它的原因在于在map和set內(nèi)部存儲(chǔ)的已經(jīng)不是元素本身了拨拓,而是包含元素的節(jié)點(diǎn)肴颊。也就是說map內(nèi)部使用的Alloc并不是map<Key, Data, Compare, Alloc>聲明的時(shí)候從參數(shù)中傳入的Alloc。例如:

4.set, multiset

set和multiset會(huì)根據(jù)特定的排序準(zhǔn)則自動(dòng)將元素排序渣磷,set中元素不允許重復(fù)婿着,multiset可以重復(fù)。
因?yàn)槭桥判虻拇捉纾詓et中的元素不能被修改竟宋,只能刪除后再添加。
向set中添加的元素類型必須重載<操作符用來排序形纺。排序滿足以下準(zhǔn)則:
1丘侠、非對稱,若A<B為真逐样,則B<A為假蜗字。
2、可傳遞脂新,若A<B,B<C秽澳,則A<C。
3戏羽、A<A永遠(yuǎn)為假。
set中判斷元素是否相等:
if(!(A<B || B<A))楼吃,當(dāng)A<B和B<A都為假時(shí)始花,它們相等妄讯。

5.map,multimap

map和multimap將key和value組成的pair作為元素酷宵,根據(jù)key的排序準(zhǔn)則自動(dòng)將元素排序亥贸,map中元素的key不允許重復(fù),multimap可以重復(fù)浇垦。
map<key,value>
因?yàn)槭桥判虻目恢茫詍ap中元素的key不能被修改,只能刪除后再添加男韧。key對應(yīng)的value可以修改朴摊。
向map中添加的元素的key類型必須重載<操作符用來排序。排序與set規(guī)則一致此虑。

6. List的功能方法

實(shí)際上有兩種List: 一種是基本的ArrayList,其優(yōu)點(diǎn)在于隨機(jī)訪問元素甚纲,另一種是更強(qiáng)大的LinkedList,它并不是為快速隨機(jī)訪問設(shè)計(jì)的,而是具有一套更通用的方法朦前。
List : 次序是List最重要的特點(diǎn):它保證維護(hù)元素特定的順序介杆。List為Collection添加了許多方法,使得能夠向List中間插入與移除元素(這只推薦LinkedList使用韭寸。)一個(gè)List可以生成ListIterator,使用它可以從兩個(gè)方向遍歷List,也可以從List中間插入和移除元素春哨。
ArrayList : 由數(shù)組實(shí)現(xiàn)的List。允許對元素進(jìn)行快速隨機(jī)訪問恩伺,但是向List中間插入與移除元素的速度很慢赴背。ListIterator只應(yīng)該用來由后向前遍歷ArrayList,而不是用來插入和移除元素。因?yàn)槟潜萀inkedList開銷要大很多莫其。
LinkedList : 對順序訪問進(jìn)行了優(yōu)化癞尚,向List中間插入與刪除的開銷并不大。隨機(jī)訪問則相對較慢乱陡。(使用ArrayList代替浇揩。)還具有下列方法:addFirst(), addLast(), getFirst(),getLast(), removeFirst() 和 removeLast(), 這些方法 (沒有在任何接口或基類中定義過)使得LinkedList可以當(dāng)作堆棧、隊(duì)列和雙向隊(duì)列使用

7..1 hash_map和map的區(qū)別在哪里憨颠?

構(gòu)造函數(shù)胳徽。hash_map需要hash函數(shù),等于函數(shù)爽彤;map只需要比較函數(shù)(小于函數(shù)).
存儲(chǔ)結(jié)構(gòu)养盗。hash_map采用hash表存儲(chǔ),map一般采用 紅黑樹(RB Tree) 實(shí)現(xiàn)适篙。因此其memory數(shù)據(jù)結(jié)構(gòu)是不一樣的往核。

7.2 什么時(shí)候需要用hash_map,什么時(shí)候需要用map?

總體來說嚷节,hash_map 查找速度會(huì)比map快聂儒,而且查找速度基本和數(shù)據(jù)數(shù)據(jù)量大小虎锚,屬于常數(shù)級別;而map的查找速度是log(n)級別。并不一定常數(shù)就比log(n)小衩婚,hash還有hash函數(shù)的耗時(shí)窜护,如果你考慮效率,特別是在元素達(dá)到一定數(shù)量級時(shí)非春,考慮考慮hash_map柱徙。但若你對內(nèi)存使用特別嚴(yán)格,希望程序盡可能少消耗內(nèi)存奇昙,那么一定要小心护侮,hash_map可能會(huì)讓你陷入尷尬,特別是當(dāng)你的hash_map對象特別多時(shí)敬矩,你就更無法控制了概行,而且hash_map的構(gòu)造速度較慢。
權(quán)衡三個(gè)因素: 查找速度, 數(shù)據(jù)量, 內(nèi)存使用弧岳。
8.一些使用上的建議:
Level 1 - 僅僅作為Map使用:采用靜態(tài)數(shù)組
Level 2 - 保存定長數(shù)據(jù)凳忙,使用時(shí)也是全部遍歷:采用動(dòng)態(tài)數(shù)組(長度一開始就固定的話靜態(tài)數(shù)組也行)
Level 3 - 保存不定長數(shù)組,需要?jiǎng)討B(tài)增加的能力禽炬,側(cè)重于尋找數(shù)據(jù)的速度:采用vector
Level 3 - 保存不定長數(shù)組涧卵,需要?jiǎng)討B(tài)增加的能力,側(cè)重于增加刪除數(shù)據(jù)的速度:采用list
Level 4 - 對數(shù)據(jù)有復(fù)雜操作腹尖,即需要前后增刪數(shù)據(jù)的能力柳恐,又要良好的數(shù)據(jù)訪問速度:采用deque
Level 5 - 對數(shù)據(jù)中間的增刪操作比較多:采用list,建議在排序的基礎(chǔ)上热幔,批量進(jìn)行增刪可以對運(yùn)行效率提供最大的保證
Level 6 - 上述中找不到適合的:組合STL容器或者自己建立特殊的數(shù)據(jù)結(jié)構(gòu)來實(shí)現(xiàn)

(1).vector - 會(huì)自動(dòng)增長的數(shù)組
vector<int>vec(10) //一個(gè)有10個(gè)int元素的容器
vector<float> vec(10, 0.5)//一個(gè)有10個(gè)float元素的容器乐设,并且他們得值都是0.5
vector<int>::iterator iter;
for(iter = vec.begin(); iter != vec.end(); iter++)
{
//. . . . . . .
}
vector由于數(shù)組的增長只能向前,所以也只提供了后端插入和后端刪除绎巨,
也就是push_back和pop_back近尚。當(dāng)然在前端和中間要操作數(shù)據(jù)也是可以的,
用insert和erase场勤,但是前端和中間對數(shù)據(jù)進(jìn)行操作必然會(huì)引起數(shù)據(jù)塊的移動(dòng)戈锻,
這對性能影響是非常大的。
最大的優(yōu)勢就是隨機(jī)訪問的能力和媳。
vector<T1>::iterator相關(guān)的方法有:
begin():用來獲得一個(gè)指向vector第一個(gè)元素的指針
end():用來獲得一個(gè)指向vector最后一個(gè)元素之后的那個(gè)位置的指針格遭,注意不是指向最后一個(gè)元素。
erase(vector<T1>::iterator):用來刪除作為參數(shù)所傳入的那個(gè)iterator所指向的那個(gè)元素留瞳。
(2).list - 擅長插入刪除的鏈表
list<string>Milkshakes; list<int> Scores;
push_back, pop_backpush_front. pop_front
list是一個(gè)雙向鏈表的實(shí)現(xiàn)拒迅。
為了提供雙向遍歷的能力,list要比一般的數(shù)據(jù)單元多出兩個(gè)指向前后的指針
一個(gè)使用iterator來刪除元素的例子
list<string> stringList;
list<string>::iterator iter;
advance(iter, 5); //將iterator指向stringList的第五個(gè)元素
stringList.erase(iterator);//刪除
那么刪除操作進(jìn)行以后,傳入erase()方法的iterator指向哪里了呢坪它?它指向了刪除操作前所指向的那個(gè)元素的后一個(gè)元素骤竹。
(3).deque - 擁有vector和list兩者優(yōu)點(diǎn)的雙端隊(duì)列
(4).這三個(gè)模板的總結(jié) 比較和一般使用準(zhǔn)則
這三個(gè)模板都屬于序列類模板,可以看到他們有一些通用方法
size():得到容器大小
begin():得到指向容器內(nèi)第一個(gè)元素的指針(這個(gè)指針的類型依容器的不同而不同)
end():得到指向容器內(nèi)最后一個(gè)元素之后一個(gè)位置的指針
erase():刪除傳入指針指向的那個(gè)元素
clear():清除所有的元素
==運(yùn)算符:判斷兩個(gè)容器是否相等
=運(yùn)算符:用來給容器賦值
上面的三個(gè)模板有各自的特點(diǎn)
vector模板的數(shù)據(jù)在內(nèi)存中連續(xù)的排列往毡,所以隨機(jī)存取元素(即通過[]運(yùn)算符存取)的速度最快靶溜,這一點(diǎn)和數(shù)組是一致的开瞭。同樣由于它的連續(xù)排列,所以它在除尾部以外的位置刪除或添加元素的速度很慢罩息,在使用vector時(shí)嗤详,要避免這種操作。
list模板的數(shù)據(jù)是鏈?zhǔn)酱鎯?chǔ)瓷炮,所以不能隨機(jī)存取元素葱色。它的優(yōu)勢在于任意位置添加 刪除元素的速度。
deque模板是通過鏈接若干片連續(xù)的數(shù)據(jù)實(shí)現(xiàn)的娘香,所以均衡了以上兩個(gè)容器的特點(diǎn)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末苍狰,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子烘绽,更是在濱河造成了極大的恐慌淋昭,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件安接,死亡現(xiàn)場離奇詭異翔忽,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)盏檐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進(jìn)店門歇式,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人胡野,你說我怎么就攤上這事材失。” “怎么了给涕?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵豺憔,是天一觀的道長。 經(jīng)常有香客問我够庙,道長恭应,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任耘眨,我火速辦了婚禮昼榛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己胆屿,他們只是感情好奥喻,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著非迹,像睡著了一般环鲤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上憎兽,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天冷离,我揣著相機(jī)與錄音,去河邊找鬼纯命。 笑死西剥,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的亿汞。 我是一名探鬼主播瞭空,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼疗我!你這毒婦竟也來了咆畏?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤碍粥,失蹤者是張志新(化名)和其女友劉穎鳖眼,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嚼摩,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡钦讳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了枕面。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片愿卒。...
    茶點(diǎn)故事閱讀 38,163評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖潮秘,靈堂內(nèi)的尸體忽然破棺而出琼开,到底是詐尸還是另有隱情,我是刑警寧澤枕荞,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布柜候,位于F島的核電站,受9級特大地震影響躏精,放射性物質(zhì)發(fā)生泄漏渣刷。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一矗烛、第九天 我趴在偏房一處隱蔽的房頂上張望辅柴。 院中可真熱鬧,春花似錦、人聲如沸碌嘀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽股冗。三九已至霹陡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間魁瞪,已是汗流浹背穆律。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留导俘,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓剔蹋,卻偏偏與公主長得像旅薄,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子泣崩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容