源代码:
// 3_a3.cpp —— 循环队列结构的定义
/*
* -> 程序要求:
* 1. 完成对循环队列结构的定义,以及对循环队列的各种基本运算的实现(每种基本运算用一个函数来实现)。
* 2. 基本运算包括:初始化Init_sqqueue运算、判队空Empty_sqqueue运算、入队En_sqqueue运算、出队De_sqqueue运算、取队头元素Gethead_sqqueue运算。
* 3. 并且在main函数中分别调用以上各种基本运算的函数来使用,以验证其功能已实现。
* 4. 此题的源程序保存为 3_a3.cpp
*/
/*
* -> 程序分析
* 1. 写循环队列最需要解决的一个问题是:如何知道它是满是空?
* 2. 如课件所说:有三种方法
* 1)另设长度计数器n,此时多耗费了空间去保存变量,多耗费了一点计算时间。
* 2)另设标志位以区分队空、队满,多耗费了空间去保存变量。
* 3)入队前预测试,队满条件:front=(rear+1)%maxsize,此时少用一个存储单元,且front所指处总为空,此时多耗费了计算时间。
* 每种方法都有利弊,这里,我也跟很多书本与经典例题一样,采用第三种方法。
* 3. 写循环队列,因为它不断地进出,必然会使下标值不断改变,这里,进出都需各用一个变量,这样会比较方便。
* 4. 循环队列中,还是如上几题所说的那样,有那几种成员函数[构造,判断空满,进,取,出,销毁].
* 5. 元素进出如果将数据结构中的栈和队列相比,不同点是,一个是从头部出的,一个是从尾部出的,也就是说,栈是LIFO,队列是FIFO.
**/
#include <iostream>
#include <cstdlib>
using std::cin;
using std::cout;
using std::endl;
template <typename elem>
class cirqueue
{
private:
enum { defaultmaxsize = 10}; // 定义默认最大的队列size
int lastindex; // 现在的队列尾部
int headindex; // 现在的队列头
int maxsize; // 队列的实际最大size
elem *arr; // 现存数据
public:
// 构造,析构函数
cirqueue(int mz = defaultmaxsize):maxsize(mz), lastindex(0), headindex(0){arr = new elem[maxsize];}
~cirqueue() { delete [] arr; maxsize = lastindex = headindex = 0;}
// 判空,判满
bool isempty();
bool isfull();
// 入队,取队,出队
void enqueue(const elem &enelem);
void gethead(elem & gelem);
void dequeue();
};
// 判空,判满
template <typename elem>
bool cirqueue<elem>::isempty()
{
if ( lastindex == headindex )
return true;
else
return false;
}
template <typename elem>
bool cirqueue<elem>::isfull()
{
if ( headindex == (lastindex + 1) % maxsize)
return true;
else
return false;
}
// 入队
template <typename elem>
void cirqueue<elem>::enqueue(const elem &enelem)
{
if(isfull())
{
cout << "队列已满,插入失败。";
return;
}
// 先将元素放入队列,再将队列尾下标自增。
// 这里可以自行安排,只是这里的安排会与删除,提取元素这些函数相关。
arr[lastindex] = enelem;
lastindex = (lastindex + 1) % maxsize;
return;
}
// 取队
template <typename elem>
void cirqueue<elem>::gethead(elem & gelem)
{
if ( isempty())
{
cout << "队列为空,不能从队列中取出顶部元素.";
return;
}
gelem = arr[(lastindex - 1) % maxsize];
return;
}
// 出队
template <typename elem>
void cirqueue<elem>::dequeue()
{
if (isempty())
{
cout << "队列为空,不能从队列中出队。";
return;
}
headindex = (headindex + 1) % maxsize;
return;
}
int main()
{
// 开始测试循环队列
cout << "\n ----------------------- 现在开始对循环队列程序进行测试 -----------------------\n\n";
cirqueue<int> test;
cout << "\n\n -> 入队测试开始(使用循环语句向栈中插入11个元素)\n\n"; // 栈中一共只有10个元素,测试最后一次是否会提取失败
for (int i = 0; i != 11; ++i)
{
cout << "第 " << i + 1 << "次插入";
test.enqueue(i);
cout << " 操作完成。\n";
}
int temp;
cout << "\n\n -> 获取栈顶元素测试\n\n";
test.gethead(temp);
cout << " 获得的栈顶元素是:" << temp << endl;
cout << "\n\n -> 出栈测试开始(使用循环语句向栈中提取11个元素)\n\n"; // 栈中一共只有10个元素,测试最后一次是否会提取失败
for (int i = 0; i != 11; ++i)
{
cout << "第 " << i + 1 << "次: ";
test.dequeue();
cout << " 操作完成。\n";
}
cout << endl;
system("pause");
return 0;
}
结果:
----------------------- 现在开始对循环队列程序进行测试 -----------------------
-> 入队测试开始(使用循环语句向栈中插入11个元素)
第 1次插入 操作完成。
第 2次插入 操作完成。
第 3次插入 操作完成。
第 4次插入 操作完成。
第 5次插入 操作完成。
第 6次插入 操作完成。
第 7次插入 操作完成。
第 8次插入 操作完成。
第 9次插入 操作完成。
第 10次插入队列已满,插入失败。 操作完成。
第 11次插入队列已满,插入失败。 操作完成。
-> 获取栈顶元素测试
获得的栈顶元素是:8
-> 出栈测试开始(使用循环语句向栈中提取11个元素)
第 1次: 操作完成。
第 2次: 操作完成。
第 3次: 操作完成。
第 4次: 操作完成。
第 5次: 操作完成。
第 6次: 操作完成。
第 7次: 操作完成。
第 8次: 操作完成。
第 9次: 操作完成。
第 10次: 队列为空,不能从队列中出队。 操作完成。
第 11次: 队列为空,不能从队列中出队。 操作完成。
请按任意键继续. . .