数据结构基础(12) --双向循环链表的设计与实现

双向链表的操作特点:

    (1) “查询” 和单链表相同;

    (2)“插入” 和“删除”时需要同时修改两个方向上的指针。

   但是对于双向循环链表则在表尾插入非常的迅速, 只需O(1)的时间,因为有指向前面的指针, 因此双向循环链表会很容易的找到位于表尾的元素,因此双向循环链表比较适用于频繁在表尾插入的情况.



空链表:


双向循环链表节点构造:

[cpp] view plain copy
  1. class DoubleListNode  
  2. {  
  3. private:  
  4.     Type data;  
  5.     DoubleListNode *prev;   //前向指针域  
  6.     DoubleListNode *next;   //后项指针域  
  7. };  

因为需要将其用于DoubleList,因此需要将其改造如下:

[cpp] view plain copy
  1. template <typename Type>  
  2. class DoubleListNode  
  3. {  
  4.     //友元声明  
  5.     friend class DoubleList;  
  6.     friend class ListIterator;  
  7.   
  8.     template <typename T>  
  9.     friend ostream &operator<<(ostream &os, const DoubleList &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
  1. template <typename Type>  
  2. class DoubleList  
  3. {  
  4.     friend class ListIterator;  
  5.     template <typename T>  
  6.     friend ostream &operator<<(ostream &os, const DoubleList &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 *previous,  
  28.                        DoubleListNode *x);  
  29.     void removePrivate(DoubleListNode *x);  
  30.   
  31. private:  
  32.     DoubleListNode *first;  
  33. };  

链表的构造与析构:

[cpp] view plain copy
  1. //构造链表  
  2. template <typename Type>  
  3. DoubleList::DoubleList()  
  4. {  
  5.     first = new DoubleListNode(0);  
  6.     first->next = first;  
  7.     first->prev = first;  
  8. }  
[cpp] view plain copy
  1. //析构链表  
  2. template <typename Type>  
  3. DoubleList::~DoubleList()  
  4. {  
  5.     DoubleListNode *deleteNode = NULL;  
  6.     //保存链表尾元素  
  7.     DoubleListNode *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
  1. //同为private成员  
  2. //插入节点  
  3. template <typename Type>  
  4. void DoubleList::insertPrivate(DoubleListNode *previous,  
  5.                                      DoubleListNode *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
  1. //删除节点  
  2. template <typename Type>  
  3. void DoubleList::removePrivate(DoubleListNode *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
  1. //插入到表尾  
  2. template <typename Type>  
  3. void DoubleList::push_back(const Type &data)  
  4. {  
  5.     DoubleListNode *newNode = new DoubleListNode(data);  
  6.     //找到first的前一个节点  
  7.     DoubleListNode *previous = first->prev;  
  8.   
  9.     //插入  
  10.     insertPrivate(previous, newNode);  
  11. }  
  12. //插入到表头  
  13. template <typename Type>  
  14. void DoubleList::push_front(const Type &data)  
  15. {  
  16.     DoubleListNode *newNode = new DoubleListNode(data);  
  17.     //插入到first之后  
  18.     insertPrivate(first, newNode);  
  19. }  
  20.   
  21. //插入到任意位置(依position指定)  
  22. template <typename Type>  
  23. void DoubleList::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 *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 *newNode = new DoubleListNode(data);  
  46.     insertPrivate(previous, newNode);  
  47. }  

提供给客户的删除:

[cpp] view plain copy
  1. //删除表尾元素  
  2. template <typename Type>  
  3. void DoubleList::pop_back()  
  4. {  
  5.     removePrivate(first->prev);  
  6. }  
  7. //删除表头元素  
  8. template <typename Type>  
  9. void DoubleList::pop_front()  
  10. {  
  11.     removePrivate(first->next);  
  12. }  
  13.   
  14. //删除元素值为removeData的所有元素  
  15. template <typename Type>  
  16. void DoubleList::remove(const Type &removeData)  
  17. {  
  18.     if (isEmpty())  
  19.         throw std::range_error("link list is empty");  
  20.   
  21.     for( DoubleListNode *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
  1. template <typename Type>  
  2. bool DoubleList::search(const Type &searchData) const  
  3. {  
  4.     DoubleListNode *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
  1. template <typename Type>  
  2. ostream &operator<<(ostream &os, const DoubleList &list)  
  3. {  
  4.     for (DoubleListNode *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
  1. //除了添加了operator--, 几乎没做任何改变  
  2. template <typename Type>  
  3. class ListIterator  
  4. {  
  5. public:  
  6.     ListIterator(const DoubleList &_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 *operator->() const throw (std::out_of_range);  
  16.     DoubleListNode *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 &list;  
  37.     DoubleListNode *currentNode;  
  38. };  
[cpp] view plain copy
  1. template <typename Type>  
  2. const Type &ListIterator::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::operator*()  
  12. throw (std::out_of_range)  
  13. {  
  14.     return  
  15.         const_cast(  
  16.             static_cast<const ListIterator &>(*this).operator*()  
  17.         );  
  18. }  
[cpp] view plain copy
  1. template <typename Type>  
  2. const DoubleListNode *ListIterator::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 *ListIterator::operator->()  
  14. throw (std::out_of_range)  
  15. {  
  16.     return  
  17.         const_cast *> (  
  18.             static_cast<const ListIterator >(*this).operator->()  
  19.         );  
  20. }  
[cpp] view plain copy
  1. template <typename Type>  
  2. ListIterator &ListIterator::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 ListIterator::operator++(int)  
  13. throw (std::out_of_range)  
  14. {  
  15.     ListIterator tmp(*this);  
  16.     ++ (*this); //调用前向++版本  
  17.   
  18.     return tmp;  
  19. }  
[cpp] view plain copy
  1. template <typename Type>  
  2. ListIterator &ListIterator::operator--()  
  3. {  
  4.     //指针前移  
  5.     currentNode = currentNode->prev;  
  6.     return *this;  
  7. }  
  8. template <typename Type>  
  9. ListIterator ListIterator::operator--(int)  
  10. {  
  11.     ListIterator tmp(*this);  
  12.     -- (*this);  
  13.   
  14.     return tmp;  
  15. }  

测试代码:

[cpp] view plain copy
  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;  


原文地址:http://blog.csdn.net/zjf280441589/article/details/42463451

你可能感兴趣的:(算法与数据结构)