利用C++搭建的循环顺序队列

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_43165699/article/details/97394510

利用C++搭建的循环顺序队列

在操作系统中的作业调度中有一个比较典型的调度策略,就是先来先服务的策略。当多个作业请求需要进行系统执行调用时,先提出服务请求的作业会被率先执行,后提出服务请求的会按照提出请求的顺序“依次排队”,等候后续的执行。其实这一排队策略就可以借助队列来予以实现。

1.队列的简要概述

队列一种限定存取位置的线性表,操作方式为:在表的一段输入,在表的另一端删除与取出。允许插入的一段叫做队尾(rear),允许删除和取出的一端叫做队头(frout)。具体的操作形式,如下图所示:

图1

这个操作是不是让大家想到了去火车站买票的操作。队列最大的特征就是:先进先出FIFO(First In First Out)。
队列的存储方式有两种:一种是基于数组的存储方式,即顺序队列;另一种是基于链表的存储方式。本文是利用C++搭建的顺序队列。

2.搭建思路

2.1队列基本的操作—插入与删除/读取

队列的插入与删除代表了队列的基本内容,也是队列的核心内容。队列的插入与删除/读取的操作如下图示:

图2

从图中可以看出:

1.) 队列刚建立时,首先需要进行初始化,令front=rear=0。当加入一个新元素,将元素添加到rear指向的位置,并让rear加1上移,即指向下一元素应当指向的位置。当删除/读取队内某一元素时,将front指向的位置上移即可。
2. )如果front==rear,则表示该队列为空,如上图所示的空队以及C出队(空队)所示。
3. )从上图所示D入队的rear=Maxsize时,表示队列“已满”,如果再加入新元素就会产生“溢出”。但是我们从图上可以看出,在队列前端还有一定的存储空间。,那我们如何让前端的空间合理的利用起来呢?问题的解答其实就是如何将数组的前端与后端连接起来,形成一个完整的环呢?前人很机智的想到了除法取余运算:
队头指针进1:front=(front+1)%Maxsize;
队尾指针进1:rear=(rear+1)%Maxsize;
取余运算可以当进行元素的插入与删除/读取操作时,当指针加至Maxsize-1时,利用%运算可以直接前进到数组的0号位置,对队内的存储空间充分利用。

2.2队列基本操作的讨论

借助2.1的基本操作,我们可以构建出一个循环队列,那在进行基本操作过程中,还需要什么值得注意的呢?

1.)循环队列的删除/读取元素速度大于存入的速度,队头指针(front)快速追上队尾指针(rear),即front=rear时,该队列为空队列。
2.)循环队列的存入速度大于删除/读取元素的速度,队尾指针(rear)很快会追上队头指针(front),也会出现front=rear,但这样就会出现与空队列一样的判断条件,这样就造成了队空条件与队满条件的混淆。为了区分这个判断条件,我们这里有2个办法:

方法1:判断条件变为:(rear+1)%Maxsize==front。也就是,让rear指到front的前一位置就认为队已满。也因此在该判断条件下,队满情形实际空出了一个元素位置,也就是在循环队列中最多存放Maxsize-1个元素。(本文所提供的代码就是采用的是该判断方法)
方法2:附加一个标志位FLAG,该标志位记录该队列最近一次操作类型,如果最近执行的进队操作,即插入操作时,FLAG=1。当执行的是出队操作,即删除/读取操作时,FLAG=0。当出现front=rear时,判断FLAG的值,即可判断队列已满还是队列为空。(注:使用加标志位的方法时,当队列使用十分频繁,无疑会增加程序运行时间,故该方式谨慎使用。)

3.代码

下列代码就是根据上述思路所搭建的,供大家参考。

#include<iostream>

using namespace std;
/************************队列结构定义***************************/
template<typename Datatype> class Queue
{
public:
	Queue(int size)
	{
		Maxsize = size;   //初始化最大容量
		//初始化队首、队尾、和元素数位0
		Frout = 0;       
		Rear = 0;
		count = 0;
		Elements = new Datatype[size];      //分配空间
		//如果空间分配失败,则进行退出
		if (Elements==NULL)
		{
			cout << "空间分配失败"<< endl;
			exit(1);
		}
	}
	~Queue()
	{
		delete [] Elements;
	}

	//入队操作
	bool insert(Datatype data);
	//出队操作
	Datatype delElement();
private:
	int count;             //队列的个数
	int Maxsize;           //队列的最大元素
	int Frout;             //队首
	int Rear;              //队尾
	Datatype *Elements;    //数据指针
};
/**************************入队操作*************************/
template<typename Datatype>
bool Queue<Datatype>::insert(Datatype data)
{
	if (((Rear+1)%Maxsize)==Frout)                     //判断是否队列已满
	{
		cout << "当前队列已满" << endl;
		return false;
	}
	Elements[Rear] = data;                           //将数据插入队尾
	Rear = (Rear + 1)%Maxsize;  
	count++;                                         //元素数+1
}
/**************************出队操作*************************/
template<typename Datatype>
Datatype Queue<Datatype>::delElement()
{
	if (Rear== Frout)                                 //判断当前是否为队空
	{
		cout << "当前队列为空队列" << endl;
		exit(1);
	}
	Datatype Data = Elements[Frout];                   //去除队首元素
	Frout = (Frout + 1)%Maxsize;                       //设置新的队首位置,为节省空间,采用取模法
	count--;                                           //队内元素减1
	return Data;
}
/**************************主函数*************************/
int main()
{
	//输入构建队列的长度
	cout << "输入构建队列的长度" << endl;
	int Queue_Number;
	cin >> Queue_Number;
	Queue<int> queue(Queue_Number);                     //初始化循环队列
	for (int i = 0; i < (Queue_Number-1); i++)
	{
		queue.insert(i*10);
	}
	queue.insert(100);
	cout << "******************构建的队列依次取出为******************" << endl;
	for (int i = 0; i < (Queue_Number - 1); i++)
	{
		cout<<queue.delElement()<<"   ";
	}
	cout << ""<<endl;
	cout << "********************************************************" << endl;
	cout << queue.delElement() << "   ";
	return 0;
}

上述程序我已经运行过了,我认为没有什么问题。如果大家在参考的过程中,遇到什么问题,也希望大家相互交流。

参考文献:
1.数据结构——殷人昆。
2.妙趣横生的算法——胡浩。

猜你喜欢

转载自blog.csdn.net/weixin_43165699/article/details/97394510
今日推荐