數據結構基礎(12) --雙向循環鏈表的設計與實現

雙向鏈表的操作特點:

    (1) “查詢” 和單鏈表相同;

    (2)“插入” 和“刪除”時需要同時修改兩個方向上的指針。

   但是對於雙向循環鏈表則在表尾插入非常的迅速, 只需O(1)的時間,因爲有指向前面的指針, 因此雙向循環鏈表會很容易的找到位於表尾的元素,因此雙向循環鏈表比較適用於頻繁在表尾插入的情況.



空鏈表:


雙向循環鏈表節點構造:

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. class DoubleListNode  
  2. {  
  3. private:  
  4.     Type data;  
  5.     DoubleListNode *prev;   //前向指針域  
  6.     DoubleListNode *next;   //後項指針域  
  7. };  

因爲需要將其用於DoubleList,因此需要將其改造如下:

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. template <typename Type>  
  2. class DoubleListNode  
  3. {  
  4.     //友元聲明  
  5.     friend class DoubleList<Type>;  
  6.     friend class ListIterator<Type>;  
  7.   
  8.     template <typename T>  
  9.     friend ostream &operator<<(ostream &os, const DoubleList<T> &list);  
  10. private:  
  11.     DoubleListNode(const Type &dataValue)  
  12.         :data(dataValue),prev(NULL),next(NULL) {}  
  13.   
  14.     Type data;  
  15.     DoubleListNode *prev;   //前向指針域  
  16.     DoubleListNode *next;   //後項指針域  
  17. };  

雙向循環鏈表構造:

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. template <typename Type>  
  2. class DoubleList  
  3. {  
  4.     friend class ListIterator<Type>;  
  5.     template <typename T>  
  6.     friend ostream &operator<<(ostream &os, const DoubleList<T> &list);  
  7. public:  
  8.     DoubleList();  
  9.     ~DoubleList();  
  10.   
  11.     void push_back(const Type &data);  
  12.     void push_front(const Type &data);  
  13.     void insert(int position, const Type &data);  
  14.   
  15.     void pop_front();  
  16.     void pop_back();  
  17.     void remove(const Type &removeData);  
  18.   
  19.     bool search(const Type &searchData) const;  
  20.     bool isEmpty() const  
  21.     {  
  22.         return (first->next == first);  
  23.     }  
  24.   
  25. private:  
  26.     //將節點x插入到節點previous後面  
  27.     void insertPrivate(DoubleListNode<Type> *previous,  
  28.                        DoubleListNode<Type> *x);  
  29.     void removePrivate(DoubleListNode<Type> *x);  
  30.   
  31. private:  
  32.     DoubleListNode<Type> *first;  
  33. };  

鏈表的構造與析構:

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. //構造鏈表  
  2. template <typename Type>  
  3. DoubleList<Type>::DoubleList()  
  4. {  
  5.     first = new DoubleListNode<Type>(0);  
  6.     first->next = first;  
  7.     first->prev = first;  
  8. }  
[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. //析構鏈表  
  2. template <typename Type>  
  3. DoubleList<Type>::~DoubleList()  
  4. {  
  5.     DoubleListNode<Type> *deleteNode = NULL;  
  6.     //保存鏈表尾元素  
  7.     DoubleListNode<Type> *tmp = first;  
  8.   
  9.     //first首先指向第一個真實的元素  
  10.     first = first->next;  
  11.     //一路到達鏈表結尾  
  12.     while (first != tmp)  
  13.     {  
  14.         deleteNode = first;  
  15.         first = first -> next;  
  16.         delete deleteNode;  
  17.     }  
  18.     // 釋放掉鏈表的空節點(表頭)  
  19.     delete tmp;  
  20. }  

鏈表元素插入與刪除的兩大主力:

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. //同爲private成員  
  2. //插入節點  
  3. template <typename Type>  
  4. void DoubleList<Type>::insertPrivate(DoubleListNode<Type> *previous,  
  5.                                      DoubleListNode<Type> *x)  
  6. {  
  7.     x->prev = previous;  
  8.     x->next = previous->next;  
  9.     previous->next->prev = x;  
  10.     previous->next = x;  
  11. }  

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. //刪除節點  
  2. template <typename Type>  
  3. void DoubleList<Type>::removePrivate(DoubleListNode<Type> *x)  
  4.   
  5. {  
  6.     if (x == first)  
  7.         throw std::range_error("permission denied to delete first pointer");  
  8.   
  9.     x->prev->next = x->next;  
  10.     x->next->prev = x->prev;  
  11.     delete x;  
  12. }  

提供給客戶的插入:

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. //插入到表尾  
  2. template <typename Type>  
  3. void DoubleList<Type>::push_back(const Type &data)  
  4. {  
  5.     DoubleListNode<Type> *newNode = new DoubleListNode<Type>(data);  
  6.     //找到first的前一個節點  
  7.     DoubleListNode<Type> *previous = first->prev;  
  8.   
  9.     //插入  
  10.     insertPrivate(previous, newNode);  
  11. }  
  12. //插入到表頭  
  13. template <typename Type>  
  14. void DoubleList<Type>::push_front(const Type &data)  
  15. {  
  16.     DoubleListNode<Type> *newNode = new DoubleListNode<Type>(data);  
  17.     //插入到first之後  
  18.     insertPrivate(first, newNode);  
  19. }  
  20.   
  21. //插入到任意位置(依position指定)  
  22. template <typename Type>  
  23. void DoubleList<Type>::insert(int position, const Type &data)  
  24. {  
  25.     if (position == 1)  
  26.         return push_front(data);  
  27.   
  28.     int count = 1;  
  29.     //previous 代表着要插入位置之前的一個位置  
  30.     DoubleListNode<Type> *previous = first->next;  
  31.   
  32.     //如果position過大, 則previous查找到first就會停止  
  33.     //此時應該將該元素插入到鏈表結尾  
  34.     while (count < position-1 && previous != first)  
  35.     {  
  36.         ++ count;  
  37.         previous = previous->next;  
  38.     }  
  39.   
  40.     //如果查找到了鏈表結尾或此時鏈表爲空, 因此插入到表尾  
  41.     if (previous == first)  
  42.         return push_back(data);  
  43.   
  44.     //如果找到了合適的插入位置  
  45.     DoubleListNode<Type> *newNode = new DoubleListNode<Type>(data);  
  46.     insertPrivate(previous, newNode);  
  47. }  

提供給客戶的刪除:

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. //刪除表尾元素  
  2. template <typename Type>  
  3. void DoubleList<Type>::pop_back()  
  4. {  
  5.     removePrivate(first->prev);  
  6. }  
  7. //刪除表頭元素  
  8. template <typename Type>  
  9. void DoubleList<Type>::pop_front()  
  10. {  
  11.     removePrivate(first->next);  
  12. }  
  13.   
  14. //刪除元素值爲removeData的所有元素  
  15. template <typename Type>  
  16. void DoubleList<Type>::remove(const Type &removeData)  
  17. {  
  18.     if (isEmpty())  
  19.         throw std::range_error("link list is empty");  
  20.   
  21.     for( DoubleListNode<Type> *searchNode = first->next;  
  22.             searchNode != first;  
  23.             searchNode = searchNode->next)  
  24.     {  
  25.         if (searchNode->data == removeData)  
  26.             removePrivate(searchNode);  
  27.     }  
  28. }  

查看是否存在於鏈表中:

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. template <typename Type>  
  2. bool DoubleList<Type>::search(const Type &searchData) const  
  3. {  
  4.     DoubleListNode<Type> *searchNode = first->next;  
  5.     while (searchNode != first)  
  6.     {  
  7.         if (searchNode->data == searchData)  
  8.             return true;  
  9.   
  10.         searchNode = searchNode->next;  
  11.     }  
  12.     return false;  
  13. }  

輸出鏈表所有元素(測試用):

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. template <typename Type>  
  2. ostream &operator<<(ostream &os, const DoubleList<Type> &list)  
  3. {  
  4.     for (DoubleListNode<Type> *currentNode = (list.first)->next;  
  5.             currentNode != list.first;  
  6.             currentNode = currentNode->next)  
  7.         os << currentNode->data << ' ';  
  8.   
  9.     return os;  
  10. }  

雙向循環鏈表迭代器的設計與實現:

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. //除了添加了operator--, 幾乎沒做任何改變  
  2. template <typename Type>  
  3. class ListIterator  
  4. {  
  5. public:  
  6.     ListIterator(const DoubleList<Type> &_list):  
  7.         list(_list),  
  8.         currentNode((_list.first)->next) {}  
  9.   
  10.     //重載 *operator  
  11.     const Type &operator*() const throw (std::out_of_range);  
  12.     Type &operator*() throw (std::out_of_range);  
  13.   
  14.     //重載 ->operator  
  15.     const DoubleListNode<Type> *operator->() const throw (std::out_of_range);  
  16.     DoubleListNode<Type> *operator->() throw (std::out_of_range);  
  17.   
  18.     //重載 ++operator  
  19.     ListIterator &operator++() throw (std::out_of_range);  
  20.     //注意:此處返回的是值,而不是reference  
  21.     ListIterator operator++(intthrow (std::out_of_range);  
  22.   
  23.     //重載 --operator,  
  24.     // 其實這個版本的--operator是不完美的,  
  25.     // 因爲他沒有做任何的判錯控制  
  26.     ListIterator &operator--();  
  27.     //注意:此處返回的是值,而不是reference  
  28.     ListIterator operator--(int);  
  29.   
  30.     bool isEmpty() const  
  31.     {  
  32.         return (currentNode == list.first);  
  33.     }  
  34.   
  35. private:  
  36.     const DoubleList<Type> &list;  
  37.     DoubleListNode<Type> *currentNode;  
  38. };  
[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. template <typename Type>  
  11. Type &ListIterator<Type>::operator*()  
  12. throw (std::out_of_range)  
  13. {  
  14.     return  
  15.         const_cast<Type &>(  
  16.             static_cast<const ListIterator<Type> &>(*this).operator*()  
  17.         );  
  18. }  
[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. template <typename Type>  
  2. const DoubleListNode<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.     //直接返回指針  
  9.     return currentNode;  
  10. }  
  11.   
  12. template <typename Type>  
  13. DoubleListNode<Type> *ListIterator<Type>::operator->()  
  14. throw (std::out_of_range)  
  15. {  
  16.     return  
  17.         const_cast<DoubleListNode<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. template <typename Type>  
  2. ListIterator<Type> &ListIterator<Type>::operator--()  
  3. {  
  4.     //指針前移  
  5.     currentNode = currentNode->prev;  
  6.     return *this;  
  7. }  
  8. template <typename Type>  
  9. ListIterator<Type> ListIterator<Type>::operator--(int)  
  10. {  
  11.     ListIterator<Type> tmp(*this);  
  12.     -- (*this);  
  13.   
  14.     return tmp;  
  15. }  

測試代碼:

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. int main()  
  2. {  
  3.     cout << "-------- 1 --------" << endl;  
  4.     DoubleList<int> myList;  
  5.   
  6.     for (int i = 0; i < 3; ++i)  
  7.         myList.push_back(i+1);  
  8.     for (int i = 0; i < 5; ++i)  
  9.         myList.push_front(10+i);  
  10.     for (int i = 0; i < 3; ++i)  
  11.         myList.push_back(i+1);  
  12.   
  13.     ListIterator<int> iter(myList), iter2(myList);  
  14.     while (!iter.isEmpty())  
  15.     {  
  16.         cout << *iter << ' ';  
  17.         ++ iter;  
  18.   
  19.         ++ iter2;  
  20.     }  
  21.     cout << endl;  
  22.   
  23.     -- iter2;  
  24.     while (!iter2.isEmpty())  
  25.     {  
  26.         cout << *iter2 << ' ';  
  27.         iter2 --;  
  28.     }  
  29.     cout << endl;  
  30.   
  31.     cout << "-------- 2 --------" << endl;  
  32.   
  33.     cout << myList << endl;  
  34.     cout << "Test insert..." << endl;  
  35.     myList.insert(1, 14);  
  36.     myList.insert(2, 13);  
  37.     myList.insert(2, 13);  
  38.     myList.insert(88, 88);  
  39.     cout << myList << endl;  
  40.   
  41.     myList.pop_back();  
  42.     myList.pop_front();  
  43.     cout << myList << endl;  
  44.   
  45.     for (int i = 0; i < 5; ++i)  
  46.     {  
  47.         if (myList.search(i))  
  48.             cout << i << ": Have found!" << endl;  
  49.         else  
  50.             cout << i << ": Not in the list!" << endl;  
  51.     }  
  52.   
  53.     cout << "Test remove..." << endl;  
  54.     cout << myList << endl;  
  55.     int value;  
  56.     while (cin >> value)  
  57.     {  
  58.         try  
  59.         {  
  60.             myList.remove(value);  
  61.         }  
  62.         catch (const std::exception &e)  
  63.         {  
  64.             cerr << e.what() << endl;  
  65.         }  
  66.   
  67.         cout << myList << endl;  
  68.         if (myList.isEmpty())  
  69.         {  
  70.             cout << "empty" << endl;  
  71.         }  
  72.         else  
  73.         {  
  74.             cout << "not empty" << endl;  
  75.         }  
  76.     }  
  77.   
  78.     return 0;  
  79. }  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章