1.目的
基于双链表实现双端队列的典型操作(判空、头插、头删、尾插、尾删、普通构造、拷
贝构造、赋值运算符重 载、析构)
2.原理
双端队列头插:
双端队列尾插:
双端队列头删:
双端队列尾删:
3.代码
dlist.cpp
#include <iostream>
using namespace std;
template <typename T>
class Dlist {
public:
bool isEmpty() const; //判空
void insertFront(T *o); //在表头插入元素
void insertBack(T *o); //在表尾插入元素
T *removeFront(); //删除一个表头元素
T *removeBack(); //删除一个表尾元素
Dlist(); //构造函数
Dlist(const Dlist &l); //拷贝构造函数
Dlist& operator=(const Dlist &l); //"="运算符重载
~Dlist(); //析构函数
private:
struct Node {
Node(){ //给指针赋初始值
this->next = NULL;
this->prev = NULL;
this->o = NULL;
}
Node *next; //指向下一个节点
Node *prev; //指向前一个节点
T *o;
};
Node *first; //指向表头
Node *last; //指向表尾
void makeEmpty(); //建立一个空表
void removeAll(); //删除表中所有元素
void copyAll(const Dlist &l); //将l表中的元素值拷贝到当前表
};
template <typename T>
bool Dlist<T>::isEmpty() const //判空
{
return first == NULL;
}
template <typename T>
void Dlist<T>::insertFront(T *o) //在表头插入元素
{
Node *new_node = new Node(); //定义一个新的节点
new_node->o = o; //给新节点赋初值,将要插入的值放入新节点
if(first == NULL) //当原表为空时,表明要插入的节点为表头
{
first = last = new_node;
}
else{ //当原表不为空
first->prev = new_node; //将原表头的前指针指向新节点
new_node->next = first; //将新节点的后指针指向原表头
first = new_node; //让表头指向新节点
}
}
template <typename T>
void Dlist<T>::insertBack(T *o) //在表尾插入元素
{
Node *new_node = new Node(); //定义一个新的节点
new_node->o = o; //给新节点赋初值,将要插入的值放入新节点
if(first == NULL) //当原表为空时,表明要插入的节点为表头
{
first = last = new_node;
}
else{ //当原表不为空
last->next = new_node; //将原表尾的后指针指向新节点
new_node->prev = last; //将新节点的前指针指向原表尾
last = new_node; //让表尾指向新节点
}
}
template <typename T>
T* Dlist<T>::removeFront() //删除一个表头元素
{
Node *new_node = NULL; //定义一个新的节点
T* p;
if(NULL == first)
return NULL; //如果表是空的则返回空
new_node = first; //让新指针指向表头
p = new_node->o; //保存表头元素值
first = first->next; //表头向后移一位
if(NULL != first)
{
first->prev = NULL; //新的表头的前指针置空
}
else{
first = NULL; //如果表中无元素,将表头置空
}
delete new_node; //删除原表头
return p;
}
template <typename T>
T* Dlist<T>::removeBack() //删除一个表尾元素
{
Node *new_node = NULL; //定义一个新的节点
T* p = NULL;
if(NULL == first)
{
return NULL;//如果表是空的则返回空
}
new_node = last; //让新指针指向表尾
p = last->o; //保存表尾元素值
last = last->prev; //表尾向前移一位
if(last != NULL) //如果表尾前还有元素
{
last->next = NULL; //新的表尾的后指针置空
}
else{
first = NULL; //如果表中无元素,将表头置空
}
delete new_node; //删除原表尾
return p;
}
template <typename T>
Dlist<T>::Dlist() //构造函数
{
makeEmpty(); //建立一个空表
}
template <typename T>
Dlist<T>::Dlist(const Dlist &l) //拷贝构造函数
{
makeEmpty(); //建立一个空表
copyAll(l); //将l表元素复制到当前表
}
template <typename T>
Dlist<T>& Dlist<T>::operator=(const Dlist &l) //"="运算符重载
{
Dlist new_copy(l); //调用拷贝构造函数,将l表元素拷贝给new_copy
removeAll(); //删除原表中所有元素
first = new_copy.first; //让当前表的头指针指向new_copy的头指针
last = new_copy.last; //让当前表的尾指针指向new_copy的尾指针
new_copy.first = NULL;
new_copy.last = NULL;
return *this; //返回当前表
}
template <typename T>
Dlist<T>::~Dlist() //析构函数
{
if( !isEmpty() ){ //当表不为空时删除所有元素
removeAll();
}
}
template <typename T>
void Dlist<T>::makeEmpty() //建立一个空表
{
first = NULL; //初始化指向表头的指针
last = NULL; //初始化指向表尾的指针
}
template <typename T>
void Dlist<T>::removeAll() //删除表中所有元素
{
Node *p = NULL;
while(first != NULL){ //遍历当前表,逐个删除
p = first;
first = first->next;
delete p;
}
}
template <typename T>
void Dlist<T>::copyAll(const Dlist &l) //将l表中的元素值拷贝到当前表
{
Node *old_node = NULL; //定义指针指向要拷贝的表
old_node = l.first; //指向要拷贝的表的表头
while(old_node != NULL) //当要拷贝的表有元素时拷贝
{
insertBack(old_node->o);//将元素依次从后面插入当前表中
old_node = old_node->next;
}
}
测试类 distmain.cpp
#include <iostream>
#include "dlist.cpp"
using namespace std;
int main()
{
Dlist<int> ilist;
Dlist<int> one;
int *ip = new int(3);
int *j = new int(5);
int *i = new int (7);
int *p = new int();
ilist.insertFront(ip); //3
ilist.insertFront(j); //5 3
ilist.insertBack(i); //5 3 7
one = ilist; //测试“=”运算符重载
p = one.removeFront(); //返回并删除one的第一个数据
cout << "one first number is:" << *p << endl; //结果应为5
Dlist<int> two(ilist); //测试拷贝构造函数
p = two.removeFront(); //返回并删除two的第一个数据
cout << "two first number is:" << *p << endl; //结果应为5
ip = ilist.removeFront(); //返回并删除ilist的第一个数据
cout << "ilist first number is:" << *ip << endl; //结果应为5
j = ilist.removeBack(); //测试从末尾删除元素,返回并删除ilist的最后一个数据
cout << "ilist last number is:" << *j << endl; //结果应为7
delete ip;
delete j;
delete i;
delete p;
return 0;
}
运行结果:
结果解释:
程序先依次从ilist表头中插入3,5,然后从表尾插入7,则表中数据依次5,3,7.
one表是用来测试“=”运算符重载函数的,让one=ilist,取其头元素的值。第一行值
为5,说明正确。
two表是用来测试拷贝构造函数的,取其表头的值,第二行值为5,说明拷贝构造函数正确。
第三行是测试从表头返回并删除元素,值为5,说明正确。
第四行是测试从表尾返回并删除元素,值为7,说明正确。