循环队列详解

概述

1.先进先出的线性序列,称为队列,队列也是一种线性表,只不过它是操作受限的线性表,只能在两端操作。一端进,一端出。进的一端称为队尾,出的一端称为队头,队列可以用顺序存储也可以用链式存储。

2.队列的顺序存储形式,可以用一段连续的空间存储数据元素,用两个整型变量记录队头和队尾元素的下标。

3初始化

(1)

base为数组的基地址,front,base分别代表指向队头和队尾的"指针"(数组下标),构造空队列只需要申请一块内存给基地址,并且将队头指针与队尾指针赋值为0.

(2)

因为该队列为循环队列所以

typedef struct SqQueue
{
	int* base;
	int front, rear;
}SqQueue;

//构造空队列
bool InitQueue(SqQueue& Q)
{
	Q.base = new int[Maxsize];
	if (Q.base == NULL)
	{
		return false;
	}
	Q.front = Q.rear = 0;
	return true;
}

 4入队

 (1)将队尾指向的位置赋值,并且赋值后将队尾的位置后移

 (2)在入队时难免会出现以下情况

 队列的空间未利用完,但是却造成了元素的溢出(又称"假溢出"),所以要利用循环队列,这样就不会有这样的顾虑

 入队的操作为

Q.base[Q.rear]=e;  将元素e放入Q.rear指向的空间

Q.rear=(Q.rear+1)%Maxsize rear指针向后移动一个单位

至于为什么要加对(Q.rear+1)取模,这是因为rear指针会一直增加到比队列容量大的数字,对其取模就是为了使其缩小,指向真正的位置例如 容量大小为5 队尾指向9 取模队尾指向的是4,说明队尾指正已经走过了一个圈

tips:在入队前要判断队列是否为空怎们办

如图此时队尾指向的是循环队列的最后一个空间,这个空间并没有存放任何数据,判断队列是否为满只要将队尾指针+1看看其是否与队头相等,此处为什么要取模?

例如队列空间大小为10,队尾指向第10个空间,下标为9,对其加1等于10,取模等于0,此时队头也是指向0的所以需要取模

有例如如果一开始队头指向的是1,队尾指向的是0,那么队尾加1,取模后为1,那么此时对也满

//入队
bool Push(SqQueue& Q, int e)
{
	if ((Q.rear + 1) % Maxsize == Q.front)
	{
		cout << "队满" << endl;
		return false;
	}

	Q.base[Q.rear] = e;
	Q.rear = (Q.rear + 1) % Maxsize;
	return true;
}

5出队

出队前判断队列是否为空

当尾指针与头指针指向一起时队空,注意与队满的区别

出队的操作

e=Q.base[Q.front];

Q.front=[Q.front+1]%Maxsize;

将头指针向着元素增长方向移动一个单元,原来的头指针指向的元素并没有真正的删除,只是逻辑上的删除,后序如果要用到这个空间,会用新的元素将其覆盖掉

至于为什么要用取模和上述的入队是一致的

bool Pop(SqQueue& Q, int& e)
{
	if (Q.rear == Q.front)
	{
		cout << "队空" << endl;
		return false;
	}
	e = Q.base[Q.front];
	Q.front = (Q.front + 1) % Maxsize;
    return true;
}

6.获取队头元素

判断队列是否为空

简单的数组取元素而已

int Get_front(SqQueue Q)
{
	if (Q.rear == Q.front)
	{
		cout << "队空" << endl;
		return -1;
	}

	return Q.base[Q.front];
}

7.获取队尾元素

判断队列是否为空

因为队尾一直指向最后一个元素的后一个位置,所以要去指正前面的空间,就是队尾元素

int Get_back(SqQueue Q)
{
	if (Q.front == Q.rear)
	{
		cout << "队空" << endl;
		return -1;
	}

	return Q.base[Q.rear - 1];
}

8.获取队列元素个数

这两段的代码意思是一样的

因为队尾减队头可能会出现负数,所以需要加上容量大小后取模,这样才会得到真实的容量大小

例如队列大小6,队尾指向1,队头指向2,那么元素个数为(1-2+6)%6=5个

例如队列大小6,队尾指向5,队头指向0,那么元素个数为(5-0+6)%6=5个

int length(SqQueue Q)
{
	return (Q.rear - Q.front + MaxSize) % MaxSize;

	/*if (Q.rear - Q.front >= 0)
	{
		return Q.rear - Q.front;
	}
	else
	{
		return (Q.rear - Q.front + MaxSize);
	}*/
}

完整代码如下

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
using namespace std;

const int MaxSize = 100;

typedef struct SqQueue
{
	int* base;
	int front, rear;
}SqQueue;

bool InitQueue(SqQueue& Q)
{
	Q.base = new int[MaxSize];
	if (Q.base == NULL)
	{
		return false;
	}
	Q.front = Q.rear = 0;
	return true;
}

bool Push(SqQueue& Q, int e)
{
	if ((Q.rear + 1) % MaxSize == Q.front)
	{
		return false;
	}

	Q.base[Q.rear] = e;
	Q.rear = (Q.rear + 1) % MaxSize;
	return true;

}

bool Pop(SqQueue& Q, int& e)
{
	if (Q.rear == Q.front)
	{
		return false;
	}
	e = Q.base[Q.front];
	Q.front = (Q.front + 1) % MaxSize;
}

int Get_front(SqQueue Q)
{
	if (Q.front == Q.rear)
	{
		return -1;
	}

	return Q.base[Q.front];
}

int Get_back(SqQueue Q)
{
	if (Q.front == Q.rear)
	{
		return -1;
	}

	return Q.base[Q.rear - 1];
}

int length(SqQueue Q)
{
	return (Q.rear - Q.front + MaxSize) % MaxSize;

	/*if (Q.rear - Q.front >= 0)
	{
		return Q.rear - Q.front;
	}
	else
	{
		return (Q.rear - Q.front + MaxSize);
	}*/
}

int main()
{

	SqQueue S;
	InitQueue(S);

	int n = 0;
	cout << "请输入有多少元素" << endl;
	cin >> n;
	cout << "依次输入元素" << endl;
	while (n--)
	{
		int e;
		cin >> e;
		Push(S, e);
	}
	int L = length(S);
	for (int i = 0; i < L; i++)
	{
		cout << "队尾:"<<Get_back(S) << " "<<"队头:"<<Get_front(S)<<"---";

		int e = 0;
		Pop(S, e);
		cout << e <<" ";
		cout << endl;
	}
	//cout << length(S);
	cout << endl;




	system("pause");
	return EXIT_SUCCESS;
}

评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值