CLinkedDeQue.h文件
#pragma once
/*
*Copyright? 中国地质大学(武汉) 信息工程学院
*All right reserved.
*
*文件名称:CLinkedDeQue.h
*摘 要:链式双端队列的定义及实现
*
*当前版本:1.0
*作 者:邵玉胜
*完成日期:2018-04
*/
#ifndef CLINKEDDEQUE
#define CLINKEDDEQUE
#include<iostream>
using namespace std;
//结点结构体的定义
template<class _Ty>
struct CLinkedNode {
_Ty m_tData; //数据域
CLinkedNode<_Ty>* m_pLast; //指针域-指向上一个元素
CLinkedNode<_Ty>* m_pNext; //指针域-指向下一元素
CLinkedNode(_Ty data,
CLinkedNode<_Ty>* last = nullptr,
CLinkedNode<_Ty>* next = nullptr) {
m_tData = data;
m_pLast = last;
m_pNext = next;
}
CLinkedNode<_Ty>* InsertNext(const _Ty data) { //向后插入一个元素-返回下一个元素的地址
m_pNext = new CLinkedNode<_Ty>(data);
if (m_pNext == nullptr) {
cerr << "内存分配错误!" << endl;
exit(-1);
}
return m_pNext;
}
CLinkedNode<_Ty>* InsertLast(const _Ty data) { //向后插入一个元素-返回下一个元素的地址
m_pLast = new CLinkedNode<_Ty>(data);
if (m_pLast == nullptr) {
cerr << "内存分配错误!" << endl;
exit(-1);
}
return m_pLast;
}
};
template<class _Ty>
class CLinkedDeQue {
public:
CLinkedDeQue() :m_pFront(nullptr), m_pRear(nullptr) {} //构造函数,将头指针与尾指针都设为空
CLinkedDeQue(CLinkedDeQue<_Ty>& Q); //赋值构造函数
~CLinkedDeQue(); //析构函数
CLinkedDeQue<_Ty>& operator = (CLinkedDeQue<_Ty>& Q); //重载赋值运算符
void EnQueue(const _Ty data); //进队-默认在队尾入队
bool DeQueue(_Ty& data); //出队-默认在队头出队
void EnQueueHead(const _Ty data); //从队头入队
void EnQueueRear(const _Ty data); //从队尾入队
bool DeQueueHead(_Ty& data); //从队头出队
bool DeQueueRear(_Ty& data); //从队尾出队
bool GetFrontData(_Ty& data); //获取队头值
bool GetRearData(_Ty& data); //获取队尾值
void MakeEmpty(); //置空函数
bool IsEmpty(); //判空函数
int GetSize(); //获取队列大小
//重载输入运算符
//模板类的输入输出运算符的重载要写在类内种
friend istream& operator >> (istream& in, CLinkedDeQue<_Ty>& Q) {
cout << "请输入一个队列,输入\"#\"结束:";
_Ty data;
while (in >> data) {
if (data == '#')
break;
else {
Q.EnQueueRear(data);
}
}
return in;
}
//重载输出运算符
//模板类的输入输出运算符的重载要写在类内种
friend ostream& operator<<(ostream& out, CLinkedDeQue<_Ty>& Q) {
CLinkedNode<_Ty>* srcPtr = Q.GetHead();
if (srcPtr == nullptr)
out << "队列为空!" << endl;
else {
_Ty data;
out << "队列中的元素为:";
while (srcPtr != nullptr) {
data = srcPtr->m_tData;
out << data << " ";
srcPtr = srcPtr->m_pNext;
}
out << endl;
}
return out;
}
private:
CLinkedNode<_Ty>* m_pFront; //头指针
CLinkedNode<_Ty>* m_pRear; //尾指针
CLinkedNode<_Ty>* GetHead() { //获取队头指针
return m_pFront;
}
CLinkedNode<_Ty>* GetRear() { //获取队尾指针
return m_pRear;
}
};
//赋值构造函数
template<class _Ty>
CLinkedDeQue<_Ty>::CLinkedDeQue(CLinkedDeQue<_Ty>& Q) {
CLinkedNode<_Ty>* srcPtr = Q.GetHead(); //指向参数第一个结点
_Ty data;
while (srcPtr != nullptr) { //如果还未复制完
data = srcPtr->m_tData; //取出当前结点的数值
this->EnQueueRear(data); //将该数值从队尾加入
srcPtr = srcPtr->m_pLink; //指向参数队列指向下一项
}
}
template<class _Ty>
CLinkedDeQue<_Ty>& CLinkedDeQue<_Ty>::operator =
(CLinkedDeQue<_Ty>& Q) { //重载赋值运算符
CLinkedNode<_Ty>* srcPtr = Q.GetHead(); //指向参数第一个结点
_Ty data;
while (srcPtr != nullptr) { //如果还未复制完
data = srcPtr->m_tData; //取出当前结点的数值
this->EnQueueRear(data); //将该数值从队尾加入
srcPtr = srcPtr->m_pLink; //指向参数队列指向下一项
}
return *this;
}
template<class _Ty>
CLinkedDeQue<_Ty>::~CLinkedDeQue() { //析构函数
this->MakeEmpty(); //直接调用置空函数
}
template<class _Ty>
void CLinkedDeQue<_Ty>::EnQueueHead(const _Ty data) { //从队头入队
if (m_pFront == nullptr) { //如果队列为空
m_pFront = m_pRear = new CLinkedNode<_Ty>(data);
if (m_pFront == nullptr) { //内存分配错误
cerr << "内存分配错误!" << endl;
exit(-1);
}
}
else { //队列不为空
CLinkedNode<_Ty>* pfront = this->GetHead(); //指向当前的头指针
m_pFront = m_pFront->InsertLast(data); //在队头新建一个结点
m_pFront->m_pNext = pfront; //新的头结点的m_pNext指向原头结点
}
}
template<class _Ty>
void CLinkedDeQue<_Ty>::EnQueueRear(const _Ty data) { //从队尾入队
if (m_pFront == nullptr) { //如果队列为空
m_pFront = m_pRear = new CLinkedNode<_Ty>(data);
if (m_pFront == nullptr) { //内存分配错误
cerr << "内存分配错误!" << endl;
exit(-1);
}
}
else { //队列不为空
CLinkedNode<_Ty>* prear = this->GetRear(); //保存增加结点之前的尾指针
m_pRear = m_pRear->InsertNext(data); //增加结点
m_pRear->m_pLast = prear; //尾结点的上一个元素指向未增加结点之前的元素
}
}
template<class _Ty>
void CLinkedDeQue<_Ty>::EnQueue(const _Ty data) { //进队-默认在队尾入队
EnQueueRear(data); //直接调用队尾入队函数
}
template<class _Ty>
bool CLinkedDeQue<_Ty>::DeQueueHead(_Ty& data) { //从队头出队
if (m_pFront == nullptr) //如果队列为空,直接返回假
return false;
CLinkedNode<_Ty>* pfront = m_pFront; //定义一个临时变量指向头结点,用于释放空间
data = pfront->m_tData; //将头结点的值赋值给参数
m_pFront = m_pFront->m_pNext; //指向头结点的下一结点
m_pFront->m_pLast = nullptr; //删除头结点之后将现在的头结点的m_pLast指向空
delete pfront; //释放原头结点的空间
return true;
}
template<class _Ty>
bool CLinkedDeQue<_Ty>::DeQueueRear(_Ty& data) { //从队尾出队
if (m_pRear == nullptr) //如果队列为空,直接返回假
return false;
CLinkedNode<_Ty>* prear = m_pRear; //定义一个临时变量指向头结点,用于释放空间
data = prear->m_tData; //将头结点的值赋值给参数
m_pRear = m_pRear->m_pLast; //指向尾结点的上一个结点
m_pRear->m_pNext = nullptr; //将当前尾结点的m_pNext指向空域
delete prear; //释放原尾结点的空间
return true;
}
template<class _Ty>
bool CLinkedDeQue<_Ty>::DeQueue(_Ty& data) { //出队-默认在队头出队
DeQueueHead(data); //直接调用从队头出队函数
}
template<class _Ty>
bool CLinkedDeQue<_Ty>::GetFrontData(_Ty& data) { //获取队头值
if (IsEmpty())
return false;
data = m_pFront->m_tData;
return true;
}
template<class _Ty>
bool CLinkedDeQue<_Ty>::GetRearData(_Ty& data) { //获取队尾值
if (IsEmpty())
return false;
data = m_pRear->m_tData;
return true;
}
template<class _Ty>
void CLinkedDeQue<_Ty>::MakeEmpty() { //置空函数
CLinkedNode<_Ty>* pdel = nullptr; //指向删除结点
while (m_pFront != nullptr) { //循环删除结点
pdel = m_pFront;
m_pFront = m_pFront->m_pNext;
delete pdel;
}
m_pRear = nullptr; //为安全起见,将m_pRear指向空
}
template<class _Ty>
bool CLinkedDeQue<_Ty>::IsEmpty() { //判空函数
return m_pFront == nullptr;
}
template<class _Ty>
int CLinkedDeQue<_Ty>::GetSize() { //获取队列大小
CLinkedNode<_Ty>* pelement = m_pFront; //临时指针,指向队列元素
int count = 0; //用于计数的临时变量,初始化为0
while (pelement != nullptr) { //当所指向的元素不为空时,说明没有到队尾指针
++count; //计数加一
pelement = pelement->m_pLink; //指向下一元素
}
return count;
}
#endif
main.cpp文件(测试文件)
#include"CLinkedDeQue.h"
int main() {
CLinkedDeQue <int> testDeQue;
cout << "输入testDeQue:" << endl;
cin >> testDeQue;
cout << "输出testDeQue:" << endl;
cout << testDeQue;
int a, b;
if (testDeQue.GetFrontData(a) && testDeQue.GetRearData(b)) {
cout << "当前头部的元素为:" << a << ",尾部的元素为:" << b << endl;
}
testDeQue.EnQueueHead(1);
testDeQue.EnQueueRear(3);
cout << "在头部插入1, 尾部插入3之后:" << endl;
cout << testDeQue;
if (testDeQue.DeQueueHead(a) && testDeQue.DeQueueRear(b)) {
cout << "在头部删除" << a << "尾部删除" << b <<"之后:"<< endl;
cout << testDeQue;
}
return 0;
}