数据结构之链式双端队列(CLinkedDeQue)源代码

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;
}

测试结果

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值