《STL源碼剖析》筆記:list

對(duì)于vector而言,list就要復(fù)雜得多济赎,list 有2個(gè)特點(diǎn):

  • 相較于vector记某,它的好處是每次插入一個(gè)或刪除一個(gè)元素,就配置或釋放一個(gè)元素空間壳猜。所以list對(duì)空間不浪費(fèi)滑凉。
  • 對(duì)于任何位置的元素插入或者元素移除,list永遠(yuǎn)是常數(shù)時(shí)間畅姊。

list結(jié)構(gòu)是雙向循環(huán)鏈表:

list.png

結(jié)點(diǎn)內(nèi)存管理

list node
  • 結(jié)點(diǎn)
    struct ListNode {
          ListNode *_prev;
          ListNode *_next;
          T _data;
      };
    
構(gòu)造結(jié)點(diǎn)
  • 第1個(gè)版本為構(gòu)造有數(shù)據(jù)域結(jié)點(diǎn)
  • 第2個(gè)版本構(gòu)造沒(méi)有數(shù)據(jù)域結(jié)點(diǎn)
template<typename T>
typename List<T>::nodePtr List<T>::createListNode(const T &value) {
    nodePtr ptrTmp = nodeAlloc::allocate();
    ptrTmp->_prev = nullptr;
    ptrTmp->_next = nullptr;
    allocator<T>::construct(&(ptrTmp->_data), value);

    return ptrTmp;
}

template<typename T>
typename List<T>::nodePtr List<T>::createListNode() {
    nodePtr ptrTmp = nodeAlloc::allocate();
    ptrTmp->_prev = nullptr;
    ptrTmp->_next = nullptr;

    return ptrTmp;
}
銷毀結(jié)點(diǎn)
template<typename T>
    void List<T>::deleteNode(nodePtr p) {
    allocator<T>::destroy(&(p->_data));
    nodeAlloc::deallocate(p);
}

迭代器

list不再能夠像vecctor一樣以普通指針作為迭代器朱嘴,因?yàn)槠涔?jié)點(diǎn)不保證在存儲(chǔ)空間中連續(xù)存在粗合。所以list迭代器必須有能力指向list的節(jié)點(diǎn)乌昔,并有能力進(jìn)行正確的遞增帚湘,遞減,取值,成員存取等操作资柔。

并且list是一個(gè)雙向鏈表撵割,迭代器必須具備前移,后移的能力羹与。庶灿,所以List提供的是一個(gè)Bidirectional iterators

由于是鏈表往踢,一個(gè)重要性質(zhì)就是:插入操作和節(jié)后操作都不會(huì)造成原有的list迭代器失效

struct ListIterator : public iterator<bidirectional_iterator_tag, T> {
    ......
    typedef ListNode<T> *nodePtr;
    
    nodePtr p;
}

插入元素

void push_back(const T &value)
void List<T>::push_back(const T &value){
    if (empty()) {
        nodePtr ptrTmp = createListNode(value);
        ptrTmp->_prev = nullptr;
        _end.p->_prev = ptrTmp;
        ptrTmp->_next = _end.p;
        _begin.p = ptrTmp;
    } else {
        nodePtr ptrTmp = createListNode(value);
        nodePtr oldEndPrevNode = _end.p->_prev;

        oldEndPrevNode->_next = ptrTmp;
        ptrTmp->_prev = oldEndPrevNode;
        ptrTmp->_next = _end.p;
        _end.p->_prev = ptrTmp;
    }
}
  • 空l(shuí)ist插入第一個(gè)節(jié)點(diǎn)


    空l(shuí)ist插入第一個(gè)節(jié)點(diǎn).png
  • 非空l(shuí)ist插入節(jié)點(diǎn)


    非空l(shuí)ist插入節(jié)點(diǎn).png
void push_front(const T& value)
void List<T>::push_front(const T &value) {
    auto ptrTmp = createListNode(value);
    auto oldStartNode = _begin.p;
    oldStartNode->_prev = ptrTmp;

    ptrTmp->_prev = nullptr;
    ptrTmp->_next = oldStartNode;

    _begin.p = ptrTmp;
}
push_front.png
iterator insert(iterator position, const T& val)
  • 3種情況:
    • position == _begin
      push_front(val)
    • position == _end
      push_back(val)
    • position 等于中間節(jié)點(diǎn)
if (position == begin()) {
    push_front(val);
    return begin();
} 
else if (position == end()) {
    auto ret = position;
    push_back(val);
    return ret;
}
auto node = createListNode(val);
(position.p->_prev)->_next = node;
node->_next = position.p;
node->_prev = (position.p)->_prev;
(position.p)->_prev = node;

return iterator(node);
position 等于中間節(jié)點(diǎn).png
void insert(iterator position, size_type n, const T& value)
void List<T>::insert(iterator position, size_type n, const T& value)
{
    for (auto i = n; i != 0; --i)
        position = insert(position, value);
}
void insert(iterator position, InputIterator first, InputIterator last)
void List<T>::insert(iterator position, InputIterator first, InputIterator last) 
{
    for (; first != last; first++)           
        position = insert(position, *first);
}

刪除節(jié)點(diǎn)

void pop_front()
if (empty())
    throw std::out_of_range("pop_front() on empty List");
auto oldNode = _begin.p;
_begin.p = oldNode->_next;
_begin.p->_prev = nullptr;
deleteNode(oldNode);
pop_front.png
void pop_back()
if (empty())
    throw std::out_of_range("pop_back() on empty List");

auto new_end_p = _end.p->_prev;
new_end_p->_next = nullptr;
allocator<T>::destroy(&(new_end_p->_data));     // 析構(gòu)元素

nodeAlloc::deallocate(_end.p);  // 釋放原_end.p內(nèi)存
_end.p = new_end_p;
iterator erase(iterator position)
  • 分為3種情況:
    • 刪除_begin
    • 刪除_end
    • 刪除中間節(jié)點(diǎn)
if (position == _begin) {
    pop_front();
    return _begin;
}
else if (position == _end) {
    pop_back();
    return _end;
}
else {
    auto prevNode = position.p->_prev;
    auto nextNode = position.p->_next;

    prevNode->_next = nextNode;
    nextNode->_prev = prevNode;
    deleteNode(position.p);
            
    return iterator(nextNode);
}

反轉(zhuǎn)list

void reverse()

去重

void unique()
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末猪贪,一起剝皮案震驚了整個(gè)濱河市讯私,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌妄帘,老刑警劉巖抡驼,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異碎税,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)雷蹂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門匪煌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人萎庭,你說(shuō)我怎么就攤上這事‰攘玻” “怎么了吗购?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)镀梭。 經(jīng)常有香客問(wèn)我贯底,道長(zhǎng),這世上最難降的妖魔是什么禽捆? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任胚想,我火速辦了婚禮,結(jié)果婚禮上浊服,老公的妹妹穿的比我還像新娘。我一直安慰自己愁憔,他們只是感情好孽拷,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著膜宋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪史简。 梳的紋絲不亂的頭發(fā)上肛著,一...
    開(kāi)封第一講書(shū)人閱讀 49,166評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音策泣,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛火本,可吹牛的內(nèi)容都是我干的钙畔。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼簿盅,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼揍魂!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起现斋,我...
    開(kāi)封第一講書(shū)人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤庄蹋,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后限书,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡能真,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年舟陆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片秦躯。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡踱承,死狀恐怖倡缠,靈堂內(nèi)的尸體忽然破棺而出茎活,到底是詐尸還是另有隱情,我是刑警寧澤盾饮,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布懒熙,位于F島的核電站,受9級(jí)特大地震影響徘钥,放射性物質(zhì)發(fā)生泄漏肢娘。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一而钞、第九天 我趴在偏房一處隱蔽的房頂上張望畴博。 院中可真熱鬧笨忌,春花似錦俱病、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)果元。三九已至犀盟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間倡怎,已是汗流浹背贱枣。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留纽哥,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓晓避,卻偏偏與公主長(zhǎng)得像只壳,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

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