国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

[C/C++]詳解STL容器3--list的功能和模擬實現(xiàn)(迭代器失效問題)

amc / 911人閱讀

摘要:本文介紹了的常用接口的使用,并對其進(jìn)行了模擬實現(xiàn),包括迭代器的實現(xiàn)。與為反向迭代器,對迭代器執(zhí)行操作,迭代器向前移動。

本文介紹了list的常用接口的使用,并對其進(jìn)行了模擬實現(xiàn),包括list迭代器的實現(xiàn)。

目錄

一、list的介紹

二、list的常用接口的使用

1. list的構(gòu)造

2. list iterator的使用

3.list capacity的使用

4.list element access

5.list modifiers

6. list的迭代器失效

三、list與vector的對比

四、list的模擬實現(xiàn)


一、list的介紹

list 容器,又稱雙向鏈表容器,即該容器的底層是以雙向鏈表的形式實現(xiàn)的。這意味著,list 容器中的元素可以分散存儲在內(nèi)存空間里,而不是必須存儲在一整塊連續(xù)的內(nèi)存空間中。結(jié)構(gòu)如圖。

?list是可以在常數(shù)范圍內(nèi)在任意位置進(jìn)行插入和刪除的序列式容器,并且該容器可以前后雙向迭代

list與forward_list非常相似:最主要的不同在于forward_list是單鏈表,只能朝前迭代,已讓其更簡單高效。

?與其他的序列式容器相比(array,vector,deque),list通常在任意位置進(jìn)行插入、移除元素的執(zhí)行效率更好。最大的缺陷是不支持任意位置的隨機訪問,必須從已知的位置(比如頭部或者尾部)迭代到該位置,在這段位置上迭代需要線性的時間;list還需要一些額外的空間,以保存每個節(jié)點的相關(guān)聯(lián)信息。

二、list的常用接口的使用

1. list的構(gòu)造

構(gòu)造函數(shù)( (constructor))接口說明
list()構(gòu)造空的list
list (size_type n, const value_type& val = value_type())構(gòu)造的list中包含n個值為val的元素
list (const list& x)拷貝構(gòu)造函數(shù)
list (InputIterator first, InputIterator last)用[first, last)區(qū)間中的元素構(gòu)造list
#include #include int main (){    std::list a; // 構(gòu)造空的a    std::list b (4,1); // b中放4個值為100的元素    std::list c (b.begin(), b.end()); // 用b的[begin(), end())左閉右開的區(qū)間構(gòu)造c    std::list d (c); // 用c拷貝構(gòu)造d    // 以數(shù)組為迭代器區(qū)間構(gòu)造e    int array[] = {16,2,77,29};    std::list e (array, array + sizeof(array) / sizeof(int) );    // 用迭代器方式打印e中的元素    for(std::list::iterator it = e.begin(); it != e.end(); it++)        std::cout << *it << " ";    std::cout<

2. list iterator的使用

函數(shù)聲明接口說明
begin + end返回第一個元素的迭代器+返回最后一個元素下一個位置的迭代器
rbegin + rend返回第一個元素的reverse_iterator,即end位置,返回最后一個元素下一個位置的reverse_iterator,即begin位置

begin與end為正向迭代器,對迭代器執(zhí)行++操作,迭代器向后移動。
rbegin(end)與rend(begin)為反向迭代器,對迭代器執(zhí)行++操作,迭代器向前移動。

?

#include using namespace std;#include void print_list(const list& l){    // 注意這里調(diào)用的是list的 begin() const,返回list的const_iterator對象    for (list::const_iterator it = l.begin(); it != l.end(); ++it)    {        cout << *it << " ";        // *it = 10; 編譯不通過    }    cout << endl;}int main(){    int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };    list l(array, array + sizeof(array) / sizeof(array[0]));    // 使用正向迭代器正向list中的元素    for (list::iterator it = l.begin(); it != l.end(); ++it)        cout << *it << " ";    cout << endl;    // 使用反向迭代器逆向打印list中的元素    for (list::reverse_iterator it = l.rbegin(); it != l.rend(); ++it)        cout << *it << " ";    cout << endl;    return 0;}

3.list capacity的使用

函數(shù)聲明接口說明
empty檢測list是否為空,是返回true,否則返回false
size返回list中有效節(jié)點的個數(shù)

4.list element access

函數(shù)聲明接口說明
front返回list的第一個節(jié)點中值的引用
back返回list的最后一個節(jié)點中值的引用

5.list modifiers

函數(shù)聲明接口說明
push_front在list首元素前插入值為val的元素
pop_front刪除list中第一個元素
push_back在list尾部插入值為val的元素
pop_back刪除list中最后一個元素
insert在list position 位置中插入值為val的元素
erase刪除list position位置的元素
swap交換兩個list中的元素
clear清空list中的有效元素

6. list的迭代器失效

此處可將迭代器暫時理解成類似于指針,迭代器失效即迭代器所指向的節(jié)點的無效,即該節(jié)點被刪除了。因為list的底層結(jié)構(gòu)為帶頭結(jié)點的雙向循環(huán)鏈表,因此在list中進(jìn)行插入時是不會導(dǎo)致list的迭代器失效的,只有在刪除時才會失效,并且失效的只是指向被刪除節(jié)點的迭代器,其他迭代器不會受到影響。

三、list與vector的對比

vectorlist


結(jié)
構(gòu)
動態(tài)順序表,一段連續(xù)空間帶頭結(jié)點的雙向循環(huán)鏈表



支持隨機訪問,訪問某個元素效率O(1)不支持隨機訪問,訪問某個元素效率O(N)




任意位置插入和刪除效率低,需要搬移元素,時間復(fù)雜度為O(N),插入時有可能需要增容,增容:開辟新空間,拷貝元素,釋放舊空間,導(dǎo)致效率更低




底層為連續(xù)空間,不容易造成內(nèi)存碎片,空間利用率高,緩存利用率高底層節(jié)點動態(tài)開辟,小節(jié)點容易造成內(nèi)存碎片,空間利用率低,緩存利用率低


原生態(tài)指針對原生態(tài)指針(節(jié)點指針)進(jìn)行封裝




在插入元素時,要給所有的迭代器重新賦值,因為插入元素有可能會導(dǎo)致重新擴容,致使原來迭代器失效,刪除時,當(dāng)前迭代器需要重新賦值否則會失效插入元素不會導(dǎo)致迭代器失效,刪除元素時,只會導(dǎo)致當(dāng)前迭代器失效,其他迭代器不受影響
使


需要高效存儲,支持隨機訪問,不關(guān)心插入刪除效率大量插入和刪除操作,不關(guān)心隨機訪問

四、list的模擬實現(xiàn)

?list的模擬實現(xiàn)十分有趣,這里需要注意,list本身和list的節(jié)點是不同的結(jié)構(gòu),所以需要分開設(shè)計。成員都是只需淺拷貝,所以拷貝構(gòu)造,析構(gòu) ,重載 = 都可以使用默認(rèn)。

list?iterator也需要多帶帶設(shè)計,因為原生指針已經(jīng)無法滿足迭代器需求,所以需要封裝,讓它像一個指針一樣完成訪問操作。

通過template 區(qū)別T&,*T。

#include #include #include #include #include #include using namespace std;namespace Zht{  template     struct _list_node     //list本身和list的節(jié)點是不同的結(jié)構(gòu),所以需要分開設(shè)計,這里是list節(jié)點的結(jié)構(gòu)  {      T val;              //數(shù)據(jù)      _list_node* _next;       //下一個節(jié)點指針      _list_node* _prev;       //上一個            _list_node(const T& val = T())      //構(gòu)造節(jié)點        :val(val)                         //傳的參        ,_prev(nullptr)        ,_next(nullptr)      {                }  };  template   struct _list_iterator   {    typedef _list_node node;    typedef _list_iterator self;    node* _pnode;      //迭代器本質(zhì)上是指針    _list_iterator(node* pnode)     //構(gòu)造函數(shù)      :_pnode(pnode)    {    }    //這里,成員都是只需淺拷貝,所以拷貝構(gòu)造,析構(gòu) ,重載 = 都可以使用默認(rèn)       Ref operator*()       //重載*,通過Ref靈活的調(diào)整const和普通。    {      return _pnode->val;    }    bool operator!=(const self& s) const     {      return _pnode != s._pnode;    }    bool operator==(const self& s) const     {      return _pnode == s._pnode;    }    self& operator++()            //++就是指向下一個節(jié)點    {      _pnode = _pnode->_next;      return *this;    }    self operator++(int)          //C++規(guī)定后綴調(diào)用需要有一個int型參數(shù)作為區(qū)分前綴與后綴調(diào)用的區(qū)別    {      self tmp (*this);      ++*this;      return tmp;                 //*this++后++    }    self& operator--()    {      _pnode = _pnode->_prev;      return *this;    }    self operator--(int)    {      self tmp (*this);      --*this;      return tmp;    }    Ptr operator->()    {      return &(operator*());          }  };  template   class list  {      typedef _list_node node;  public:      typedef _list_iterator iterator;      typedef _list_iterator const_iterator;      list()      //構(gòu)造函數(shù),構(gòu)造哨兵位      {          _head = new node;           //開一個節(jié)點          _head->_next = _head;       //初始化節(jié)點          _head->_prev = _head;      }      template       list(Iterator first, Iterator last)      {        _head = new node;        _head->_next = _head;        _head->_prev = _head;        while(first != last)        {          push_back(*first);          first++;        }      }      list(const list& It)      {        _head = new node;                   //構(gòu)造哨兵節(jié)點        _head->_next = _head;             _head->_prev = _head;        for(const auto& e : It)             //逐個尾插        {          push_back(e);        }      }      list& operator=(list It)      {        swap(_head, It._head);        return *this;      }      ~list()      {        clear();        delete _head;        _head = nullptr;      }      iterator begin()      {        return iterator(_head->_next);      }      const_iterator begin() const            //調(diào)用const的迭代器,返回一個用_head->next構(gòu)造的迭代器對象      {        return const_iterator(_head->_next);       }      iterator end()                                {        return iterator(_head);      }      const_iterator end() const       {        return const_iterator(_head);      }      void push_back(const T& x)        //只有哨兵位的也可以通用      {         /* node* newnode = new node(x);    //創(chuàng)建新節(jié)點          node* tail = _head->_prev;      //當(dāng)前的最后一個節(jié)點          tail->_next = newnode;          newnode->_next = _head;          newnode->_prev = tail;          _head->_prev = newnode;*/        insert(iterator(end()), x);     //前一個就是尾      }            void push_front(const T& x)      {        insert(iterator(begin),x);      }      void pop_back()      {        erase(iterator(--end()));      }      void pop_front()      {        erase(iterator(begin()));      }            iterator insert(iterator pos, const T& val)       //pos位置前插入      {        node* newnode = new node(val);        node* tail = pos._pnode;        newnode->_next = tail;        newnode->_prev = tail->_prev;        newnode->_prev->_next = newnode;              //還要讓前一個指向自己        pos._pnode->_prev = newnode;        return iterator(newnode);                     //需要返回迭代器;      }      iterator erase(iterator pos)    //刪除pos位置              {        assert(pos._pnode);        assert(pos != end());        node* tail = pos._pnode;        node* ret = tail->_next;        tail->_prev->_next = tail->_next;        tail->_next->_prev = tail->_prev;        delete tail;        return iterator(ret);       //返回下一個      }      bool empty()      {        return begin() == end();      }      size_t size()      {        size_t sz = 0;        iterator it = begin();        while(it != end())        {          sz++;          it++;        }        return sz;      }      void clear()      {        iterator it = begin();        while(it != end())        {          erase(it);          it++;        }      }        private:      node* _head;  };    void PrintList(const list& It)  {    list::const_iterator it = It.begin();    while(it != It.end())    {      cout << *it < lt;		lt.push_back(1);		lt.push_back(2);		lt.push_back(3);		lt.push_back(4);		list::iterator it = lt.begin();		while (it != lt.end())		{			*it += 1;			cout << *it << " ";			++it;		}		cout << endl;		for (auto e : lt)		{			cout << e << " ";		}		cout << endl;		PrintList(lt);  }}

?

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/121133.html

相關(guān)文章

  • [C/C++]詳解STL1--string功能模擬實現(xiàn)(深淺拷貝問題

    摘要:本文介紹了類的常用接口的使用,并對其進(jìn)行了模擬實現(xiàn),對模擬實現(xiàn)中涉及到的深淺拷貝問題進(jìn)行了解析。在此之前,必須提到一個經(jīng)典問題。為了解決淺拷貝問題,所以中引入了深拷貝。但是實際使用中需要是第一個形參對象,才能正常使用。 本文介紹了string類的常用接口的使用,并對其進(jìn)行了模擬實現(xiàn),對模擬實...

    tianren124 評論0 收藏0
  • [C/C++ -STL]vector使用及迭代失效問題詳解

    摘要:函數(shù)底層實際上是對指針的操作隸書向,范圍內(nèi)比較等于的第一個元素返回迭代器。指定位置元素的刪除操作使用查找所在位置的刪除位置的數(shù)據(jù),導(dǎo)致迭代器失效。因此刪除中任意位置上元素時,就認(rèn)為該位置迭代器失效了。 ...

    VishKozus 評論0 收藏0
  • [C/C++ -STL]vector底層實現(xiàn)機制刨析

    摘要:并且由于的連續(xù)性,且循環(huán)中有迭代器的自加,所以在刪除一個元素后,迭代器需要減。隸書方案二與方案一在迭代器的處理上是類似的,不過對元素的訪問采用了迭代器的方法。 一、...

    lowett 評論0 收藏0
  • [C/C++ -STL]list模擬實現(xiàn)list迭代底層刨析

    摘要:對類采用三個模板來實現(xiàn)迭代器。楷體類中和模板定義分別對應(yīng)迭代器中模板定義的楷體采用向上傳值的方式,傳入不同值來采用不同迭代器。首先是迭代器的,分為前置和后置。迭代器的和都是獲取迭代器所對應(yīng)的值。唯一的差別就是就是用到了迭代器。 ...

    不知名網(wǎng)友 評論0 收藏0
  • C++】list詳解

    摘要:結(jié)果我們發(fā)現(xiàn),好像沒多大問題,但是我們嘗試修改迭代器里面的內(nèi)容時,卻發(fā)現(xiàn)能修改成功。注意為兩個迭代器之間的距離。報錯這里的報錯說的是不在我們的迭代器當(dāng)中,這個是對我們迭代器類型的一個檢查。當(dāng)中為迭代器添加了如下聲明來解決這個問題。 ...

    wanghui 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<