循环链表:最后一个结点的指针域的指针又指回第一个结点的链表;
循环单链表与单链表的区别在于:表中最有一个节点的指针不再是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;
- }
原文地址:http://blog.csdn.net/zjf280441589/article/details/42430955