C++筆記八(Boolan網(wǎng)——STL與泛型編程)

本周內(nèi)容:
(1)deque&queue 和 stack 深度探索
(2)R-B tree 深度探索
(3)set/multiset深度探索
(4)map/multimap深度探索
(5)hashtable深度探索
(6)unordered容器概念

一 deque&queue 和 stack 深度探索

deque:deque的內(nèi)存空間分布是小片的連續(xù),小片間用鏈表相連坤塞,實(shí)際上內(nèi)部有一個(gè)map的指針辩蛋。其中buffer表示deque的緩沖區(qū)驼鞭,每個(gè)buffer可以存放多個(gè)元素結(jié)點(diǎn)椅棺。并且每個(gè)buffer指針存放在vector容器中。每個(gè)iterator存放四個(gè)指針:cur定庵、first西篓、last、node炉爆,cur表示當(dāng)前數(shù)據(jù)結(jié)點(diǎn)的指針堕虹,first表示buffer首指針卧晓,last表示buffer的尾指針,node表示這個(gè)iterator在vector中的指針地址赴捞。它模擬了一個(gè)連續(xù)的存儲(chǔ)空間(實(shí)質(zhì)表示連續(xù)分段的容器)逼裆。


deque.png

deque實(shí)現(xiàn)代碼如下,gnu2.9模板參數(shù)有三個(gè)赦政,其中第三個(gè)BufSiz默認(rèn)為0胜宇,可以由使用者自定buffer大小。


deque代碼.png

同樣的恢着,deque的iterator需要回答算法的五個(gè)問題桐愉,即上周的iterator traits。
deque iterator.png
  • deque<T>::insert()源碼解析
//在position處安插一個(gè)元素掰派,其值為x
iterator insert(iterator position,const value_type& x){
    if(position.cur == start.cur){               //如果安插點(diǎn)是deque最前端
      push_front(x);                                //交給push——front()做
      return start;
    }
    else if (position.cur == finish.cur) {    //如果安插點(diǎn)是deque最尾端
      push_back(x);                              //交給push——back()做
      iterator tmp =finish;
      --tmp;
      return tmp;
    }
    else {
      return insert_aux(position,x);
    }
  }

template<class T,class Alloc,size_t BufSize>
typename deque<T,Alloc,BufSize>::iterator
deque<T,Alloc,BufSize>::insert_aux(iterator pos,const value_type& x){
    difference_type index = pos - start;     //安插點(diǎn)之前的元素個(gè)數(shù)
    value_type x_copy =x;
    if (index<size()/2){                //如果安插點(diǎn)之前的元素個(gè)數(shù)較少
      push_front(front());             //在最前端加入與第一元素同值的元素
      ...
      copy(front2,pos1,front1);    //元素搬移
    }
    else{                        //安插點(diǎn)之后的元素個(gè)數(shù)較少
      push_back(back());   //在尾端加入與最末元素同值的元素
      ...
      copy_backward(pos,back2,back1);      //元素搬移
    }
    *pos = x_copy;        //在安插點(diǎn)上設(shè)定新值
    return pos;
}

deque是如何模擬連續(xù)空間的呢从诲?全都是deque iterators的功勞,源代碼做了大量的操作符重載靡羡,尤其是遇到buffer邊界時(shí)如何跳到控制中心盏求,使得deque的iterator能夠在buffer之間模擬出連續(xù)空間。實(shí)現(xiàn)代碼如下:

reference operator[] (size_type n)
{
    return start[difference_type(n)];
}
reference front(){return *start;}
reference back()
{
    iterator tmp = finish;
    --tmp;
    return *tmp;
}
size_type size() const {return finish - start;}
bool empty() const {return == start;}
reference operator*() const {return *cur;}
pointer operator->() const {return & (operator*());}
//兩根iterators之間的距離相當(dāng)于
//(1)兩根iterators間的buffers的總長(zhǎng)度+
//(2)itr至其buffer末尾的長(zhǎng)度+
//(3)x至其buffer起頭的長(zhǎng)度
difference_type
operator-(const self& x) const
{
     return difference_type(buffer_size())*(node-x.node-1)+
        (cur-first)+(x.last-x.cur);
          //首尾buffers之間的buffers數(shù)量
          //(cur-first)末尾(當(dāng)前)buffer的元素量亿眠,(x.last-x.cur)起始buffer的元素量
}
deque模擬連續(xù)空間.png

deque模擬連續(xù)空間2.png

deque模擬連續(xù)空間3.png

queue和stack底層都是由deque完成的碎罚,通常他們也被稱為容器適配器。

  • queue


    queue.png
  • stack


    stack.png
  • stack和queue都不允許遍歷纳像,也不提供iterator荆烈。
  • stack和queue都可選擇list和deque作為底層容器
  • queue不可選擇vector作為底層結(jié)構(gòu),stack可選擇vector作為底層結(jié)構(gòu)
  • stack和queue都不可選擇set或map做底層結(jié)構(gòu)

二 R-B tree 深度探索

  • Red-Black tree(紅黑樹)是平衡二元搜尋樹(balanced binary search tree)中常被使用的一種竟趾。平衡二元搜尋樹的特征:排列規(guī)則有利于search和insert憔购,并保持適度平衡,即無(wú)任何節(jié)點(diǎn)過深岔帽。
    • re_tree提供“遍歷”操作及iterators玫鸟。按正常規(guī)則(++ite)遍歷,便能獲得排序狀態(tài)(sorted)犀勒。
    • 我們不應(yīng)使用rb_tree的iterators改變?cè)刂担ㄒ驗(yàn)樵赜衅鋰?yán)謹(jǐn)排列規(guī)則)屎飘。編程并未阻止此事。如此設(shè)計(jì)是正確的贾费,因?yàn)閞b_tree即將為set和map服務(wù)(作為其底部支持)钦购,而map允許元素的data被改變,只有元素的key才是不可被改變的褂萧。
    • rb_tree提供兩種insertion操作:insert_unique()和insert_equal( )押桃。前者表示節(jié)點(diǎn)的key一定在整個(gè)tree中獨(dú)一無(wú)二,否則安插失數加獭唱凯;后者表示節(jié)點(diǎn)的key可重復(fù)羡忘。
rb_tree.png

rb_tree使用.png

紅黑樹的使用如下:


rb_tree使用.png

三 set/multiset深度探索

  • set/multiset以rb_tree為底層結(jié)構(gòu),因此有元素自動(dòng)排序特性磕昼。排序的依據(jù)是key壳坪,而set/multiset元素的value和key合一:value就是key。
  • set/multiset提供“遍歷”操作及iterators掰烟。按正常規(guī)則(++ite)遍歷爽蝴,便能獲得排序狀態(tài)(sorted)。
  • 我們無(wú)法使用set/multiset的iterators改變?cè)刂担ㄒ驗(yàn)閗ey有其嚴(yán)謹(jǐn)排列規(guī)則)纫骑。set/multiset的iterator是其底部的RB tree的const-iterator蝎亚,就是為了禁止user對(duì)元素賦值。
  • set元素的key必須獨(dú)一無(wú)二先馆,因此其insert()用的是rb_tree的insert_unique()发框。multiset元素的key可以重復(fù),因此其insert()用的rb_tree的insert_equal().


    set源代碼.png

四 map/multimap深度探索

  • map/multimap以rb_tree為底層結(jié)構(gòu)煤墙,因此有元素自動(dòng)排序特性梅惯。排序的依據(jù)是key。
  • map/multimap提供“遍歷”操作及iterators仿野。按正常規(guī)則(++ite)遍歷铣减,便能獲得排序狀態(tài)(sorted)。我們無(wú)法使用map/multimap的iterators改變?cè)氐膋ey(因?yàn)閗ey有其嚴(yán)謹(jǐn)排列順序)脚作,但可以用它來改變?cè)氐膁ata葫哗。因此map/multimap內(nèi)部自動(dòng)將user指定的key type設(shè)為const,如此便能禁止user對(duì)元素的key賦值球涛。
  • map元素的key必須獨(dú)一無(wú)二劣针,因此其insert()用的是rb_tree的insert_unique()。multimap元素的key可以重復(fù)亿扁,因此其insert()用的是rb_tree的insert_equal()捺典。


    map源代碼.png

五 hashtable深度探索

有一大堆的東西要放在容器里,每一個(gè)東西可以折射成一個(gè)數(shù)值从祝,這些數(shù)值的變化如果有2^32種變化襟己,所需要的空間要非常大,hashtable就是用來解決這個(gè)問題哄褒。


hashtable.png

當(dāng)碰撞的元素超過“籃子”的個(gè)數(shù)稀蟋,經(jīng)驗(yàn)判斷為危險(xiǎn),則將“籃子”的數(shù)量擴(kuò)大為原來的兩倍呐赡,一般籃子數(shù)量是素?cái)?shù)。GUC初始籃子數(shù)量為53骏融,兩倍變成106链嘀,附近的素?cái)?shù)而且比106大的為193.
我們可以使用hashtable iterators改變?cè)氐膁ata萌狂,但不能改變?cè)氐膋ey(因?yàn)閔ashtable根據(jù)key實(shí)現(xiàn)嚴(yán)謹(jǐn)?shù)脑嘏帕校?/p>

hashtable.png

hashtable源代碼如下:
hashtable.png

第一第二個(gè)參數(shù)與紅黑樹為底層的set和map類似,第三個(gè)模板參數(shù)hashFcn的目的是希望根據(jù)元素值算出一個(gè)hash code(一個(gè)可進(jìn)行modulus運(yùn)算的值)怀泊,使得元素hash code映射之后能夠夠雜亂夠隨機(jī)地被置于hashtable內(nèi)茫藏,越是亂,越是不容易碰撞霹琼,可以傳函數(shù)务傲、仿函數(shù)、函數(shù)對(duì)象枣申,它是通過模板偏特化實(shí)現(xiàn)售葡,c風(fēng)格的字符串char*是一個(gè)指針,stl提供了實(shí)現(xiàn)方式忠藤,而C++的字符串string則需要自己寫實(shí)現(xiàn)方式挟伙;第四個(gè)ExtractKey告訴我們?nèi)绾稳〕鰇ey;第五個(gè)EqualKey告訴我們?nèi)绾伪容^key大心:ⅰ尖阔;第六個(gè)分配器。

六 unordered容器概念

從C++11開始榨咐,以hash開頭的容器都改為unordered容器(不定序容器)

  • Before C++11
    • hash_set
    • hash_multiset
    • hash_map
    • hash_multimap
  • Since C++11
    • unordered_set
    • unordered_multiset
    • unordered_map
    • unordered_multimap
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末介却,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子块茁,更是在濱河造成了極大的恐慌筷笨,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件龟劲,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡仰禀,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門答恶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人萍诱,你說我怎么就攤上這事悬嗓≡7唬” “怎么了?”我有些...
    開封第一講書人閱讀 165,689評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)周瞎。 經(jīng)常有香客問我苗缩,道長(zhǎng),這世上最難降的妖魔是什么声诸? 我笑而不...
    開封第一講書人閱讀 58,925評(píng)論 1 295
  • 正文 為了忘掉前任彼乌,我火速辦了婚禮,結(jié)果婚禮上慰照,老公的妹妹穿的比我還像新娘。我一直安慰自己膏萧,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評(píng)論 6 392
  • 文/花漫 我一把揭開白布榛泛。 她就那樣靜靜地躺著噩斟,像睡著了一般。 火紅的嫁衣襯著肌膚如雪沛简。 梳的紋絲不亂的頭發(fā)上斥废,一...
    開封第一講書人閱讀 51,727評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音捧灰,去河邊找鬼统锤。 笑死,一個(gè)胖子當(dāng)著我的面吹牛饲窿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播逾雄,決...
    沈念sama閱讀 40,447評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼淌哟!你這毒婦竟也來了辽故?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,349評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤掉弛,失蹤者是張志新(化名)和其女友劉穎喂走,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體芋肠,經(jīng)...
    沈念sama閱讀 45,820評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡帖池,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了肴甸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片囚巴。...
    茶點(diǎn)故事閱讀 40,127評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖彤叉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情浮庐,我是刑警寧澤兼呵,帶...
    沈念sama閱讀 35,812評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站维苔,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏介时。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評(píng)論 3 331
  • 文/蒙蒙 一循衰、第九天 我趴在偏房一處隱蔽的房頂上張望褐澎。 院中可真熱鬧,春花似錦工三、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至澡罚,卻和暖如春姥闪,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背筐喳。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留荣月,地道東北人梳毙。 一個(gè)月前我還...
    沈念sama閱讀 48,388評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像萌业,于是被迫代替她去往敵國(guó)和親奸柬。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評(píng)論 2 355

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