3-2. 順序容器-list

目錄

  • 概要
  • 結(jié)構(gòu)
  • 重要函數(shù)
  • 總結(jié)

概要

如果vector對(duì)應(yīng)邏輯的array, list對(duì)應(yīng)是double-link-list, 避免大obj占用連續(xù)內(nèi)存, 雙向可訪問, 沒有隨機(jī)訪問的特性

結(jié)構(gòu)

list這塊兒結(jié)構(gòu)對(duì)仗比較工整, list_node作為內(nèi)部成員, list_iter作為接口形式出現(xiàn)


list中_M_node既是頭結(jié)點(diǎn), 它的next指向第一個(gè)節(jié)點(diǎn), 如果回環(huán)指向自己既是空l(shuí)ist


重要函數(shù)

通過(guò)基本insert, delete符合出及其精彩的操作

//internal create node
  _Node* _M_create_node(const _Tp& __x)
  {
    _Node* __p = _M_get_node();
    __STL_TRY {
      _Construct(&__p->_M_data, __x);
    }
    __STL_UNWIND(_M_put_node(__p));
    return __p;
  }

  _Node* _M_create_node()
  {
    _Node* __p = _M_get_node();
    __STL_TRY {
      _Construct(&__p->_M_data);
    }
    __STL_UNWIND(_M_put_node(__p));
    return __p;
  }

iterator begin()             { return (_Node*)(_M_node->_M_next); 
iterator end()             { return _M_node; }

//insert before __position
iterator insert(iterator __position, const _Tp& __x) {
    _Node* __tmp = _M_create_node(__x);
    __tmp->_M_next = __position._M_node;
    __tmp->_M_prev = __position._M_node->_M_prev;
    __position._M_node->_M_prev->_M_next = __tmp;
    __position._M_node->_M_prev = __tmp;
    return __tmp;
  }

void push_front(const _Tp& __x) { insert(begin(), __x); }
list<_Tp, _Alloc>::insert(iterator __position, 
                          const _Tp* __first, const _Tp* __last)
{
  for ( ; __first != __last; ++__first)
    insert(__position, *__first);
}

list<_Tp, _Alloc>::_M_fill_insert(iterator __position,
                                  size_type __n, const _Tp& __x)
{
  for ( ; __n > 0; --__n)
    insert(__position, __x);
}

//erase @__position
  iterator erase(iterator __position) {
    _List_node_base* __next_node = __position._M_node->_M_next;
    _List_node_base* __prev_node = __position._M_node->_M_prev;
    _Node* __n = (_Node*) __position._M_node;
    __prev_node->_M_next = __next_node;
    __next_node->_M_prev = __prev_node;
    _Destroy(&__n->_M_data);
    _M_put_node(__n);
    return iterator((_Node*) __next_node);
  }

typename list<_Tp,_Alloc>::iterator list<_Tp, _Alloc>::erase(iterator __first, 
                                                             iterator __last)
{
  while (__first != __last)
    erase(__first++);
  return __last;
}

template <class _Tp, class _Alloc>
void list<_Tp, _Alloc>::resize(size_type __new_size, const _Tp& __x)
{
  iterator __i = begin();
  size_type __len = 0;
  for ( ; __i != end() && __len < __new_size; ++__i, ++__len)
    ;
  if (__len == __new_size)
    erase(__i, end()); //original size greater
  else                          // __i == end(), pad new elements
    insert(end(), __new_size - __len, __x);
}

list<_Tp, _Alloc>& list<_Tp, _Alloc>::operator=(const list<_Tp, _Alloc>& __x)
{
  if (this != &__x) {
    iterator __first1 = begin();
    iterator __last1 = end();
    const_iterator __first2 = __x.begin();
    const_iterator __last2 = __x.end();
    while (__first1 != __last1 && __first2 != __last2) 
      *__first1++ = *__first2++;
    if (__first2 == __last2)
      erase(__first1, __last1);
    else
      insert(__last1, __first2, __last2);
  }
  return *this;
}

  template <class _InputIterator>
  list(_InputIterator __first, _InputIterator __last,
       const allocator_type& __a = allocator_type())
    : _Base(__a)
    { insert(begin(), __first, __last); }

void list<_Tp, _Alloc>::remove(const _Tp& __value)
{
  iterator __first = begin();
  iterator __last = end();
  while (__first != __last) {
    iterator __next = __first;
    ++__next;
    if (*__first == __value) erase(__first);
    __first = __next;
  }
}

void list<_Tp, _Alloc>::unique()
{
  iterator __first = begin();
  iterator __last = end();
  if (__first == __last) return;
  iterator __next = __first;
  while (++__next != __last) {
    if (*__first == *__next)
      erase(__next);
    else
      __first = __next;
    __next = __first;
  }
}

//brilliant
inline void __List_base_reverse(_List_node_base* __p)
{
  _List_node_base* __tmp = __p;
  do {
    __STD::swap(__tmp->_M_next, __tmp->_M_prev);
    __tmp = __tmp->_M_prev;     // Old next node is now prev.
  } while (__tmp != __p);
}

transfer, splice, merge, sort實(shí)現(xiàn)
splice的語(yǔ)義是:移動(dòng)預(yù)算進(jìn)入當(dāng)前l(fā)ist


void transfer(iterator __position, iterator __first, iterator __last)語(yǔ)義是從__first到__last插入當(dāng)前的__position

  void transfer(iterator __position, iterator __first, iterator __last) {
    if (__position != __last) {
      // Remove [first, last) from its old position.
      __last._M_node->_M_prev->_M_next     = __position._M_node;//① 
      __first._M_node->_M_prev->_M_next    = __last._M_node;//②
      __position._M_node->_M_prev->_M_next = __first._M_node; //③

      // Splice [first, last) into its new position.
      _List_node_base* __tmp      = __position._M_node->_M_prev;
      __position._M_node->_M_prev = __last._M_node->_M_prev;//④
      __last._M_node->_M_prev     = __first._M_node->_M_prev; //⑤
      __first._M_node->_M_prev    = __tmp; //⑥
    }
  }

例如待插入list是 0<->f <-> 1<-> 2 <-> 3 <-> l <-> 4, __position(p)情況是: x <-> p <-> y


應(yīng)用transfer如下:

  void splice(iterator __position, list& __x) {
    if (!__x.empty()) 
      this->transfer(__position, __x.begin(), __x.end()); //all
  }
  void splice(iterator __position, list&, iterator __i) {
    iterator __j = __i;
    ++__j;
    if (__position == __i || __position == __j) return;
    this->transfer(__position, __i, __j); // single
  }
  void splice(iterator __position, list&, iterator __first, iterator __last) {
    if (__first != __last) 
      this->transfer(__position, __first, __last); // f -> l
  }
//classical merge
void list<_Tp, _Alloc>::merge(list<_Tp, _Alloc>& __x)
{
  iterator __first1 = begin();
  iterator __last1 = end();
  iterator __first2 = __x.begin();
  iterator __last2 = __x.end();
  while (__first1 != __last1 && __first2 != __last2)
    if (*__first2 < *__first1) {
      iterator __next = __first2;
      transfer(__first1, __first2, ++__next); //merge one 
      __first2 = __next;
    }
    else
      ++__first1;
  if (__first2 != __last2) transfer(__last1, __first2, __last2);
}

最后還有一個(gè)list sort代碼如下

void list<_Tp, _Alloc>::sort()
{
  // Do nothing if the list has length 0 or 1.
  if (_M_node->_M_next != _M_node && _M_node->_M_next->_M_next != _M_node) {
    list<_Tp, _Alloc> __carry;
    list<_Tp, _Alloc> __counter[64];
    int __fill = 0;
    while (!empty()) {
      __carry.splice(__carry.begin(), *this, begin());
      int __i = 0;
      while(__i < __fill && !__counter[__i].empty()) {
        __counter[__i].merge(__carry);
        __carry.swap(__counter[__i++]);
      }
      __carry.swap(__counter[__i]);         
      if (__i == __fill) ++__fill;
    } 

    for (int __i = 1; __i < __fill; ++__i)
      __counter[__i].merge(__counter[__i-1]);
    swap(__counter[__fill-1]);
  }
}

最大允許長(zhǎng)度是∑ 2^(i - 1) i = 1 -> 64, carry是每一輪中間見過(guò), 每一次內(nèi)部循環(huán)把它歸并放入對(duì)應(yīng)長(zhǎng)度的counter
以一個(gè)例子看下流程:



每個(gè)小數(shù)子i的迭代次數(shù)
代碼注釋如下:


總結(jié)

list在iter的體系下, 通過(guò)提煉精簡(jiǎn)的如insert, erase操作, 急進(jìn)美妙的組合形成了很多優(yōu)美的函數(shù), 精煉且易懂

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市统抬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌门烂,老刑警劉巖习贫,帶你破解...
    沈念sama閱讀 216,324評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件逛球,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡苫昌,警方通過(guò)查閱死者的電腦和手機(jī)颤绕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)祟身,“玉大人奥务,你說(shuō)我怎么就攤上這事⊥嗔颍” “怎么了氯葬?”我有些...
    開封第一講書人閱讀 162,328評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)婉陷。 經(jīng)常有香客問我帚称,道長(zhǎng),這世上最難降的妖魔是什么秽澳? 我笑而不...
    開封第一講書人閱讀 58,147評(píng)論 1 292
  • 正文 為了忘掉前任闯睹,我火速辦了婚禮,結(jié)果婚禮上担神,老公的妹妹穿的比我還像新娘楼吃。我一直安慰自己,他們只是感情好妄讯,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評(píng)論 6 388
  • 文/花漫 我一把揭開白布孩锡。 她就那樣靜靜地躺著,像睡著了一般捞挥。 火紅的嫁衣襯著肌膚如雪浮创。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,115評(píng)論 1 296
  • 那天砌函,我揣著相機(jī)與錄音斩披,去河邊找鬼。 笑死讹俊,一個(gè)胖子當(dāng)著我的面吹牛垦沉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播仍劈,決...
    沈念sama閱讀 40,025評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼厕倍,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了贩疙?” 一聲冷哼從身側(cè)響起讹弯,我...
    開封第一講書人閱讀 38,867評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤况既,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后组民,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體棒仍,經(jīng)...
    沈念sama閱讀 45,307評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評(píng)論 2 332
  • 正文 我和宋清朗相戀三年臭胜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了莫其。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,688評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡耸三,死狀恐怖乱陡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情仪壮,我是刑警寧澤憨颠,帶...
    沈念sama閱讀 35,409評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站睛驳,受9級(jí)特大地震影響烙心,放射性物質(zhì)發(fā)生泄漏膜廊。R本人自食惡果不足惜乏沸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望爪瓜。 院中可真熱鬧蹬跃,春花似錦、人聲如沸铆铆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)薄货。三九已至翁都,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間谅猾,已是汗流浹背柄慰。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留税娜,地道東北人坐搔。 一個(gè)月前我還...
    沈念sama閱讀 47,685評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像敬矩,于是被迫代替她去往敵國(guó)和親概行。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評(píng)論 2 353

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

  • 第一章 1.9 令人困惑的語(yǔ)法 1.9.1 stl_config.h中的各種組態(tài)(configurations) ...
    鏡中無(wú)我閱讀 1,026評(píng)論 0 0
  • 空間配置器 分為第一級(jí)空間配置器弧岳,和第二級(jí)空間配置器 配合使用 第一級(jí)空間配置器分配大內(nèi)存大于128bytes...
    陳星空閱讀 1,278評(píng)論 0 1
  • 所謂順序容器(sequential containers)凳忙,其中的元素都可序(ordered)业踏,但未必有序(sor...
    toMyLord閱讀 727評(píng)論 0 3
  • 前言: 詳細(xì)介紹: List:元素有放入順序,元素可重復(fù)Map:元素按鍵值對(duì)存儲(chǔ)胎撤,無(wú)放入順序Set:元素?zé)o放入順序...
    YBshone閱讀 8,649評(píng)論 0 17
  • 概要 vector是stl最常用的順序容器, 使用簡(jiǎn)單, 動(dòng)態(tài)擴(kuò)展, 隨機(jī)訪問, 在stg-stl framewo...
    db24cc閱讀 196評(píng)論 0 0