队列的顺序存储实现—循环队列

   队列(queue)是一种只允许在一端插入元素,而在另一端删除元素的线性表。它是一种先进先出(First In First Out,FIFO)的线性表。我们把允许插入的一端称为队尾,允许删除元素的一端称为队头。由于队列也是一种线性表,所以队列的实现也有顺序存储和链式存储这两种实现。当队列顺序存储时,入队列操作所需要的时间复杂度为O(1),而出队列的时间复杂度为O(n)。因为删除队头元素时,需要将后面的元素整体向前移动。为了避免顺序存储队列删除元素时,导致其他元素的移动,可以考虑循环队列。循环队列是指队列的首尾两个指针可以绕着队列循环移动。例如,当往循环队列中添加元素(入队列)时,将队列的尾指针rear向后移动一步,如果其超出了队列的最大长度MAXSIZE则回绕到队列的头部继续;当从循环队列中取元素(出队列)时,将队列的头指针front向后移动一步,如果其超出了队列的最大长度MAXSIZE则回绕到队列的头部继续。我们指定当队列的头指针front和尾指针rear重合时,即front == rear时,队列为空。当rear与front相差一个位置时,我们就认定队列已满,即(rear+1)%MAXSIZE == front。对于队列的长度计算,则是通过公式:length = (rear -front+MAXSIZE)%MAXSIZE。
    循环队列涉及的主要操作有:初始化队列、判断一个队列是否为空、返回队列的长度、入队列操作以及出队列操作等。其代码实现如下:
#define MAXSIZE 20
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

typedef int Status;

//循环队列的顺序存储结构
typedef int ElemType;
typedef struct {
    ElemType data[MAXSIZE];//循环队列大小
    int front;//队列头指针
    int rear;//队列尾指针
}SqQueue;

/* *
 * 初始化一个队列
 * 让头尾指针相同,从队头开始
 * */
Status InitQueue(SqQueue *Q){
   Q->rear = 0;
   Q->front = 0;
}

/* *
 * 求循环队列的长度
 * 返回队列的长度
 * */

int QueueLength(SqQueue Q){
    return ((Q.rear-Q.front + MAXSIZE)%MAXSIZE);
}

/* *
 * 循环队列的入队操作
 * 成功返回1,
 * 失败返回0
 * */

Status EnQueue(SqQueue *Q,ElemType e){
    if((Q->rear + 1)%MAXSIZE == Q->front)
        return ERROR;//循环队列已满
    Q->data[Q->rear] = e;
    Q->rear = (Q->rear + 1)%MAXSIZE;//队尾指针指向下一个元素
    return OK;
}

/* *
 * 循环队列的出队列操作
 * 成功返回1,并把元素通过e返回
 * 失败返回0
 * */
Status DeQueue(SqQueue *Q,ElemType *e){
    if(Q->front == Q->rear)
        return ERROR;//循环队列为空
    *e = Q->data[Q->front];
    Q->front = (Q->front + 1)%MAXSIZE;//队头指针指向下一个元素
    return OK;
}

/* *
 * 判断一个循环队列是否为空
 * 如果队列为空,则返回TRUE,反之则返回FALSE
 * */
Status QueueEmpty(SqQueue Q){
    return Q.rear == Q.front?TRUE:FALSE;
}

测试代码为:

int main(){
    SqQueue Q;
    InitQueue(&Q);
    printf("The queue length is:%d\n",QueueLength(Q));
    if(QueueEmpty(Q))
        printf("The Queue is empty!\n");
    int i;
    for(i = 0; i < 10; i++){
       int  e = rand()%100 + 1;
       EnQueue(&Q,e);
       printf("The queue Length is:%d\n",QueueLength(Q));
    }
    int m;
    while(!QueueEmpty(Q)){
        if(DeQueue(&Q,&m))
            printf("delete the queue element is :%d\n",m);
        printf("The queue length is:%d\n",QueueLength(Q));
    }

    return 0;
}
循环队列虽然可以做到插入和删除元素所需要的时间复杂为为O(1),但它还是存在顺序存储链表的不足之处:需要预先指定队列的大小,这样可能面临着数组可能溢出的问题。而队列的链式存储则不需要担心队列长度问题。



  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值