假期之后,数字逻辑课的东西太多了,于是我采用了牺牲数据结构的数字逻辑保护法高强度复习数字逻辑。结果就是现在有点C++生疏了。。今天刚点开Xcode剧烈不适应。
为什么这是第八篇呢?因为第七篇我写的是有关栈的应用,然而因为以上保护法,我一直搁置没有写完,之后会尽快补上的。
今天的课的内容主要是队列和队列的应用。关于队列,有一点可以多讨论一下的就是它的存储方式。我们设置rear指向队尾的元素,front指向队头的元素。(rear和front可以是指针,可以是数组下标,取决于你的ADT形式)
由于队列是FIFO,就意味着直线式的储存会面临着假溢出的现象(出队的时候前面有空位置但是数据无法存进来)。为了处理假溢出现象,采用了首尾相连的环形储存结构,这样rear可以跨越最后一个空间,回到队头实用储存空间。这里的实现要用到整除的知识,就是当rear超出maxsize的时候,用整除可以‘归零’。然而这样又会面临着无法判别队列为空还是满。(满和空都是rear和front指向同一个空间)。
为了解决无法判别队列空满的现象,有两种方法:
1)在入队、出队时记录队中元素数量;
2)给环形结构多一个空间用来区分。
方法一简单但是耗内存,方法二在实现上稍微复杂一点,但时间杂度和储存空间都没有变多。
我们可以着重讨论一下方法二。在这种情况下,我们的队列一共有n+1个空位。初始化就让rear指向0,front指向1,之后每入队一个元素,就让rear+1。 当然,这里不要忘记做整除,否则就不是环形结构了!那么满队是什么情况呢?满队的时候只能存n个元素,所以front 和 rear 应当满足 (rear + 2)%maxsize = front。
以下是实现的代码。
#include <iostream>
using namespace std;
template <typename E> class Aqueue{
private:
int maxsize;
int front;
int rear;
E *listarray;
public:
Aqueue(int size = 10){
maxsize = size + 1; //把队列的容量增加一位,用来判断是否满
rear = 0; front = 1;
listarray = new E[maxsize];
}
~Aqueue(){
delete []listarray;
}
void clear(){
rear = 0;
front = 1;
}
void enqueue(const E&it){
if((rear+2)%maxsize == front) return; //满队
rear = (rear+1)%maxsize;
listarray[rear] = it;
}
void dequeue(){
if((rear+1) % maxsize == front) return; //空队
E it = listarray[front];
front = (front + 1) % maxsize;
}
const E &top(){
// if((rear+1) % maxsize == front) return -1;
return listarray[front];
}
virtual int length(){
return (rear + maxsize + 1 - front) % maxsize;
}
};
int main() {
Aqueue<int> myqueue;
myqueue.enqueue(1);myqueue.enqueue(2);myqueue.enqueue(3);myqueue.enqueue(4);
cout<<myqueue.top();
}
有关队列的应用,是一些关于数组储存的压缩方式,我之后会再写一篇整理出来。
reference: 数据结构与算法分析 [美]Clifford A. Shaffer
我校某老师ppt