”双向链表与队列“
“双向链表”是包含两个指针域,一个数据域,既有指向前驱的指针,还有指向后继的指针,同时可以从两个方向对链表进行遍历,访问各个节点。“双向链表”较”单链表“在插入和删除节点方面更为简单,但是所占的空间比“单链表”大。“队列”的实现之所以选择使用双向链表,是因为队列的特点是“先进先出”,如若使用顺序表则很大程度上的浪费空间。在这样的情境下,链表较顺序表更为合适。
根据“模板”的概念,设计并实现双向链表,进而实现队列的基本功能。下面是利用模板来实现双向链表的具体代码:
#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;
};
转载于:https://blog.51cto.com/10740590/1753241