1. 程式人生 > >C++標準庫中的list的實現原理

C++標準庫中的list的實現原理

在C++中採用了大量的標誌模板庫(STL)實現程式的設計,這種設計方式使得不同型別的物件都能通用,而不再是C語言中的通常對於不同的型別需要重新設計或者或者比較採用間接的指標操作。C++中的這種方式簡化了寫程式碼的複雜度,但是增加了編譯器的複雜度和難度。 在資料結構中連結串列是比較基本的型別,在C++中連結串列是基於模板的類,因此在實際的使用過程中需要涉及到實際的型別。

點選(此處)摺疊或開啟

  1. #include<list>
  2. list<int> lint;
在C++中關於list的介面比較豐富,主要是關於大小,資料的插入、刪除等。但是在C++中引入了迭代器的概念,這個迭代器是關於關於容器中比較重要的一部分,因為這種迭代器使得演算法等問題與容器獨立開來,迭代器實質上還是指標,準確的將是一個封裝了指標的類。 迭代器類的建立應該包含下面的操作,首先應該支援的操作符至少包括如下(operator*(),operator++(),operator++(int),operator==(), operator!=()),當然也會存在const_iterator這樣的常迭代器,也就是隻允許訪問,不能修改物件的迭代器,當然存在迭代器的建構函式、複製控制函式,這些函式都是必須要存在的,因為設計到了指標的操作問題,建構函式應該存在引數是連結串列節點指標的定義,只有存在這個定義才能間接的訪問節點物件。
當然在類中至少存在返回迭代器的begin()和end()函式,這兩個函式返回的迭代器分別指向連結串列的開始和連結串列結束的下一個地址,這是迭代器中經常容易理解錯誤的地方。 在C++中通常建立const_iterator類,然後iterator直接繼承const_iterator。 下面說說list類設計的基本思路: 首先、建立連結串列節點物件,實質上是完成對傳遞進來的型別的封裝操作,同時構成一個雙向連結串列的基本要素(prev、next指標)。節點肯定要存在建構函式,而且是直接初始化三個成員變數。 其次、建立迭代器類,實質上就是封裝一個節點指標,通過節點指標實現操作,至少要實現的操作符已說明。這兩個類都要設定List為友元類,因為這樣才能用List直接操作迭代器的相關操作。 最後、依靠上面的迭代器類和節點類,建立一個List類,該類中主要完成一些基本操作。其中需要注意的就是迭代器的操作,比如刪除元素和插入元素以後迭代器的變化問題等。 需要注意的是在List中採用了哨兵節點,這個哨兵節點並不算實際的操作物件,也就是為了保證肯定有目標所指向,存在一個head物件,這個物件的next就是實際的資料,而tail是迭代器所能到達的最後一個物件,但是這個物件並不是合理的區域,實際上end()實際上就是指向了tail節點,這兩個節點head和tail就是哨兵節點。具體的參看程式碼。 實現的基本形式如下:

點選(此處

)摺疊或開啟

  1. #ifndef __MYLIST_H_H_
  2. #define __MYLIST_H_H_
  3. #include<iostream>
  4. namespace myspace
  5. {
  6.         templateObject>
  7.         class List
  8.         {
  9.         private:
  10.                 /*封裝物件,形成連結串列節點*/
  11.                 struct Node
  12.                 {
  13.                         Object data;
  14.                         struct Node *
    prev;
  15.                         struct Node *next;
  16.                         /*節點建構函式*/
  17.                         Node(const Object &d = Object(), Node *p = NULL, Node *n = NULL)
  18.                         :data(d), prev(p), next(n){}
  19.                 };
  20.         public:
  21.                 /*建立一個常量迭代器類,這是容器設計的關鍵*/
  22.                 class
    const_iterator
  23.                 {
  24.                 public:
  25.                         const_iterator():current(NULL)
  26.                         {}
  27.                         /*過載迭代器的值*/
  28.                         const Object & operator*()const
  29.                         {
  30.                                 return retrieve();
  31.                         }
  32.                         /*過載前向++操作符*/
  33.                         const_iterator & operator++ ()
  34.                         {
  35.                                 current = current->next;
  36.                                 return *this;
  37.                         }
  38.                         /*過載後向++操作符,因為是一個區域性物件不能返回引用*/
  39.                         const_iterator operator++(int)
  40.                         {
  41.                                 const_iterator old = *this;
  42.                                 ++(*this);
  43.                                 return old;
  44.                         }
  45.                         /*判斷迭代器是否相同,實質上就是判斷指向的節點是否相同*/
  46.                         bool operator==(const const_iterator &rhs) const
  47.                         {
  48.                                 return current == rhs.current;
  49.                         }
  50.                         /*呼叫==操作符*/
  51.                         bool operator!=(const const_iterator &rhs)const
  52.                         {
  53.                                 return (!(*this == rhs));
  54.                         }
  55.                 protected:
  56.                         /*迭代器實質就是一個節點指標*/
  57.                         Node *current;
  58.                         /*獲得連結串列中的內容*/
  59.                         Object & retrieve() const
  60.                         {
  61.                                 return current->data;
  62.                         }
  63.                         /*基於指標引數的迭代器建構函式,保證只有List使用*/
  64.                         const_iterator(Node *p):current (p)
  65.                         {}
  66.                         /*友元類,可以呼叫迭代器的私有成員*/
  67.                         friend class List<Object>;
  68.                 };
  69.                 /*一般迭代器,直接繼承const_iterator*/
  70.                 class iterator : public const_iterator
  71.                 {
  72.                 public:
  73.                         iterator():const_iterator()
  74.                         {}
  75.                         /*得到物件的值*/
  76.                         Object &operator*()
  77.                         {
  78.                                 return retrieve();
  79.                         }
  80.                         /*基於const的過載*/
  81.                         const Object& operator*()const
  82.                         {
  83.                                 return const_iterator::operator*();
  84.                         }
  85.                         /*前向++操作符*/
  86.                         iterator &operator++()
  87.                        {
  88.                                 current = current->next;
  89.                                 return *this;
  90.                         }
  91.                         /*後向++操作符*/
  92.                         iterator operator++(int)
  93.                         {
  94.                                 iterator *old = *this;
  95.                                 ++(*this);
  96.                                 return old;
  97.                         }
  98.                 protected:
  99.                         /*基於節點的迭代器建構函式*/
  100.                         iterator(Node *p):const_iterator(p)
  101.                         {}
  102.                         friend class List<Object>;
  103.                 };
  104.         public:
  105.                 List()
  106.                 {
  107.                         init();
  108.                 }
  109.                 ~List()
  110.                 {
  111.                         clear();
  112.                         delete head;
  113.                         delete tail;
  114.                 }
  115.                 List(const List &rhs)
  116.                 {
  117.                        /*建立哨兵節點*/
  118.                         init();
  119.                         /*複製資料*/
  120.                         *this = rhs;
  121.                 }
  122.                 const List & operator=(const List &rhs)
  123.                 {
  124.                         if(this == &rhs)
  125.                                 return *this;
  126.                         /*清除原有的資訊*/
  127.                         clear();
  128.                         /*新增新的物件*/
  129.                         for(const_iterator itr = rhs.begin(); itr != rhs.end(); ++ itr)
  130.                                 push_back(*itr);
  131.                         return *this;
  132.                 }
  133.                 /*得到迭代器,實質上就是得到節點指標*/
  134.                 iterator begin()
  135.                 {
  136.                         /*iterator()是建構函式*/
  137.                         return iterator(head->next);
  138.                 }
  139.                 const_iterator begin()const
  140.                 {
  141.                         return const_iterator(head->next);
  142.                 }
  143.                 iterator end()
  144.                {
  145.                         return iterator(tail);
  146.                 }
  147.                 const_iterator end()const
  148.                 {
  149.                         return const_iterator(tail);
  150.                 }
  151.                 int size()const
  152.                 {
  153.                         return theSize;
  154.                 }
  155.                 bool empty()const
  156.                 {
  157.                         return size() == 0;
  158.                 }
  159.                 void clear()
  160.                 {
  161.                         while( !empty())
  162.                                 pop_front();
  163.                 }
  164.                 /*得到第一個元素*/
  165.                 Object & front()
  166.                 {
  167.                         /*採用了迭代器begin()*/
  168.                         return *begin();
  169.                 }
  170.                 const Object &front()const
  171.                 {
  172.                         return *begin();
  173.                }
  174.                 Object &back()
  175.                 {
  176.                         /*end()指向最後一個物件的下一個地址,因此需要--*/
  177.                         return *--end();
  178.                 }
  179.                 const Object &back()const
  180.                 {
  181.                         return *--end();
  182.                 }
  183.                 /***********************************************
  184.                 *從頭插入新的節點,這時候的begin已經不再是begin
  185.                 *因此插入操作會導致迭代器出錯
  186.                 ***********************************************/
  187.                 void push_front(const Object &x)
  188.                 {
  189.                         insert(begin(), x);
  190.                 }
  191.                 /*從後插入新的節點,這時候會將end後移*/
  192.                 void push_back(const Object &x)
  193.                 {
  194.                         insert(end(), x);
  195.                 }
  196.                 /*從頭彈出一個物件*/
  197.                 void pop_front()
  198.                 {
  199.                         erase(begin());
  200.                 }
  201.                 void pop_back()
  202.                 {
  203.                        erase(--end());
  204.                 }
  205.                 /*插入物件,引數是迭代器和資料*/
  206.                 iterator insert(iterator itr, const Object &x)
  207.                 {
  208.                         /*得到當前迭代器的指標*/
  209.                         Node *p = itr.current;
  210.                         theSize ++;
  211.                         /*
  212.                         *Node *np = Node(x,p->prev,p);
  213.                         this means that np->prev = p->prev,
  214.                         and np->next = p;
  215.                         update the p->prev and p->prev->next;
  216.                         *p->prev->next = np;
  217.                         *p->prev = np;
  218.                         */
  219.                         return iterator(p->prev=p->prev->next= new Node(x,p->prev, p));
  220.                 }
  221.                 /*刪除迭代器處的物件,因此刪除也會導致迭代器破壞*/
  222.                 iterator erase(iterator itr)
  223.                 {
  224.                         /*得到當前迭代器的指標*/
  225.                         Node *p = itr.current;
  226.                         /*得到新的迭代器,並初始化*/
  227.                         iterator retVal(p->next);
  228.                         /*更新連結串列的連結關係*/
  229.                         p->prev->next = p->next;
  230.                         p->next->prev = p->prev;
  231.                         /*刪除物件*/
  232.                         delete p;
  233.                         /*使得物件數減少*/
  234.                         theSize --;
  235.                         /*返回新的迭代器*/
  236.                         return retVal;
  237.                 }
  238.                 /*刪除迭代器指向的物件*/
  239.                 iterator erase(iterator start, iterator end)
  240.                 {
  241.                         /*for中不使用++itr的原因是erase之後
  242.                          *就是下一個迭代器,因此不需要++操作*/
  243.                         for(iterator itr = start; itr != end; )
  244.                         {
  245.                                 /*該操作會導致迭代器更新到下一個*/
  246.                                 itr = erase(itr);
  247.                         }
  248.                         return itr;
  249.                 }
  250.         private:
  251.                 /*連結串列中的資料成員*/
  252.                 int theSize;
  253.                 Node *head;
  254.                 Node *tail;
  255.                 /*初始化函式*/
  256.                 void init()
  257.                 {
  258.                         theSize = 0;
  259.                         /*create two sentinel node*/
  260.                         /*構建兩個哨兵節點,也就是兩個並不算在結構體中的物件*/
  261.                         head = new Node;
  262.                         tail = new Node;
  263.                         /*繫結起來*/
  264.                         head->next = tail;
  265.                         tail->prev = head;
  266.                 }
  267.         };
  268. }
  269. #endif