数据结构基础(12) --双向循环链表的设计与实现
来源:互联网 发布:mac照片拷贝到移动硬盘 编辑:程序博客网 时间:2024/06/05 16:33
双向链表的操作特点:
(1) “查询” 和单链表相同;
(2)“插入” 和“删除”时需要同时修改两个方向上的指针。
但是对于双向循环链表则在表尾插入非常的迅速, 只需O(1)的时间,因为有指向前面的指针, 因此双向循环链表会很容易的找到位于表尾的元素,因此双向循环链表比较适用于频繁在表尾插入的情况.
空链表:
双向循环链表节点构造:
- class DoubleListNode
- {
- private:
- Type data;
- DoubleListNode *prev; //前向指针域
- DoubleListNode *next; //后项指针域
- };
因为需要将其用于DoubleList类,因此需要将其改造如下:
- template <typename Type>
- class DoubleListNode
- {
- //友元声明
- friend class DoubleList<Type>;
- friend class ListIterator<Type>;
- template <typename T>
- friend ostream &operator<<(ostream &os, const DoubleList<T> &list);
- private:
- DoubleListNode(const Type &dataValue)
- :data(dataValue),prev(NULL),next(NULL) {}
- Type data;
- DoubleListNode *prev; //前向指针域
- DoubleListNode *next; //后项指针域
- };
双向循环链表构造:
- template <typename Type>
- class DoubleList
- {
- friend class ListIterator<Type>;
- template <typename T>
- friend ostream &operator<<(ostream &os, const DoubleList<T> &list);
- public:
- DoubleList();
- ~DoubleList();
- void push_back(const Type &data);
- void push_front(const Type &data);
- void insert(int position, const Type &data);
- void pop_front();
- void pop_back();
- void remove(const Type &removeData);
- bool search(const Type &searchData) const;
- bool isEmpty() const
- {
- return (first->next == first);
- }
- private:
- //将节点x插入到节点previous后面
- void insertPrivate(DoubleListNode<Type> *previous,
- DoubleListNode<Type> *x);
- void removePrivate(DoubleListNode<Type> *x);
- private:
- DoubleListNode<Type> *first;
- };
链表的构造与析构:
- //构造链表
- template <typename Type>
- DoubleList<Type>::DoubleList()
- {
- first = new DoubleListNode<Type>(0);
- first->next = first;
- first->prev = first;
- }
- //析构链表
- template <typename Type>
- DoubleList<Type>::~DoubleList()
- {
- DoubleListNode<Type> *deleteNode = NULL;
- //保存链表尾元素
- DoubleListNode<Type> *tmp = first;
- //first首先指向第一个真实的元素
- first = first->next;
- //一路到达链表结尾
- while (first != tmp)
- {
- deleteNode = first;
- first = first -> next;
- delete deleteNode;
- }
- // 释放掉链表的空节点(表头)
- delete tmp;
- }
链表元素插入与删除的两大主力:
- //同为private成员
- //插入节点
- template <typename Type>
- void DoubleList<Type>::insertPrivate(DoubleListNode<Type> *previous,
- DoubleListNode<Type> *x)
- {
- x->prev = previous;
- x->next = previous->next;
- previous->next->prev = x;
- previous->next = x;
- }
- //删除节点
- template <typename Type>
- void DoubleList<Type>::removePrivate(DoubleListNode<Type> *x)
- {
- if (x == first)
- throw std::range_error("permission denied to delete first pointer");
- x->prev->next = x->next;
- x->next->prev = x->prev;
- delete x;
- }
提供给客户的插入:
- //插入到表尾
- template <typename Type>
- void DoubleList<Type>::push_back(const Type &data)
- {
- DoubleListNode<Type> *newNode = new DoubleListNode<Type>(data);
- //找到first的前一个节点
- DoubleListNode<Type> *previous = first->prev;
- //插入
- insertPrivate(previous, newNode);
- }
- //插入到表头
- template <typename Type>
- void DoubleList<Type>::push_front(const Type &data)
- {
- DoubleListNode<Type> *newNode = new DoubleListNode<Type>(data);
- //插入到first之后
- insertPrivate(first, newNode);
- }
- //插入到任意位置(依position指定)
- template <typename Type>
- void DoubleList<Type>::insert(int position, const Type &data)
- {
- if (position == 1)
- return push_front(data);
- int count = 1;
- //previous 代表着要插入位置之前的一个位置
- DoubleListNode<Type> *previous = first->next;
- //如果position过大, 则previous查找到first就会停止
- //此时应该将该元素插入到链表结尾
- while (count < position-1 && previous != first)
- {
- ++ count;
- previous = previous->next;
- }
- //如果查找到了链表结尾或此时链表为空, 因此插入到表尾
- if (previous == first)
- return push_back(data);
- //如果找到了合适的插入位置
- DoubleListNode<Type> *newNode = new DoubleListNode<Type>(data);
- insertPrivate(previous, newNode);
- }
提供给客户的删除:
- //删除表尾元素
- template <typename Type>
- void DoubleList<Type>::pop_back()
- {
- removePrivate(first->prev);
- }
- //删除表头元素
- template <typename Type>
- void DoubleList<Type>::pop_front()
- {
- removePrivate(first->next);
- }
- //删除元素值为removeData的所有元素
- template <typename Type>
- void DoubleList<Type>::remove(const Type &removeData)
- {
- if (isEmpty())
- throw std::range_error("link list is empty");
- for( DoubleListNode<Type> *searchNode = first->next;
- searchNode != first;
- searchNode = searchNode->next)
- {
- if (searchNode->data == removeData)
- removePrivate(searchNode);
- }
- }
查看是否存在于链表中:
- template <typename Type>
- bool DoubleList<Type>::search(const Type &searchData) const
- {
- DoubleListNode<Type> *searchNode = first->next;
- while (searchNode != first)
- {
- if (searchNode->data == searchData)
- return true;
- searchNode = searchNode->next;
- }
- return false;
- }
输出链表所有元素(测试用):
- template <typename Type>
- ostream &operator<<(ostream &os, const DoubleList<Type> &list)
- {
- for (DoubleListNode<Type> *currentNode = (list.first)->next;
- currentNode != list.first;
- currentNode = currentNode->next)
- os << currentNode->data << ' ';
- return os;
- }
双向循环链表迭代器的设计与实现:
- //除了添加了operator--, 几乎没做任何改变
- template <typename Type>
- class ListIterator
- {
- public:
- ListIterator(const DoubleList<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 DoubleListNode<Type> *operator->() const throw (std::out_of_range);
- DoubleListNode<Type> *operator->() throw (std::out_of_range);
- //重载 ++operator
- ListIterator &operator++() throw (std::out_of_range);
- //注意:此处返回的是值,而不是reference
- ListIterator operator++(int) throw (std::out_of_range);
- //重载 --operator,
- // 其实这个版本的--operator是不完美的,
- // 因为他没有做任何的判错控制
- ListIterator &operator--();
- //注意:此处返回的是值,而不是reference
- ListIterator operator--(int);
- bool isEmpty() const
- {
- return (currentNode == list.first);
- }
- private:
- const DoubleList<Type> &list;
- DoubleListNode<Type> *currentNode;
- };
- 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)
- {
- return
- const_cast<Type &>(
- static_cast<const ListIterator<Type> &>(*this).operator*()
- );
- }
- template <typename Type>
- const DoubleListNode<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>
- DoubleListNode<Type> *ListIterator<Type>::operator->()
- throw (std::out_of_range)
- {
- return
- const_cast<DoubleListNode<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;
- }
- template <typename Type>
- ListIterator<Type> &ListIterator<Type>::operator--()
- {
- //指针前移
- currentNode = currentNode->prev;
- return *this;
- }
- template <typename Type>
- ListIterator<Type> ListIterator<Type>::operator--(int)
- {
- ListIterator<Type> tmp(*this);
- -- (*this);
- return tmp;
- }
测试代码:
- int main()
- {
- cout << "-------- 1 --------" << endl;
- DoubleList<int> myList;
- for (int i = 0; i < 3; ++i)
- myList.push_back(i+1);
- for (int i = 0; i < 5; ++i)
- myList.push_front(10+i);
- for (int i = 0; i < 3; ++i)
- myList.push_back(i+1);
- ListIterator<int> iter(myList), iter2(myList);
- while (!iter.isEmpty())
- {
- cout << *iter << ' ';
- ++ iter;
- ++ iter2;
- }
- cout << endl;
- -- iter2;
- while (!iter2.isEmpty())
- {
- cout << *iter2 << ' ';
- iter2 --;
- }
- cout << endl;
- cout << "-------- 2 --------" << endl;
- cout << myList << endl;
- cout << "Test insert..." << endl;
- myList.insert(1, 14);
- myList.insert(2, 13);
- myList.insert(2, 13);
- myList.insert(88, 88);
- cout << myList << endl;
- myList.pop_back();
- myList.pop_front();
- cout << myList << endl;
- for (int i = 0; i < 5; ++i)
- {
- if (myList.search(i))
- cout << i << ": Have found!" << endl;
- else
- cout << i << ": Not in the list!" << endl;
- }
- cout << "Test remove..." << endl;
- cout << myList << endl;
- int value;
- while (cin >> value)
- {
- try
- {
- myList.remove(value);
- }
- catch (const std::exception &e)
- {
- cerr << e.what() << endl;
- }
- cout << myList << endl;
- if (myList.isEmpty())
- {
- cout << "empty" << endl;
- }
- else
- {
- cout << "not empty" << endl;
- }
- }
- return 0;
- }
0 0
- 数据结构基础(12) --双向循环链表的设计与实现
- 数据结构基础(12) --双向循环链表的设计与实现
- 数据结构基础(12) --双向循环链表的设计与实现
- 数据结构基础(11) --循环链表的设计与实现
- 数据结构基础(11) --循环链表的设计与实现
- 数据结构基础(11) --循环链表的设计与实现
- 基础数据结构--双向链表的实现
- 数据结构:双向链表实现队列与循环链表
- 数据结构---双向链表实现队列与循环链表
- 数据结构基础(7) --循环队列的设计与实现
- 数据结构基础(7) --循环队列的设计与实现
- 数据结构基础(7) --循环队列的设计与实现
- 数据结构 P36-37 算法实现 双向循环链表的插入与删除
- 数据结构的C实现_双向循环链表
- 数据结构之——循环双向链表的实现
- 数据结构 P35 算法实现 双向循环链表的创建
- 【数据结构】双向循环链表实现
- 数据结构通用双向循环链表实现
- redhat7 安装 docker
- 【Boost】boost库中function和bind一起使用的技巧(二)
- const 使用
- iOS毛玻璃效果
- IA64 IA32 x64的理解
- 数据结构基础(12) --双向循环链表的设计与实现
- java基本数据类型总结
- POJ 2536 大数取模运算
- 使用开源imageLoader优化listview加载大量本地图片的demo
- 浏览器插件之ActiveX开发(二)
- gearmand的安装
- 计算器
- Linux 常用命令
- hadoop 2.6.3 BlockPlacementPolicyDefault源代码分析