队列(上)
队列的结构以及顺序表中队列(queue_s)的定义、初始化
队列和栈一样,也是一种特殊的线性表,和栈不同的是,栈只能在线性表的一端进行插入和删除操作,而常规的队列(因为还有双端队列这种情况)是在线性表的一端只能进行插入操作,另一端只能进行删除操作。
#define MaxSize 100
//队列结构体
struct queue_s {
int front, rear;
int data[MaxSize];
};
//队列初始化
queue_s *new_queue_s() {
queue_s *q = new queue_s;
q->front = 0;
q->rear = 0;
return q;
}
在这种队列中,我们可以使用front==rear==0作为判空条件,但是判断队列满条件不能是rear==MaxSize,因为随着数据元素的删除,front指针的值也在不断增加,最后删除完成所有的数据元素后,front==rear,但是rear指针的值仍然是MaxSize,也就是说rear指针的值并不会因为删除操作而减少。所以这种顺序队列是存在缺点的。
顺序表中定义循环队列(queue_r)
#define MaxSize 100
//循环队列结构体
struct queue_r {
int front, rear;
int data[MaxSize];
};
//循环队列初始化
queue_r *new_queue_r(){
queue_r *q = new queue_r;
q->front = 0;
q->rear = 0;
return q;
}
//判空
bool isEmpty(queue_r q) {
if (q.front == q.rear) return true;
return false;
}
//判满
bool isFull(queue_r q) {
if ((q.rear + 1) % MaxSize == q.front) return true;
return false;
}
这种队列弥补了传统顺序队列的缺点,它将队列看作为一个环状的结构(虽然本质上还是由一个顺序数组组成)。这样当front的值为MaxSize-1(即即将到达队列所容许的最大容量)时,再进一步就会将front的值变为0(front=(front+1)%MaxSize,取余操作)。这样,判断队列满的条件就变成了front==rear。不过,这也和队列空的判别条件产生了冲突,即当front==rear时,这个队列可能是空的,也可能是满的。
常见的纠正方法为牺牲一个存储单元,即数据元素入队时从下一个存储单元入队,这样判满条件就变成了(rear+1)%MaxSize==front,和判空条件作出了区分。
当然,还可以在队列的结构体中增加数据变量用来进行记录数据信息,比如增加某个变量用来代表当前队列元素个数,或者直接增加变量用来代表当前队列空还是队列满。