首页 > 代码库 > 数据结构基础(12) --双向循环链表的设计与实现
数据结构基础(12) --双向循环链表的设计与实现
双向链表的操作特点:
(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 =http://www.mamicode.com/= removeData)>查看是否存在于链表中:
template <typename Type> bool DoubleList<Type>::search(const Type &searchData) const { DoubleListNode<Type> *searchNode = first->next; while (searchNode != first) { if (searchNode->data =http://www.mamicode.com/= searchData)>输出链表所有元素(测试用):
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; }数据结构基础(12) --双向循环链表的设计与实现
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。