循环队列 ~ 程序实现二
本篇博客的内容为利用 C++
中的 类 对数据结构中的 循环队列 进行代码实现!
其中涉及了循环队列的 增(入队)删(出队)查(队头与队尾元素)改(没写(~ ̄▽ ̄)~),判空,判满,打印等操作!并附带了实例以及对应的运行结果!
注意1:在下述程序中尝试了 两种情况:
- 当队列满时,无法继续入队操作;
- 当队列满时,可以继续入队操作,但会覆盖队列满时的队头元素,从而队头指针(
_front
)会依次后移。
注意2:下面程序中设定循环队列的元素数是5(有效元素个数),但对应于 温故而知新 -> 数据结构 -> 线性表 ->队列 中所说的循环队列,其总的个数为6,只不过1个为空,即可根据 rear + 1 == front
来区别队列是否为满!
具体内容如下
(1)CQueue.h
#pragma once;
#include<iostream>
using namespace std;
#include<assert.h>
typedef int CQDataType;
class CircularQueue
{
public:
CircularQueue(int capa)
{
_data = (CQDataType*)malloc(sizeof(CQDataType)*capa);
_capa = capa;
_front = _rear = 0;
_size = 0;
}
~CircularQueue()
{
if (_data != NULL)
{
free(_data);
}
}
/* 判空操作 */
bool CQueueEmpty();
/* 判满操作 */
bool CQueueFull();
/* 入队操作 */
void CQueuePush(CQDataType val);
/* 出队操作 */
void CQueuePop();
/* 获得队头元素 */
CQDataType CQueueFront();
/* 获得队尾元素 */
CQDataType CQueueRear();
/* 打印操作 */
void CQueuePrint();
/* 销毁操作 */
void CQueueDestory();
private:
//队头元素的位置
int _front;
//队尾元素的下一位置
int _rear;
//所存元素个数 最后一个元素的位置是k
int _capa;//元素计数时,是从0开始的
//所存元素的首地址
int *_data;
//当前有效元素个数
int _size;
};
(2)main.cpp
#include"CQueue.h"
/*
整个程序我实验两种情况:
1、当队列满后,若没有进行出队操作,则不可再往里放数据
2、当队列满后,且没有出队操作,此时再做入队操作时,会覆盖原有数据,且_front按次序后移
*/
/* 判空操作 */
bool CircularQueue::CQueueEmpty()
{
return _size == 0;
}
/* 判满操作 */
bool CircularQueue::CQueueFull()
{
//return (_rear + 1) % (_capa + 1) == _front;
return _size == _capa; //正常情况下,即满队列不再入队数据
}
/* 入队操作 */
void CircularQueue::CQueuePush(CQDataType val)
{
/* 情况1 */
判断队列是否为满
//assert(!CircularQueue::CQueueFull());
队尾入队
//_data[_rear++] = val;
判断队尾是否越界,越界则重置 -- 如此会满足当队列满了后,新数据会覆盖原数据,且队头元素后移
//if (_rear >= _capa)//说明尾指针到了头指针的位置
// _rear = 0;
//_size++;// 一直入队操作,则_size很容易大于_capa,此时作取余操作可得具体到那个位置
/* 情况2 */
//判断队列是否为满
if (CircularQueue::CQueueFull())
_front++;//因为满队列后,再入队相当于覆盖了之前的数据,所以队头后移
_rear = _rear % _capa;
// 队尾入队
_data[_rear] = val;
_rear++;
_size = _size >= _capa ? _capa : _size + 1;// 一直入队操作,则_size很容易大于_capa,当满队后,_size就不再发生变化
}
/* 出队操作 */
void CircularQueue::CQueuePop()
{
// 判断队列是否为空
assert(!CircularQueue::CQueueEmpty());
// 队头出队
_front++;
// 判断队头是否越界
if (_front >= _capa)
_front = 0;
_size--;
}
/* 获得队头元素 */
CQDataType CircularQueue::CQueueFront()
{
assert(!CircularQueue::CQueueEmpty());
return _data[_front];
}
/* 获得队尾元素 */
CQDataType CircularQueue::CQueueRear()
{
assert(!CircularQueue::CQueueEmpty());
if (_rear != 0)
return _data[_rear - 1];//元素个数从0开始
else
return _data[_capa - 1];//_rear=0 即队尾在数组的末尾
}
/* 打印操作 */
void CircularQueue::CQueuePrint()
{
/* 情况1 */
/*assert(!CircularQueue::CQueueEmpty());
int begin = _front;
int end = _rear == 0 ? _rear + _capa : _rear;
cout << "队列内容:";
while (begin < end)
{
cout << _data[begin] << " ";
begin++;
}cout << endl;*/
/* 情况2 */
assert(!CircularQueue::CQueueEmpty());
int begin = _front;
//int end = _rear <= _front ? _capa : _rear;
int end = _rear%_capa <= _front ? _capa : _rear%_capa;
cout << "队列内容:";
while (begin < end)
{
cout << _data[begin] << " ";
begin++;
}
if (_rear%_capa <= _front)
{
begin = 0;
end = _rear%_capa;
while (begin < end)
{
cout << _data[begin] << " ";
begin++;
}
}
cout << endl;
}
/* 销毁操作 */
void CircularQueue::CQueueDestory()
{
free(_data);
cout << "已销毁" << endl;
}
void test()
{
/* 情况1 */
//CircularQueue cq(5);//有效数据个数为5
///* 验证未超过有效数据个数 即 _rear <= _capa*/
//cq.CQueuePush(1);
//cq.CQueuePush(2);
//cq.CQueuePush(3);
//cq.CQueuePush(4);
//cq.CQueuePrint();// 1 2 3 4
//cout << endl;
///* 验证 _rear > _capa */
//cq.CQueuePush(5);
//cq.CQueuePrint();// 1 2 3 4 5
cq.CQueuePush(6);// 到此处会警告,因为队列满了,注释掉 push 中的判满操作可解决,如此满队后队列一开始的数据会刷新
cq.CQueuePrint();
//cout << endl;
///* 验证出队 */
//cq.CQueuePop();
//cq.CQueuePrint();// 2 3 4 5
//cq.CQueuePop();
//cq.CQueuePrint();// 3 4 5
//cq.CQueuePop();
//cq.CQueuePrint();// 4 5
cq.CQueuePop();
cq.CQueuePrint();// 5
cq.CQueuePop();
cq.CQueuePrint();// 到此处依然会警告,因为队列已空
//cout << endl;
///* 验证队头、队尾 */
//cout << "此时队头元素:" << cq.CQueueFront() << endl; //4
//cout << "此时队尾元素:" << cq.CQueueRear() << endl << endl;//5
cq.CQueueDestory();//这句省略,因为析构函数中会重新释放,若还有这句,会报错
/* 情况2 */
CircularQueue cq(5);//有效数据个数为5
/* 验证未超过有效数据个数 即 _rear <= _capa*/
cq.CQueuePush(1);
cq.CQueuePush(2);
cq.CQueuePush(3);
cq.CQueuePush(4);
cq.CQueuePrint();// 1 2 3 4
cout << endl;
/* 验证 _rear > _capa */
cq.CQueuePush(5);
cq.CQueuePrint();// 1 2 3 4 5
cq.CQueuePush(6);
cq.CQueuePrint();// 2 3 4 5 6
cq.CQueuePush(7);
cq.CQueuePrint();// 3 4 5 6 7
cout << endl;
/* 验证出队 */
cq.CQueuePop();
cq.CQueuePrint();// 4 5 6 7
cq.CQueuePop();
cq.CQueuePrint();// 5 6 7
cq.CQueuePop();
cq.CQueuePrint();// 6 7
//cq.CQueuePop();
//cq.CQueuePrint();// 7
//cq.CQueuePop();
//cq.CQueuePrint();// 到此处依然会警告,因为队列已空
cout << endl;
/* 验证队头、队尾 */
cout << "此时队头元素:" << cq.CQueueFront() << endl; //6
cout << "此时队尾元素:" << cq.CQueueRear() << endl << endl;//7
}
int main()
{
test();
system("pause");
return 0;
}
(3)运行结果
-
情况1
-
情况2