数据结构之循环队列 | 青训营笔记

135 阅读1分钟

循环队列的出现 队列是一种只能在表的一端进行插入运算,在表的另一端进行删除运算的线性表(头删尾插),它的存储方式分为 顺序队或链队,以循环队列更常见。这里仅介绍顺序队以及顺序队存在的假溢出缺陷,进而引出循环队列。

image.png

image.png 一方面:降低了出队时所耗费的时间复杂度,因为队列先进先出的原则,导致在dequeue(出栈操作)时,必须删除队首的元素,后面所有的元素都要往前移动一位,导致时间复杂度为O(n* 。如果弄成循环队列,引入front(队首)、tail(队尾)指针,则出队时,后面所有的元素不用动,只要front+1,时间复杂度为O(1); 另一方面:节约了空间,因为当队前面的元素删除时,tail指向队尾后,还可以再从第一个元素循环。
补充:队列为空时,front = tail
队列满时,(tail+1)% length = front 解释: 因为tail+1 <= length,当tail+1 =length时,说明tail在队尾,余数为0,front为0,队列已满;当tail+1<length时,余数为tail + 1,则tail+1+front = length,队也已满。 注意:循环队列满的时候,tail指向的位置是空的,说明length-1才是实际元素的个数,会有一个空位没有元素

循环队列代码:

`#include using namespace std;

#define MAXSIZE 5 //最大队列长度

template class RQueue { public: RQueue() :_base(NULL) ,_front(0) ,_rear(0) { _base = (T*) malloc (MAXSIZE*sizeof(T)); if(!_base) { cout<<"开辟空间失败"<<endl; } }

//返回队列元素个数
int Length()
{
	return (_rear-_front+MAXSIZE)%MAXSIZE;
}

//插入元素
bool Insert(const T& x)
{
	if((_rear+1)%MAXSIZE == _front)//队列满
	{
		cout<<"队列已满!"<<endl;
		return false;
	}

	_base[_rear] = x;
	_rear = (_rear+1)%MAXSIZE;
	return true;
}

//删除元素
bool Delete()
{
	if(_front == _rear)
	{
		cout<<"队列为空!"<<endl;
		return false;
	}
	_front = (_front+1)%MAXSIZE;
	return true;
}

private: T* _base; //初始化的动态分配存储空间 int _front; //头指针,若队列不空,指向队列头元素 int _rear; //尾指针,若队列不空,指向队列尾元素的下一个位置 };`