【数据结构】C++实现之队列结构

1. 概念

队列本质上是特殊的线性表,它是在一端(队头)进行删除操作,另一端(队尾)进行插入操作,遵守先进先出规则(FIFO)。既然队列也是线性表,当然也有两种数据存储方式:顺序存储结构,这种结构事先要基本确定队列的大小,不支持动态分配存储空间,所以插入和删除元素比较省时,但是会造成空间的浪费。 为了节省空间,后来学者提出了循环队列链式存储结构,可以不需要事先知道队列的大小,支持动态和释放空间,但是插入和删除操作比较耗时,也称链队列。其中有循环队列也可分为两种:顺序存储结构循环队列 、链式结构循环队列。【链表优势:空间无限理论上】

2. 顺序存储结构队列

2.1 抽象数据类型
在这里插入图片描述

/*
InitQueue(*Q);		//初始化一个空队列
DestroyQueue(*Q);	//队列存在,则销毁
ClearQueue(*Q);		//将队列清空
QueueEmpty(Q);		//队列为空,返回true or flase
GetHead(Q,*e);		//队列存在且非空,返回队列的头元素
InsertQueue(*Q,e);	//队列存在,插入元素e到Q中并成为队尾元素
DeleteQueue(*Q,*e);	//删除队列头元素,并以e返回
QueueLength(Q);		//返回队列的元素个数
*/
//队列的顺序存储结构与线性表顺序结构相同
struct QUEUE{
	ElemType data[MAXSIZE];  //数据域
	int length;   //长度
	};

2.2 初始化、插入以及删除操作
1)初始化就是开辟空间,清理内存以及更新长度
2)插入队列的插入只能是从尾端进行,时间复杂度为O(1)
3)删除操作时只能在队列头部进行,后面所有数据要向前移动,时间复杂度O(n)

//初始化队列
void Qq::InitQueue(QUEUE &q)
{
	q.length = 0;
	for (int i = MAXSIZE - 1; i >= 0; i--)
		q.data[i] = 0;
}

//插入数据队列
Qq::Status Qq::InsertQueue(QUEUE &q, ElemType e)
{
	if (q.length == MAXSIZE)
		return ERROR;
	q.data[q.length] = e;
	q.length++;
	return OK;
}

//删除数据队列
Qq::Status Qq::DeleteQueue(QUEUE &q, ElemType &e)
{
	if (q.length < 1)
		return ERROR;
	e = q.data[0];
	for (int i = 1; i <= q.length; i++)
		q.data[i - 1] = q.data[i];
	q.length--;
	return OK;
}

3. 链式存储结构队列

4. 顺序存储结构循环队列

4.1 抽象数据类型

	//队列的顺序存储结构与线性表顺序结构相同
struct RQUEUE{
	ElemType data[MAXSIZE]; //数据空间
	int front;  //头指针
	int rear;	//尾指针
	};

在这里插入图片描述
1) 这里就存在一个问题:怎么判断循环队列是满了的?
**方法1:**设置一个标志flage,当 front = rear时且flage=0,队列为空;当当 front = rear时且flage=1,队列为满。
**方法2:**当front = rear时为空,队列满时,我们修改其条件保留一个空间。也就是,队列满时队列还有一空闲空间。

4.2 初始化、插入以及删除操作
1)队列满时条件判断:(rear+1)%QueueSize==front,其中QueueSize指队列的最大尺寸
2)队列元素长度:(rear-front+QueueSize)%QueueSize

//初始化循环顺序结构队列
void RQq::InitQueue(RQUEUE &q)  
{
	q.front = 0;
	q.rear = 0;
}

//返回循环队列长度
int RQq::QueueLength(RQUEUE q)
{
	return (q.rear - q.front + MAXSIZE) % MAXSIZE;
}

//插入元素到循环队列rear
RQq::Status RQq::InsertQueue(RQUEUE &q, ElemType e)
{
	if ((q.rear + 1) % MAXSIZE == q.front)  //满队列
		return ERROR;
	q.data[q.rear] = e;             //插入到尾指针
	q.rear = (q.rear + 1) % MAXSIZE;  //更新尾指针位置
	return OK;
}

//删除循环队列元素front
RQq::Status RQq::DeleteQueue(RQUEUE &q, ElemType &e)
{
	if (q.rear  == q.front)  //队列为空
		return ERROR;
	e = q.data[q.rear];     //删除的数据
	q.front = (q.front + 1) % MAXSIZE;  //更新头指针
	return OK;
}

5. 链式存储结构循环队列

6.总结

在这里插入图片描述

发布了30 篇原创文章 · 获赞 6 · 访问量 5690

猜你喜欢

转载自blog.csdn.net/qq_32643313/article/details/105403103