STL與泛型編程 week 3 (Boolan)

deque&queue和stack深度探索

deque的定義(C++ Primer):

Sequential container. Elements in a deque can be accessed by their positional index. Supports fast random access to elements. Like a vector in all respects except that it supports fast insertion and deletion at the front of the container as well as at the back and does not relocate elements as a result of insertions or deletions at either end.

  • deque是雙向開(kāi)口容器漫试,它模擬了一個(gè)連續(xù)的存儲(chǔ)空間(實(shí)質(zhì)為連續(xù)分段的容器)医清,其中buffer和元素結(jié)點(diǎn)設(shè)計(jì)如下圖所示:


    stl3_1.png

    其中buffer為deque的緩沖區(qū), 每個(gè)buffer可以存放多個(gè)元素結(jié)點(diǎn), 而每個(gè)buffer指針存放在vector容器中.

  • G2.9版的deque:


    stl3_02.png
  • deque的iterator (deque如何模擬連續(xù)空間, 全都是deque iterator的功勞):


    stl3-03.png

    每個(gè)iterator有四個(gè)指針: cur(當(dāng)前數(shù)據(jù)結(jié)點(diǎn)的指針)喊儡、first(buffer首指針)、last(buffer的尾指針)甩卓、node(node表示這個(gè)iterator在vector中的指針地址).

G2.9版queue:


stl3-04.png

G2.9版stack:


stl3-05.png

容器rb_tree

Red-Black tree (紅黑樹(shù)) 是平衡二元搜尋樹(shù) (balanced binary search tree) 中常被使用的一種. 平衡二元搜尋樹(shù)的特征: 排列規(guī)則有利于search 和 insert, 并保持適度平衡----無(wú)任何節(jié)點(diǎn)過(guò)深.

rb_tree提供"遍歷"操作及iterators. 按正常規(guī)則(++ite)遍歷, 便能獲得排序狀態(tài).

我們不應(yīng)使用rb_tree的iteraotr改變?cè)刂?因?yàn)樵赜衅鋰?yán)謹(jǐn)?shù)呐帕幸?guī)則). 編程層面(programming level)并未阻絕此事. 如此設(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ù).

G2.9版rb_tree:

template <class Key,
          class Value,
          class KeyOfValue,
          class Compare,
          class Alloc = alloc>
class rb_tree {
 protected:
  typedef  __rb_tree_node<Value> rb_tree_node;
  ...
 public:
  typedef rb_tree_node* link_type;
  ...
 protected:
  // RB-tree 只有三筆資料表現(xiàn)自己
  size_type node_count;  // rb_tree的大小(節(jié)點(diǎn)數(shù)量)
  link_type header;
  Compare key_compare;  // Key的大小比較準(zhǔn)則: 應(yīng)會(huì)是個(gè)function object
};
  • 定義一個(gè)簡(jiǎn)單rb_tree class的對(duì)象:
template <class Arg, class Result>
struct unary_function {
  typedef Arg argument_type;
  typedef Result result_type;
};

template <class Arg1, class Arg2, class Result>
struct binary_function {
  typedef Arg1 first_argument_type;
  typedef Arg2 first_argument_type;
  typedef Result result_type;
};

template <class T>
struct identity : public unary_function<T, T> {
  const T& operator()(const T &x) const { return x; }
};

template <class T>
struct less : public binary_function <T, T, bool> {
  bool operator() (const T &x, const T &y) const 
  { return x < y; }
};
  • 容器rb_tree的用例
rb_tree<int, int, identity<int>, less<int>> itree;
cout << itree.empty() << endl;  // 1
cout << itree.size() << endl;  // 0

itree.insert_unique(3);
itree.insert_unique(8);
itree.insert_unique(5);
itree.insert_unique(9);
itree.insert_unique(13);
itree.insert_unique(5);  // 不會(huì)有用, 因?yàn)檫@里是insert_unique()
cout << itree.empty() << endl;  // 0
cout << itree.size() << endl;  // 5
cout << itree.count(5) << endl;  // 1

itree.insert_equal(5);
itree.insert_equal(5);
cout << itree.size() << endl;  // 7, since using insert_equal().
cout << itree.count(5) << endl;  // 3

紅黑樹(shù)的特性 (摘自Introduction to algorithms)

A red-black tree is a binary search tree with one extra bit of storage per node: its color, which can be either RED or BLACK . By constraining the node colors on any simple path from the root to a leaf, red-black trees ensure that no such path is more than twice as long as any other, so that the tree is approximately balanced.
Each node of the tree now contains the attributes color, key, left, right, and p. If a child or the parent of a node does not exist, the corresponding pointer attribute of the node contains the value NIL . We shall regard these NIL s as being pointers to leaves (external nodes) of the binary search tree and the normal, key-bearing nodes as being internal nodes of the tree.
A red-black tree is a binary tree that satisfies the following red-black properties:

  • Every node is either red or black.
  • The root is black.
  • Every leaf ( NIL ) is black.
  • If a node is red, then both its children are black.
  • For each node, all simple paths from the node to descendant leaves contain the same number of black nodes.

容器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的iterator改變?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().

  • G2.9版set:
template <class Key,
          class Compare = less<Key>,
          class Alloc = alloc>
class set {
 public:
  // typedefs:
  typedef Key key_type;
  typedef Key value_type;
  typedef Compare key_compare;
  typedef Compare value_compare;
 private:
  typedef rb_tree<key_type, value_type, 
                  identity<value_type>, key_compare, Alloc> rep_type;
  rep_type t;
 public:
  typedef typename rep_type::const_iterator iterator;
...
};

容器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)排序規(guī)則)状知, 但可以用它來(lái)改變?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().

G2.9版map:

template <class Key,
          class T,
          class Compare = less<Key>,
          class Alloc = alloc>
class map {
 public:
  typedef Key key_type;
  typedef T data_type;
  typedef T mapped_type;
  typedef pair<const Key, T> value_type;
  typedef Compare key_compare;
 private:
  typedef rb_tree<key_type, value_type, 
                  select1st<value_type>, key_compare, Alloc> rep_type;
  rep_type t;
 public:
  typedef typename rep_type::iterator iterator;
...
};

容器hashtable

  • G2.9版hashtable:
template <class Value>
struct __hashtable_node {
  __hashtable_node *next;
  Value val;
};

template <class Value, class Key, class HashFun,
          class ExtractKey, class EqualKey
          class Alloc = alloc>
class hashtable {
 public:
  typedef HashFcn hasher;
  typedef EqualKey key_equal;
  typedef size_t size_type;

 private:
  hasher hash;
  key_equal equals;
  ExtractKey get_key;

  typedef __hashtable_node<Vlaue> node;

  vector<node*, Alloc> buckets;
  size_type num_elements;
 public:
  size_type bucket_count() const { return buckets.size(); }
};

template <class Value, class Key,
          class HashFcn, class ExtractKey,
          class EqualKey, class Alloc>
struct __hashtable_iterator {
...
  mode *cur;
  hashtable *ht;
};
  • hashtable用例:
struct eqstr {
  bool operator()(const char *s1, const char *s2) const
  { return strcmp(s1, s2) == 0; }
};

hashtable <const char*,
           const char*,
           hash<const char*>,
           identity<const char*>,
           eqstr,
           alloc>
ht(50, hash<const char*>(), eqstr());

ht.insert_unique("kiwi");
ht.insert_unique("plum");
ht.insert_unique("apple");

hash-function, hash-code

// 泛化
template <class Key> struct hash { };

// 特化
template <> struct hash <char> {
  size_t operator() (char x) const { return x; }
};

template <> struct hash <short> {
  size_t operator() (short x) const { return x; }
};

template <> struct hash <unsigned short> {
  size_t operator() (unsigned short x) const { return x; }
};

template <> struct hash <int> {
  size_t operator() (int x) const { return x; }
};

template <> struct hash <unsigned int> {
  size_t operator() (unsigned int x) const { return x; }
};

template <> struct hash <long> {
  size_t operator() (long x) const { return x; }
};

template <> struct hash <unsigned long> {
  size_t operator() (unsigned long x) const { return x; }
};
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末西设,一起剝皮案震驚了整個(gè)濱河市起宽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌济榨,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,273評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件绿映,死亡現(xiàn)場(chǎng)離奇詭異擒滑,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)叉弦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門(mén)丐一,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人淹冰,你說(shuō)我怎么就攤上這事库车。” “怎么了樱拴?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,709評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵柠衍,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我晶乔,道長(zhǎng)珍坊,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,520評(píng)論 1 296
  • 正文 為了忘掉前任正罢,我火速辦了婚禮阵漏,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘翻具。我一直安慰自己履怯,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,515評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布裆泳。 她就那樣靜靜地躺著叹洲,像睡著了一般。 火紅的嫁衣襯著肌膚如雪工禾。 梳的紋絲不亂的頭發(fā)上疹味,一...
    開(kāi)封第一講書(shū)人閱讀 52,158評(píng)論 1 308
  • 那天仅叫,我揣著相機(jī)與錄音,去河邊找鬼糙捺。 笑死诫咱,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的洪灯。 我是一名探鬼主播坎缭,決...
    沈念sama閱讀 40,755評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼签钩!你這毒婦竟也來(lái)了掏呼?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,660評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤铅檩,失蹤者是張志新(化名)和其女友劉穎憎夷,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體昧旨,經(jīng)...
    沈念sama閱讀 46,203評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拾给,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,287評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了兔沃。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蒋得。...
    茶點(diǎn)故事閱讀 40,427評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖乒疏,靈堂內(nèi)的尸體忽然破棺而出额衙,到底是詐尸還是另有隱情,我是刑警寧澤怕吴,帶...
    沈念sama閱讀 36,122評(píng)論 5 349
  • 正文 年R本政府宣布窍侧,位于F島的核電站,受9級(jí)特大地震影響转绷,放射性物質(zhì)發(fā)生泄漏疏之。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,801評(píng)論 3 333
  • 文/蒙蒙 一暇咆、第九天 我趴在偏房一處隱蔽的房頂上張望锋爪。 院中可真熱鬧,春花似錦爸业、人聲如沸其骄。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,272評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)拯爽。三九已至,卻和暖如春钧忽,著一層夾襖步出監(jiān)牢的瞬間毯炮,已是汗流浹背逼肯。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,393評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留桃煎,地道東北人篮幢。 一個(gè)月前我還...
    沈念sama閱讀 48,808評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像为迈,于是被迫代替她去往敵國(guó)和親三椿。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,440評(píng)論 2 359

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