”双向链表与队列“
“双向链表”是包含两个指针域,一个数据域,既有指向前驱的指针,还有指向后继的指针,同时可以从两个方向对链表进行遍历,访问各个节点。“双向链表”较”单链表“在插入和删除节点方面更为简单,但是所占的空间比“单链表”大。“队列”的实现之所以选择使用双向链表,是因为队列的特点是“先进先出”,如若使用顺序表则很大程度上的浪费空间。在这样的情境下,链表较顺序表更为合适。
根据“模板”的概念,设计并实现双向链表,进而实现队列的基本功能。下面是利用模板来实现双向链表的具体代码:
#pragma once #include <assert.h> //双向链表 template <class T> struct ListNode { T _data; ListNode<T> * _next; ListNode<T> * _prev; ListNode(const T& x) :_data(x) , _next(NULL) , _prev(NULL) { } }; template <class T> class List { public: List() //构造函数 :_head(NULL) , _tail(NULL) { } ~List() //析构函数 { Clear(); } public: void pushBack(const T & x) //尾插 { if (_head == NULL) { _head = _tail = new ListNode<T>(x); } else { ListNode<T> * tmp = new ListNode<T>(x); _tail->_next = tmp; tmp->_prev = _tail; _tail = tmp; tmp->_next = NULL; } } void popBack() //尾删 { if (_head == NULL) { return; } else if (_head == _tail) { delete _tail; _head = _tail = NULL; } else { ListNode<T> * tmp = _tail->_prev; delete _tail; tmp->_next = NULL; _tail = tmp; } } void pushFront(const T & x) //头插 { ListNode<T> * tmp = new ListNode<T>(x); if (_head == NULL) { _head = _tail = tmp; } else { tmp->_next = _head; tmp->_prev = NULL; _head = tmp; } } void popFront() //头删 { if (_head == _tail) { if (_head) { delete _head; _head = _tail = NULL; } } else { ListNode<T> * tmp = _head->_next; delete _head; _head = tmp; tmp->_prev = NULL; } } void Insert(ListNode<T> * pos,const T& x) //在pos位置上插入数据x { assert(pos); ListNode<T> * tmp = new ListNode<T>(x); ListNode<T> * cur = pos->_next; tmp->_next = cur; cur->_prev = tmp; tmp->_prev = pos; pos->_next = tmp; } void Erase(ListNode<T> * pos) //删除pos位置上的数据 { assert(pos); if (_head == NULL) { return; } else if (_head == _tail) { delete _head; } else { ListNode<T> * cur = pos->_next; ListNode<T> * tmp = pos->_prev; tmp->_next = cur; cur->_prev = tmp; delete pos; } } ListNode<T> * Find(const T & x) //查找 { ListNode<T> * tmp = _head; while (tmp) { if (tmp->_data == x) { return tmp; } tmp = tmp->_next; } if (tmp->_next) { return NULL; } } T & Top() //读取队头元素 { return _head->_data; } T & Back() //读取队尾元素 { assert(size > 0); return _tail->_data; } void Reverse() //逆置 { swap(_head, _tail); ListNode<T>* tmp = _head; while (tmp) { swap(tmp->_prev, tmp->_next); tmp = tmp->_next; } } void Sort() //冒泡排序 { ListNode<T> * cur = _head; ListNode<T> * tmp = _head->_next; while (tmp) { if (cur->_data > tmp->_data) { T ptr = cur->_data; cur->_data = tmp->_data; tmp->_data = ptr; } cur = cur->_next; tmp = tmp->_next; } } void Unique() //在有序链表中,去掉重复的数据 { ListNode<T> * cur = _head; ListNode<T> * tmp = _head->_next; while (tmp) { while (cur->_data == tmp->_data) { ListNode<T>* str = tmp; tmp = tmp->_next; Erase(str); } cur = cur->_next; tmp = tmp->_next; } } void Merge(List<T> & s) //将某一个链表连接到这个链表后面 { _tail->_next = s._head; s._head->_prev = _tail; } void Splice(ListNode<T> * pos, List<T> & s) //将一个链表连接到pos位置后面 { assert(pos); if (pos == _tail) { Merge(s); } else { ListNode<T> * cur = pos; ListNode<T> * tmp = pos->_next; ListNode<T> * str = s._tail; cur->_next = s._head; s._head->_prev = cur; str->_next = tmp; tmp->_prev = str; } } size_t Size() //计算链表中的元素个数 { ListNode<T> * tmp = _head; int count = 0; while (tmp) { count++; tmp = tmp->_next; } return count; } void print() //格式输出 { ListNode<T> * tmp = _head; while (tmp) { cout << tmp->_data << " "; tmp = tmp->_next; } cout << endl; } void Clear() { ListNode<T> * tmp = _head; while (tmp) { ListNode<T> * str = tmp; tmp = tmp->_next; delete str; } } private: ListNode<T> * _head; ListNode<T> * _tail; };
对于”队列“能够利用上述双向链表的功能来实现,下面就是基本的程序代码:
#pragma once #include <string> //队列 #include <assert.h> #include "ListNode.h" template <class T , template<class> class container = List> class Queue { public: void push(const T & x) //进入队列 { _con.pushBack(x); } void pop() //出队列 { _con.popFront(); } bool Empty() //判断队列是否为空 { return _con.Size() == 0; } size_t size() //计算队列中的元素个数 { return _con.size(); } T & top() //队头节点 { return _con.Top(); } T & Back() //队尾节点 { return _con.Back(); } void print() //格式输出 { _con.print(); } private: container<T> _con; };
本文出自 “无心的执着” 博客,谢绝转载!
原文地址:http://10740590.blog.51cto.com/10730590/1753241