循环队列:头尾相接的顺序存储结构的队列。
循环队列的顺序存储结构:
typedef int QElemType; /* 这里假设为int */
typedef struct
{
QElemType data[MAXSIZE];
int front; /* 头指针 */
int rear; /* 尾指针,若队列不空,指向队列尾元素的下一个位置 */
} SqQueue;
循环队列的初始化:
/* 初始化一个空队列Q */
Status InitQueue( SqQueue *Q )
{
Q->front = 0;
Q->rear = 0;
return OK;
}
循环队列求队列长度:
/* 返回Q的元素个数 */
int QueueLength( SqQueue Q )
{
return ( Q.rear - Q.front + MAXSIZE ) % MAXSIZE;
}
循环队列的入队列操作:
/* 若队列未满,则插入元素e为Q新的队尾元素 */
Status EnQueue( SqQueue *Q, QElemType e )
{
if( ( Q->rear + 1 ) % MAXSIZE == Q->front ) /* 队列满的判断 */
return ERROR;
Q->data[Q->rear] = e; /* 将元素e赋值给队尾 */
Q->rear = ( Q->rear + 1 ) % MAXSIZE; /* rear指针向后移一位置,若到最后则转到数组头部 */
return OK;
}
循环队列的出队列操作:
/* 若队列不空,则删除Q中队头元素,用e返回其值 */
Status DeQueue( SqQueue *Q, QElemType *e )
{
if ( Q->front == Q->rear ) /* 队列空的判断 */
return ERROR;
*e = Q->data[Q->front]; /* 将队头元素赋值给e*/
Q->front = ( Q->front + 1 ) % MAXSIZE; /* front指针向后移一位置,若到最后则转到数组头部 */
return OK;
}
对于循环队列和链队列的比较:
1,时间上,它们都是O(1)。不过循环是实现申请好空间,使用期间不释放,对于链队列,每次申请和释放结点会存在一些时间开销。
2,空间上,链队列更加灵活。循环队列必须有一个固定的长度,所以就有了存储元素个数和空间浪费问题,链队列没有这问题,但它需要一个指针域,会产生一些空间上的开销,不过这可以接受。
总的来说,在可以确定队列长度最大值的情况下,建议使用循环队列,如果你无法估计队列长度,则用链队列。