数据结构基础(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 == 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) {}//重載 *operatorconst Type &operator*() const throw (std::out_of_range);Type &operator*() throw (std::out_of_range);//重載 ->operatorconst DoubleListNode<Type> *operator->() const throw (std::out_of_range);DoubleListNode<Type> *operator->() throw (std::out_of_range);//重載 ++operatorListIterator &operator++() throw (std::out_of_range);//注意:此處返回的是值,而不是referenceListIterator operator++(int) throw (std::out_of_range);//重載 --operator,// 其實這個版本的--operator是不完美的,// 因為他沒有做任何的判錯控制ListIterator &operator--();//注意:此處返回的是值,而不是referenceListIterator 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) {returnconst_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) {returnconst_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;elsecout << 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) --双向循环链表的设计与实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ATL中集合和枚举器
- 下一篇: 介绍JSON