數據結構基礎(10) --單鏈表迭代器的設計與實現

爲了向 STL 致敬(O(∩_∩)O~), 我們模仿STL中的list的迭代器, 我們也自己實現一個MyList的迭代器, 以供遍歷整個鏈表的所有元素:

首先:Node節點需要做如下修改(注意後綴有+的代碼)

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. //鏈表節點  
  2. template <typename Type>  
  3. class Node  
  4. {  
  5.     friend class MyList<Type>;  
  6.     friend class ListIterator<Type>;  //+  
  7.   
  8.     template <typename T>  
  9.     friend ostream &operator<<(ostream &os, const MyList<T> &list);  
  10. private:  
  11.     Node(const Type &dataValue):data(dataValue), next(NULL) {}  
  12.   
  13.     Type data;  //數據域:節點數據  
  14.     Node *next; //指針域:下一個節點  
  15. };  

然後:MyList類同樣也需要做修改,但是由於MyList類過長修改之處也較少因此在此就不貼出完整代碼會附到博客最後

 

ListIterator的設計

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. template <typename Type>  
  2. class ListIterator  
  3. {  
  4. public:  
  5.     ListIterator(const MyList<Type> &_list):  
  6.         list(_list),  
  7.         currentNode((_list.first)->next) {}  
  8.   
  9.     //重載 *operator  
  10.     const Type &operator*() const throw (std::out_of_range);  
  11.     Type &operator*() throw (std::out_of_range);  
  12.   
  13.     //重載 ->operator  
  14.     const Node<Type> *operator->() const throw (std::out_of_range);  
  15.     Node<Type> *operator->() throw (std::out_of_range);  
  16.   
  17.     //重載 ++operator  
  18.     ListIterator &operator++() throw (std::out_of_range);  
  19.     //注意:此處返回的是值,而不是reference  
  20.     ListIterator operator++(intthrow (std::out_of_range);  
  21.   
  22.     bool isEmpty() const;  
  23.   
  24. private:  
  25.     const MyList<Type> &list;  
  26.     Node<Type> *currentNode;  
  27. };  

ListIterator類的實現

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. template <typename Type>  
  2. const Type &ListIterator<Type>::operator*() const  
  3. throw (std::out_of_range)  
  4. {  
  5.     if (isEmpty())  
  6.         throw std::out_of_range("iterator is out of range");  
  7.     // 返回當前指針指向的內容  
  8.     return currentNode->data;  
  9. }  
  10.   
  11. template <typename Type>  
  12. Type &ListIterator<Type>::operator*()  
  13. throw (std::out_of_range)  
  14. {  
  15.     //首先爲*this添加const屬性,  
  16.     //以調用該函數的const版本,  
  17.     //然後再使用const_case,  
  18.     //將該函數調用所帶有的const屬性轉除  
  19.     //operator->()的non-const版本與此類同  
  20.     return  
  21.         const_cast<Type &>(  
  22.             static_cast<const ListIterator<Type> &>(*this).operator*()  
  23.         );  
  24. }  

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. template <typename Type>  
  2. const Node<Type> *ListIterator<Type>::operator->() const  
  3. throw (std::out_of_range)  
  4. {  
  5.     if (isEmpty())  
  6.         throw std::out_of_range("iterator is out of range");  
  7.     //直接返回指針  
  8.     return currentNode;  
  9. }  
  10.   
  11. template <typename Type>  
  12. Node<Type> *ListIterator<Type>::operator->()  
  13. throw (std::out_of_range)  
  14. {  
  15.     // 見上  
  16.     return  
  17.         const_cast<Node<Type> *> (  
  18.             static_cast<const ListIterator<Type> >(*this).operator->()  
  19.         );  
  20. }  

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. template <typename Type>  
  2. ListIterator<Type> &ListIterator<Type>::operator++()  
  3. throw (std::out_of_range)  
  4. {  
  5.     if (isEmpty())  
  6.         throw std::out_of_range("iterator is out of range");  
  7.     //指針後移  
  8.     currentNode = currentNode->next;  
  9.     return *this;  
  10. }  
  11. template <typename Type>  
  12. ListIterator<Type> ListIterator<Type>::operator++(int)  
  13. throw (std::out_of_range)  
  14. {  
  15.     ListIterator tmp(*this);  
  16.     ++ (*this); //調用前向++版本  
  17.   
  18.     return tmp;  
  19. }  

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. //判空  
  2. template <typename Type>  
  3. bool ListIterator<Type>::isEmpty() const  
  4. {  
  5.     if (currentNode == NULL)  
  6.         return true;  
  7.     return false;  
  8. }  

-ListIterator測試代碼:

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. int main()  
  2. {  
  3.     std::list<int> iStdList;  
  4.     MyList<int>    iMyList;  
  5.     for (int i = 0; i < 10; ++i)  
  6.     {  
  7.         iStdList.push_back(i+1);  
  8.         iMyList.insert(i+1, i+1);  
  9.     }  
  10.   
  11.     for (std::list<int>::iterator iter = iStdList.begin();  
  12.             iter != iStdList.end();  
  13.             ++ iter)  
  14.     {  
  15.         cout << *iter << ' ';  
  16.     }  
  17.     cout << endl;  
  18.   
  19.     for (ListIterator<int> iter(iMyList);  
  20.             !iter.isEmpty();  
  21.             ++ iter)  
  22.     {  
  23.         cout << *iter << ' ';  
  24.     }  
  25.     cout << endl;  
  26.   
  27.     cout << "Test: \n\t" << iMyList << endl;  
  28.   
  29.   
  30.     ListIterator<int> iter(iMyList);  
  31. cout << "first = " << *iter << endl;  
  32. }  


附-MyList完整源代碼

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. //MyList.h  
  2. #ifndef MYLIST_H_INCLUDED  
  3. #define MYLIST_H_INCLUDED  
  4.   
  5. #include <iostream>  
  6. #include <stdexcept>  
  7. using namespace std;  
  8.   
  9. //前向聲明  
  10. template <typename Type>  
  11. class MyList;  
  12. template <typename Type>  
  13. class ListIterator;  
  14.   
  15. //鏈表節點  
  16. template <typename Type>  
  17. class Node  
  18. {  
  19.     //可以將MyList類作爲Node的友元  
  20.     //同時也可以將Node類做成MyList的嵌套類, 嵌套在MyList中, 也可以完成該功能  
  21.     friend class MyList<Type>;  
  22.     friend class ListIterator<Type>;  
  23.   
  24.     template <typename T>  
  25.     friend ostream &operator<<(ostream &os, const MyList<T> &list);  
  26. private:  
  27.     //constructor說明:  
  28.     //next = NULL;    //因爲這是一個新生成的節點, 因此下一個節點爲空  
  29.     Node(const Type &dataValue):data(dataValue), next(NULL) {}  
  30.   
  31.     Type data;  //數據域:節點數據  
  32.     Node *next; //指針域:下一個節點  
  33. };  
  34.   
  35. //鏈表  
  36. template <typename Type>  
  37. class MyList  
  38. {  
  39.     template <typename T>  
  40.     friend ostream &operator<<(ostream &os, const MyList<T> &list);  
  41.   
  42.     friend class ListIterator<Type>;  
  43. public:  
  44.     MyList();  
  45.     ~MyList();  
  46.   
  47.     //將元素插入表頭  
  48.     void insertFront(const Type &data);  
  49.     //將元素插入到位置index上(index從1開始)  
  50.     void insert(const Type &data, int index);  
  51.     //刪除表中所有值爲data的節點  
  52.     void remove(const Type &data);  
  53.     bool isEmpty() const;  
  54.   
  55.     //鏈表反轉  
  56.     void invort();  
  57.     //將鏈表(list)鏈接到本條鏈表的末尾  
  58.     void concatenate(const MyList<Type> &list);  
  59.   
  60. private:  
  61.     //指向第一個節點的指針  
  62.     Node<Type> *first;  
  63. };  
  64.   
  65. template <typename Type>  
  66. MyList<Type>::MyList()  
  67. {  
  68.     //first指向一個空節點  
  69.     first = new Node<Type>(0);  
  70.     first -> next = NULL;  
  71. }  
  72. template <typename Type>  
  73. MyList<Type>::~MyList()  
  74. {  
  75.     Node<Type> *deleteNode = NULL;  
  76.     while (first != NULL)  
  77.     {  
  78.         deleteNode = first;  
  79.         first = first -> next;  
  80.         delete deleteNode;  
  81.     }  
  82. }  
  83.   
  84. template <typename Type>  
  85. void MyList<Type>::insertFront(const Type &data)  
  86. {  
  87.     Node<Type> *newNode = new Node<Type>(data);  
  88.     newNode -> next = first -> next;  
  89.     first -> next = newNode;  
  90. }  
  91.   
  92. template <typename Type>  
  93. void MyList<Type>::insert(const Type &data, int index)  
  94. {  
  95.     //由於我們在表頭添加了一個空節點  
  96.     //因此如果鏈表爲空, 或者在鏈表爲1的位置添加元素  
  97.     //其操作與在其他位置添加元素相同  
  98.   
  99.     int count = 1;  
  100.     //此時searchNode肯定不爲NULL  
  101.     Node<Type> *searchNode = first;  
  102.     // 找到要插入的位置  
  103.     // 如果所給index過大(超過了鏈表的長度)  
  104.     // 則將該元素插入到鏈表表尾  
  105.     // 原因是 searchNode->next != NULL 這個條件已經不滿足了  
  106.     // 已經到達表尾  
  107.     while (count < index && searchNode->next != NULL)  
  108.     {  
  109.         ++ count;  
  110.         searchNode = searchNode->next;  
  111.     }  
  112.   
  113.     // 插入鏈表  
  114.     Node<Type> *newNode = new Node<Type>(data);  
  115.     newNode->next = searchNode->next;  
  116.     searchNode->next = newNode;  
  117. }  
  118.   
  119. template <typename Type>  
  120. void MyList<Type>::remove(const Type &data)  
  121. {  
  122.     if (isEmpty())  
  123.         return ;  
  124.   
  125.     Node<Type> *previous = first;   //保存要刪除節點的前一個節點  
  126.     for (Node<Type> *searchNode = first->next;  
  127.             searchNode != NULL;  
  128.             searchNode = searchNode->next)  
  129.     {  
  130.         if (searchNode->data == data)  
  131.         {  
  132.             previous->next = searchNode->next;  
  133.             delete searchNode;  
  134.             //重新調整searchNode指針  
  135.             //繼續遍歷鏈表查看是否還有相等元素  
  136.   
  137.             //如果當前searchNode已經到達了最後一個節點  
  138.             //也就是searchNode->next已經等於NULL了, 則下面這條語句不能執行  
  139.             if (previous->next == NULL)  
  140.                 break;  
  141.   
  142.             searchNode = previous->next;  
  143.         }  
  144.         previous = searchNode;  
  145.     }  
  146. }  
  147. template <typename Type>  
  148. bool MyList<Type>::isEmpty() const  
  149. {  
  150.     return first->next == NULL;  
  151. }  
  152.   
  153. template <typename Type>  
  154. void MyList<Type>::concatenate(const MyList<Type> &list)  
  155. {  
  156.     if (isEmpty())//如果自己的鏈表爲空  
  157.     {  
  158.         first = list.first;  
  159.         return ;  
  160.     }  
  161.     else if (list.isEmpty())    //如果第二條鏈表爲空  
  162.     {  
  163.         return ;  
  164.     }  
  165.   
  166.     Node<Type> *endNode = first->next;  
  167.     //找到第一條鏈表的末尾節點  
  168.     while (endNode->next != NULL)  
  169.     {  
  170.         endNode = endNode->next;  
  171.     }  
  172.   
  173.     //找到第二條鏈表的第一個真實元素  
  174.     Node<Type> *secondListNode = (list.first)->next;  
  175.     //注意: 需要將第二個鏈表中的元素值copy出來  
  176.     //不能直接將第二條鏈表的表頭鏈接到第一條鏈表的表尾  
  177.     //不然在析構函數回收內存時會發生錯誤(即:同一段內存釋放兩次)  
  178.     while (secondListNode != NULL)  
  179.     {  
  180.         Node<Type> *newNode = new Node<Type>(secondListNode->data);  
  181.         newNode->next = NULL;  
  182.         endNode->next = newNode;  
  183.   
  184.         //兩條鏈表同時前進  
  185.         endNode = endNode->next;  
  186.         secondListNode = secondListNode->next;  
  187.     }  
  188. }  
  189.   
  190. template <typename Type>  
  191. void MyList<Type>::invort()  
  192. {  
  193.     if (!isEmpty())  
  194.     {  
  195.         //p指向正向鏈表的第一個真實節點  
  196.         //隨後, p也會沿正方向遍歷到鏈表末尾  
  197.         Node<Type> *p = first->next;  
  198.   
  199.         //q會成爲倒向的第一個真實節點  
  200.         //首先將q設置爲NULL: 保證反向之後  
  201.         //最後一個元素的指針域指向NULL, 以表示鏈表結束  
  202.         Node<Type> *q = NULL;  
  203.         while (p != NULL)  
  204.         {  
  205.             Node<Type> *r = q;  //暫存q當前指向的節點  
  206.             //q後退(沿着正向後退)  
  207.             q = p;  
  208.             //p前進(沿着正向前進), 保證p能夠始終領先q一個位置  
  209.             p = p -> next;  
  210.             //將指針逆向反轉  
  211.             //注意:一點要保證這條語句在p指針移動之後運行,  
  212.             //不然p就走不了了...(因爲q改變了指針的朝向)  
  213.             q -> next = r;  
  214.         }  
  215.   
  216.         //此時q成爲反向鏈表的第一個真實元素  
  217.         //但是爲了維護像以前一樣的first指針指向一個無用的節點(以使前面的操作不會出錯)  
  218.         //於是我們需要將first的指針域指向q  
  219.         first->next = q;  
  220.     }  
  221. }  
  222.   
  223. //顯示鏈表中的所有數據(測試用)  
  224. template <typename Type>  
  225. ostream &operator<<(ostream &os, const MyList<Type> &list)  
  226. {  
  227.     for (Node<Type> *searchNode = list.first -> next;  
  228.             searchNode != NULL;  
  229.             searchNode = searchNode -> next)  
  230.     {  
  231.         os << searchNode -> data;  
  232.         if (searchNode -> next != NULL) //尚未達到鏈表的結尾  
  233.             cout << " -> ";  
  234.     }  
  235.   
  236.     return os;  
  237. }  
  238.   
  239. //ListIterator的設計與實現  
  240. template <typename Type>  
  241. class ListIterator  
  242. {  
  243. public:  
  244.     ListIterator(const MyList<Type> &_list):  
  245.         list(_list),  
  246.         currentNode((_list.first)->next) {}  
  247.   
  248.     //重載 *operator  
  249.     const Type &operator*() const throw (std::out_of_range);  
  250.     Type &operator*() throw (std::out_of_range);  
  251.   
  252.     //重載 ->operator  
  253.     const Node<Type> *operator->() const throw (std::out_of_range);  
  254.     Node<Type> *operator->() throw (std::out_of_range);  
  255.   
  256.     //重載 ++operator  
  257.     ListIterator &operator++() throw (std::out_of_range);  
  258.     //注意:此處返回的是值,而不是reference  
  259.     ListIterator operator++(intthrow (std::out_of_range);  
  260.   
  261.     bool isEmpty() const;  
  262.   
  263. private:  
  264.     const MyList<Type> &list;  
  265.     Node<Type> *currentNode;  
  266. };  
  267.   
  268. template <typename Type>  
  269. const Type &ListIterator<Type>::operator*() const  
  270. throw (std::out_of_range)  
  271. {  
  272.     if (isEmpty())  
  273.         throw std::out_of_range("iterator is out of range");  
  274.     // 返回當前指針指向的內容  
  275.     return currentNode->data;  
  276. }  
  277. template <typename Type>  
  278. Type &ListIterator<Type>::operator*()  
  279. throw (std::out_of_range)  
  280. {  
  281.     //首先爲*this添加const屬性,  
  282.     //以調用該函數的const版本,  
  283.     //然後再使用const_case,  
  284.     //將該函數調用所帶有的const屬性轉除  
  285.     //operator->()的non-const版本與此類同  
  286.     return  
  287.         const_cast<Type &>(  
  288.             static_cast<const ListIterator<Type> &>(*this).operator*()  
  289.         );  
  290. }  
  291.   
  292. template <typename Type>  
  293. const Node<Type> *ListIterator<Type>::operator->() const  
  294. throw (std::out_of_range)  
  295. {  
  296.     if (isEmpty())  
  297.         throw std::out_of_range("iterator is out of range");  
  298.     //直接返回指針  
  299.     return currentNode;  
  300. }  
  301.   
  302. template <typename Type>  
  303. Node<Type> *ListIterator<Type>::operator->()  
  304. throw (std::out_of_range)  
  305. {  
  306.     // 見上  
  307.     return  
  308.         const_cast<Node<Type> *> (  
  309.             static_cast<const ListIterator<Type> >(*this).operator->()  
  310.         );  
  311. }  
  312.   
  313. template <typename Type>  
  314. ListIterator<Type> &ListIterator<Type>::operator++()  
  315. throw (std::out_of_range)  
  316. {  
  317.     if (isEmpty())  
  318.         throw std::out_of_range("iterator is out of range");  
  319.     //指針前移  
  320.     currentNode = currentNode->next;  
  321.     return *this;  
  322. }  
  323. template <typename Type>  
  324. ListIterator<Type> ListIterator<Type>::operator++(int)  
  325. throw (std::out_of_range)  
  326. {  
  327.     ListIterator tmp(*this);  
  328.     ++ (*this); //調用前向++版本  
  329.   
  330.     return tmp;  
  331. }  
  332. template <typename Type>  
  333. bool ListIterator<Type>::isEmpty() const  
  334. {  
  335.     if (currentNode == NULL)  
  336.         return true;  
  337.     return false;  
  338. }  
  339.   
  340. #endif // MYLIST_H_INCLUDED  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章