循環鏈表:最後一個結點的指針域的指針又指回第一個結點的鏈表;
循環單鏈表與單鏈表的區別在於:表中最有一個節點的指針不再是NULL, 而改爲指向頭結點(因此要對我們原來的MyList稍作修改), 從而整個鏈表形成一個環.
因此, 循環單鏈表的判空條件不再是頭結點的指針是否爲空, 而是他是否等於頭結點;
其實如果只是單純的實現循環鏈表對單鏈表的性能提升是不明顯的, 反而增加了代碼上實現的複雜度, 但是如果與下一篇中的雙向鏈表相結合的話, 在速度上的提升是十分驚人的, 因此這篇博客權當做是一個過渡吧, 爲上一篇博客和下一篇博客的結合起着承上啓下的作用.
下面是MyList.h的完整代碼與解析, 由於代碼較多, 希望能夠仔細閱讀, 但其實下面的大部分代碼都與前面類似只是對其中幾處稍作修改, 遇到與單鏈表的不同之處, 我會與++符號作爲註釋指出:
- #ifndef MYLIST_H_INCLUDED
- #define MYLIST_H_INCLUDED
- #include <iostream>
- #include <stdexcept>
- using namespace std;
- //循環鏈表
- //前向聲明
- template <typename Type>
- class MyList;
- template <typename Type>
- class ListIterator;
- //鏈表節點
- template <typename Type>
- class Node
- {
- //可以將MyList類作爲Node的友元
- //同時也可以將Node類做成MyList的嵌套類, 嵌套在MyList中, 也可以完成該功能
- friend class MyList<Type>;
- friend class ListIterator<Type>;
- template <typename T>
- friend ostream &operator<<(ostream &os, const MyList<T> &list);
- private:
- //constructor說明:
- //next = NULL; //因爲這是一個新生成的節點, 因此下一個節點爲空
- Node(const Type &dataValue):data(dataValue), next(NULL) {}
- Type data; //數據域:節點數據
- Node *next; //指針域:下一個節點
- };
- //鏈表
- template <typename Type>
- class MyList
- {
- template <typename T>
- friend ostream &operator<<(ostream &os, const MyList<T> &list);
- friend class ListIterator<Type>;
- public:
- MyList();
- ~MyList();
- //將元素插入表頭
- void insertFront(const Type &data);
- //將元素插入到位置index上(index從1開始)
- void insert(const Type &data, int index);
- //刪除表中所有值爲data的節點
- void remove(const Type &data);
- bool isEmpty() const;
- private:
- //指向第一個節點的指針
- Node<Type> *first;
- };
- template <typename Type>
- MyList<Type>::MyList()
- {
- //first指向一個空節點
- first = new Node<Type>(0);
- // ++ 這是一個關鍵點
- //first的下一個元素就指向first
- //此時, 代表鏈表是否已經到達結尾處的判斷已經不再是(是否等於NULL)
- //而改爲(是否等於first)
- //因爲此時first代表鏈表的最後一個元素
- //同時,first又是第一個元素的前一個元素
- first -> next = first;
- }
- template <typename Type>
- MyList<Type>::~MyList()
- {
- Node<Type> *deleteNode = NULL;
- // ++ 保存鏈表尾元素
- Node<Type> *tmp = first;
- // ++ first首先指向第一個真實的元素
- first = first->next;
- //一路到達鏈表結尾
- while (first != tmp)
- {
- deleteNode = first;
- first = first -> next;
- delete deleteNode;
- }
- // ++ 釋放到鏈表的空節點
- delete tmp;
- }
- //這一步與前一版鏈表相同
- template <typename Type>
- void MyList<Type>::insertFront(const Type &data)
- {
- Node<Type> *newNode = new Node<Type>(data);
- newNode -> next = first -> next;
- first -> next = newNode;
- }
- template <typename Type>
- void MyList<Type>::insert(const Type &data, int index)
- {
- //由於我們在表頭添加了一個空節點
- //因此如果鏈表爲空, 或者在鏈表爲1的位置添加元素
- //其操作與在其他位置添加元素相同
- int count = 1;
- //此時searchNode肯定不爲first
- Node<Type> *searchNode = first;
- //++ 注意:此處將NULL修改爲first
- // 找到要插入的位置
- // 如果所給index過大(超過了鏈表的長度)
- // 則將該元素插入到鏈表表尾
- // 原因是 searchNode->next != first 這個條件已經不滿足了
- while (count < index && searchNode->next != first)
- {
- ++ count;
- searchNode = searchNode->next;
- }
- // 插入鏈表
- Node<Type> *newNode = new Node<Type>(data);
- newNode->next = searchNode->next;
- searchNode->next = newNode;
- }
- template <typename Type>
- void MyList<Type>::remove(const Type &data)
- {
- if (isEmpty())
- return ;
- Node<Type> *previous = first; //保存要刪除節點的前一個節點
- for (Node<Type> *searchNode = first->next;
- //searchNode != NULL; // ++ 注意此處不再是判斷是否爲NULL
- searchNode != first; // ++ 而是不能等於first, first代表鏈表的末尾
- searchNode = searchNode->next)
- {
- if (searchNode->data == data)
- {
- previous->next = searchNode->next;
- delete searchNode;
- //重新調整searchNode指針
- //繼續遍歷鏈表查看是否還有相等元素
- // ++ 注意
- //如果當前searchNode已經到達了最後一個節點
- //也就是searchNode->next已經等於first了, 則下面這條語句不能執行
- if (previous->next == first)
- break;
- searchNode = previous->next;
- }
- previous = searchNode;
- }
- }
- //注意判空條件
- template <typename Type>
- bool MyList<Type>::isEmpty() const
- {
- return first->next == first;
- }
- //顯示鏈表中的所有數據(測試用)
- template <typename Type>
- ostream &operator<<(ostream &os, const MyList<Type> &list)
- {
- for (Node<Type> *searchNode = list.first -> next;
- searchNode != list.first; //++ 注意
- searchNode = searchNode -> next)
- {
- os << searchNode -> data;
- if (searchNode -> next != list.first) // ++ 注意(尚未達到鏈表的結尾)
- cout << " -> ";
- }
- return os;
- }
- //ListIterator 除了判空函數的判空條件之外, 沒有任何改變
- template <typename Type>
- class ListIterator
- {
- public:
- ListIterator(const MyList<Type> &_list):
- list(_list),
- currentNode((_list.first)->next) {}
- //重載 *operator
- const Type &operator*() const throw (std::out_of_range);
- Type &operator*() throw (std::out_of_range);
- //重載 ->operator
- const Node<Type> *operator->() const throw (std::out_of_range);
- Node<Type> *operator->() throw (std::out_of_range);
- //重載 ++operator
- ListIterator &operator++() throw (std::out_of_range);
- //注意:此處返回的是值,而不是reference
- ListIterator operator++(int) throw (std::out_of_range);
- bool isEmpty() const;
- private:
- const MyList<Type> &list;
- Node<Type> *currentNode;
- };
- template <typename Type>
- bool ListIterator<Type>::isEmpty() const
- {
- // ++ 注意:判空條件改爲list.first
- if (currentNode == list.first)
- return true;
- return false;
- }
- template <typename Type>
- const Type &ListIterator<Type>::operator*() const
- throw (std::out_of_range)
- {
- if (isEmpty())
- throw std::out_of_range("iterator is out of range");
- // 返回當前指針指向的內容
- return currentNode->data;
- }
- template <typename Type>
- Type &ListIterator<Type>::operator*()
- throw (std::out_of_range)
- {
- //首先爲*this添加const屬性,
- //以調用該函數的const版本,
- //然後再使用const_case,
- //將該函數調用所帶有的const屬性轉除
- //operator->()的non-const版本與此類同
- return
- const_cast<Type &>(
- static_cast<const ListIterator<Type> &>(*this).operator*()
- );
- }
- template <typename Type>
- const Node<Type> *ListIterator<Type>::operator->() const
- throw (std::out_of_range)
- {
- if (isEmpty())
- throw std::out_of_range("iterator is out of range");
- //直接返回指針
- return currentNode;
- }
- template <typename Type>
- Node<Type> *ListIterator<Type>::operator->()
- throw (std::out_of_range)
- {
- // 見上
- return
- const_cast<Node<Type> *> (
- static_cast<const ListIterator<Type> >(*this).operator->()
- );
- }
- template <typename Type>
- ListIterator<Type> &ListIterator<Type>::operator++()
- throw (std::out_of_range)
- {
- if (isEmpty())
- throw std::out_of_range("iterator is out of range");
- //指針前移
- currentNode = currentNode->next;
- return *this;
- }
- template <typename Type>
- ListIterator<Type> ListIterator<Type>::operator++(int)
- throw (std::out_of_range)
- {
- ListIterator tmp(*this);
- ++ (*this); //調用前向++版本
- return tmp;
- }
- #endif // MYLIST_H_INCLUDED
附-測試代碼:
- int main()
- {
- MyList<int> iMyList;
- for (int i = 0; i < 10; ++i) //1 2 3 4 5 6 7 8 9 10
- iMyList.insert(i+1, i+1);
- for (int i = 0; i < 5; ++i) //40 30 20 10 0 1 2 3 4 5 6 7 8 9 10
- iMyList.insertFront(i*10);
- iMyList.insertFront(100);//100 40 30 20 10 0 1 2 3 4 5 6 7 8 9 10
- iMyList.remove(10); //100 40 30 20 0 1 2 3 4 5 6 7 8 9
- iMyList.remove(8); //100 40 30 20 0 1 2 3 4 5 6 7 9
- cout << "------------ MyList ------------" << endl;
- for (ListIterator<int> iter(iMyList);
- !(iter.isEmpty());
- ++ iter)
- cout << *iter << ' ';
- cout << endl;
- cout << "Test: \n\t" << iMyList << endl;
- return 0;
- }