1、队列
队列是一种先进先出(FIFO)的线性表。只允许在队头删除元素,队尾插入元素。头删尾插。
表尾(An)是队尾,表头(A1)是队头。只能在队头队尾进行操作。常用循环顺序表。
生活中的排队问题都可以用队列
2、队列存储结构
队列的顺序结构→一维数组base[MAXQSIZE]
除了用一组地址连续的存储单元依次存放从队头到队尾的元素外,还需增加两个整型变量front和rear分别指示队头元素和队尾元素位置。(后称头指针和尾指针,不是链表的指针,仅代表元素位置。)
typedef struct {
QElemType *base;//初始化时动态分配存储空间
int front;//头指针
int rear;//尾指针
} SqQueue;
初始化创建空队列时,令front=rear=0,队尾插入新元素时,尾指针rear自增,队头删除元素时,头指针front自增。因此,在非空队列中,头指针始终指向队头元素,而尾指针始终指向队尾元素的下一个位置。
3、基本实现
空队列:rear==front
入队:base[rear]=x;rear++;
出队:x=base[front];front++;
当处于图(d)状态时不可插入新元素,否则会溢出。但实际上为空间未占满,为“假溢出”。为避免该情况,使用循环队列。
4、循环队列
将base[0]接在base[MAXQSIZE-1]后,使队列变成一个环状的空间。若rear+1==MAXQSIZE,则令rear=0。利用模运算(%)。
插入元素:Q.base[Q.rear]=x;
Q.rear=(Q.rear+1)% MAXQSIZE;
删除元素: x=Q.base[s.front]
Q.front=(Q.front+1)% MAXQSIZE
*对于循环队列,不能以头尾指针值来判断满队/空队
当队列空间大小为m时,有m-1个元素就认为是队满。这样判断队空的条件不变。尾指针在循环意义上+1后等于头指针,则为队满。
判断队空
bool QueueEmpty(SqQueue q)
{
if (q.front == q.rear)
return 1;
return 0;
}
5、初始化
Status InitQueue(SqQueue &q) //构造一个空队列Q
{
q.base = new QElemType[MAXQSIZE]; //为队列分配一个最大容量为MAXSIZE的数组空间,base指向数组空间首地址。
if(!q.base)
exit(OVERFLOW); //存储分配失败
q.front = q.rear = 0; //头指针和尾指针置为零,队列为空
return OK;
}
6、销毁队列
void DestroyQueue(SqQueue &q)
{
/* 销毁队列Q,Q不再存在 */
if(q.base)
delete []q.base;
q.base = NULL;
q.front = q.rear = 0;
}
7、队列长度
对于循环队列,差值可能为负数,所以需要将差值加上MAXQSIZE后与MAXQSIZE求余。
// 算法3.12 求循环队列的长度
int QueueLength(SqQueue q) // 返回Q的元素个数,即队列的长度
{
return (q.rear - q.front+ MAXQSIZE) % MAXQSIZE;
}
8、入队
①判断是否队满
②插入新元素到队尾
③队尾指针+1
Status EnQueue(SqQueue &q, QElemType e) // 插入元素e为Q的新的队尾元素
{
if ((q.rear + 1) % MAXQSIZE == q.front)
return ERROR;
q.base[q.rear] = e;
q.rear = (q.rear + 1) % MAXQSIZE;
return OK;
}
9、出队
①判断是否队空
②保存队头元素
③队头指针+1
Status DeQueue(SqQueue &q, QElemType &e) // 删除Q的队头元素,用e返回其值
{
if (q.front == q.rear)
return ERROR;
e = q.base[q.front];
q.front = (q.front + 1) % MAXQSIZE;
return OK;
}
10、取队头元素
// 算法3.15 取循环队列的队头元素
QElemType GetHead(SqQueue q) // 返回Q的队头元素,不修改队头指针
{
if (q.front != q.rear) return q.base[q.front];
}
11、输出队列
void PrintQueue(SqQueue q)
{
for (int i = q.front; i != q.rear; i = (i + 1) % MAXQSIZE)
{
if (i != q.front)
cout << ' ';
cout << q.base[i];
}
cout << endl;
}