数据结构链式队列C++实现

1.链式队列

链式队列是基于单链表的存储表示。所以在实现链式队列时使用了和链表一样的结点struct,结点的具体定义放在"Queue.h"的头文件中。链式队列有两个指针front,rear,front为队头指针,指向单链表的第一个结点,rear为队尾指针,指向单链表的最后一个结点,所以出队是删除第一个节点,入队是将新元素的结点插在单链表最后一个结点的后面。结构图如下:

 本文链式队列对应的单链表没有设计空的头节点,因为头节点也没太大用处。

注意,当队列只有一个元素时,front == rear,因为该元素既是第一个元素也是最后一个元素。

2.队列基类的头文件"Queue.h"

这部分代码和上一篇循环队列的文章的Queue.h头文件相同,具体如下:

#pragma once
const int maxSize = 50;  //顺序队列的最大元素个数

template <class T>
class Queue
{
public:
	Queue() {};
	~Queue() {};
	virtual bool EnQueue(const T& x) = 0; //新元素入队
	virtual bool DeQueue(T& x) = 0;       //队头元素出队
	virtual bool getFront(T& x) = 0;      //获取队头元素
	virtual bool IsEmpty() const = 0;     //判断队列是否为空
	virtual bool IsFull() const = 0;      //判断队列是否满。顺序队列需要,链式队列不需要
	virtual int getSize() const = 0;      //求队列元素的个数
};

//用struct定义节点,链式队才用的到
template <class T>
struct LinkNode {
	T data; //数据域
	LinkNode<T> * link; //指针域,指向下一个节点
	LinkNode()          //仅初始化指针的构造函数
	{
		LinkNode<T> *ptr = nullptr;
		link = ptr;
	}
	LinkNode(const T& item, LinkNode<T> *ptr = nullptr) //初始化数据和指针成员的构造函数
	{
		data = item;
		link = ptr;
	}
};

3.链式队列头文件“LinkedQueue.h”

该头文件定义和实现了链式队列的类模板及其相关接口的实现,代码如下:

#include <iostream>
#include "Queue.h"
using namespace std;

template <class T>
class LinkedQueue :public Queue<T>
{
public:
	LinkedQueue() :front(nullptr), rear(nullptr) {}   //构造函数
	~LinkedQueue() { makeEmpty(); }                   //析构函数
	void makeEmpty();                                 //清空队列
	bool EnQueue(const T& x);						  //新元素x入队
	bool DeQueue(T& x);                               //队首元素出队并由x接收
	bool IsEmpty() const { return (front == nullptr) ? true : false; }//队列是否为空
	bool getFront(T& x);							  //查看队首元素的值并由x接收
	int getSize() const;                              //求队列元素的个数,这里的const修饰this指针,即该函数运行过程中不允许对队列进行更改
	
	//注意父类中纯虚函数IsFull(),该函数一定要重写,避免LinkedQueue称为虚类而无法实例化对象
	bool IsFull() const { return false; }             //链式队列内存是动态的,所以没有“队满”的概念,因此该函数用不到,直接返回false


	//重载左移位运算符输出队列中的元素,同理为了避免模板声明发生混淆错误,这里用template <class R>来区分LinkedQueue类模板的template <class T>
	template <class R>
	friend ostream & operator<< (ostream &out, LinkedQueue<R> &lq);  //全局函数做友元

private:
	LinkNode<T> *front, *rear;                        //front指向对头节点的指针,rear指向队尾结点的指针
};

template <class T>
void LinkedQueue<T>::makeEmpty()
{
	LinkNode<T> *p;
	while (front != nullptr)             //逐个删除队列中的结点
	{
		p = front;						 //记录front
		front = front->link;			 //front指向当前被删结点的下一个结点
		delete p;						 //释放当前节点的内存
	}
}


template <class T>
bool LinkedQueue<T>::EnQueue(const T& x)
{//入队的新元素放在队尾

	if (front == nullptr)				  //如果原队列为空
	{
		front = rear = new LinkNode<T>(x);//只有一个元素时,front和rear均指向该结点,因为该节点既是队头又是队尾
		if (front == nullptr)
			return false;				  //内存分配失败
	}
	else                                  //如果原队列不为空
	{
		//先建立存放新元素的结点,并由队列最后一个节点的link指针指向该节点
		rear->link = new LinkNode<T>(x);
		//检测内存是否分配成功
		if (rear->link == nullptr)
			return false;				  //内存分配失败
		rear = rear->link;                //更新rear使其指向队尾结点
		return true;
	}
}


template <class T>
bool LinkedQueue<T>::DeQueue(T& x)
{//如果队列不为空,将队首结点从链式队列中删除,函数返回true,否则返回false
	if (IsEmpty())
		return false;
	LinkNode<T> *p = front;              //记录front指针
	x = front->data;					 //x接收元素数据
	front = front->link;			     //更新rear
	delete p;							 //清理队首结点的内存
	return true;
}


template <class T>
bool LinkedQueue<T>::getFront(T& x)
{//若队列不为空,返回队后元素的值及true,否则返回false
	if (IsEmpty())
		return false;
	x = front->data;                     //x接收队首元素的值
	return true;
}


template <class T>
int LinkedQueue<T>::getSize() const
{//求队列元素的个数
	LinkNode<T> *p = front; int num = 0;
	while (p != nullptr) 
	{
		p = p->link;                    //遍历每一个结点
		num++;							//元素个数加1
	}
	return num;
}


template <class R>
ostream & operator<<(ostream &out, LinkedQueue<R> &lq)
{
	out << "链式队列中元素的个数为:" << lq.getSize() << endl;
	LinkNode<R> *p = lq.front; int i = 0;
	while (p != nullptr)
	{
		out << i << " : " << p->data << endl;
		i++;
		p = p->link;                   //准备输出下一个元素
	}
	return out;                        //实现链式输出
}

4.代码测试

老规矩,制作简单测试,剩下的小伙伴自行测试,放在“链式队列.cpp”文件中,代码如下:

#include <iostream>
#include "LinkedQueue.h"
//LinkedQueue.h头文件已经有了using namespace std,所以这里就不用再写了
int main()
{
	LinkedQueue<int> LQ;
	for (int i = 0; i < 5; i++)
		LQ.EnQueue(i);            //入队
	cout << LQ;                   //输出队列元素

	int x;
	LQ.DeQueue(x);                //队首元素出队
	LQ.DeQueue(x);
	cout << LQ;					  //输出队列元素

	return 0;
}

测试结果如下:

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值