数据结构与算法-线性表专题(五)-队列

队列

队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头

顺序队列中的溢出现象:
(1) "下溢"现象:当队列为空时,做出队运算产生的溢出现象。“下溢”是正常现象,常用作程序控制转移的条件。
(2)"真上溢"现象:当队列满时,做进栈运算产生空间溢出的现象。“真上溢”是一种出错状态,应设法避免。
(3)"假上溢"现象:由于入队和出队操作中,头尾指针只增加不减小,致使被删元素的空间永远无法重新利用。当队列中实际的元素个数远远小于向量空间的规模时,也可能由于尾指针已超越向量空间的上界而不能做入队操作。该现象称为"假上溢"现象。

克服假溢出的方法有两种:
一种是将队列中的所有元素均向低地址区移动,显然这种方法是很浪费时间的;本文不探讨
另一种方法是将数组存储区看成是一个首尾相接的环形区域。当存放到n地址后,下一个地址就"翻转"为1。在结构上采用这种技巧来存储的队列称为循环队列


这样的话,出现一个问题:上图(b)、(c)情况无法准确判断哪一种,
为了解决此问题,我们在队列中牺牲一个存储单元,即

当Q.rear和Q.front之间只空一个存储单元时认为队列是满的

循环队列的顺序存储实现

0.数据结构声明

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 6 /* 存储空间初始分配量 */

typedef int Status;
typedef int QElementType;
//顺序循环队列结构,注意需要牺牲一个空间
typedef struct{
    
    QElementType data[MAXSIZE];
    int front;  //队列头
    int rear;   //队列尾
}SqQueue;

初始化

//**初始化**
Status InitSqQueue(SqQueue *SqQueue){
    
    SqQueue->front = SqQueue->rear = 0;
    return OK;
}

SqQueue SqQueue;
Status iStatus;
iStatus = InitSqQueue(&SqQueue);

清空

//**清空**
Status ClearSqQueue(SqQueue *SqQueue){
    
    //顺序存储不需要释放空间
    SqQueue->front = SqQueue->rear = 0;
    return OK;
}

判断是否为空

//**判断是否为空**
BOOL IsEmpty(SqQueue SqQueue){
    
    if (SqQueue.front == SqQueue.rear) {
        
        return TRUE;
    }
    return FALSE;
}

判断队满

//判断队满
BOOL IsEnough(SqQueue SqQueue){
    
    if ((SqQueue.rear + 1)%MAXSIZE == SqQueue.front) {
        
        return TRUE;
    }
    return FALSE;
}

队列长度

//**队列长度**
Status QueueLength(SqQueue SqQueue){
    
    if (IsEmpty(SqQueue)){
        
        return 0;
    }
    return ((SqQueue.rear + MAXSIZE) - SqQueue.front) % MAXSIZE;
}

获取队头

Status QueueFront(SqQueue SqQueue,QElementType *data){
    
    if (IsEmpty(SqQueue)) {
        
        return ERROR;
    }
    
    *data = SqQueue.data[SqQueue.front];
    return OK;
}

出队

//**出队**
Status QueueAway(SqQueue *SqQueue,QElementType *data){
    
    if (IsEmpty(*SqQueue)) {
        //队空
        printf("此队列为空!无法出队\n");
        return ERROR;
    }
    
    *data = SqQueue->data[SqQueue->front];
    SqQueue->front = (SqQueue->front + 1) % MAXSIZE;
    
    return OK;
}

入队

//**入队**
Status QueueEnter(SqQueue *SqQueue,QElementType data){
    
    if (SqQueue->rear == (MAXSIZE-1)) {
        //队满
        printf("此队列已满!无法入队\n");
        return ERROR;
    }
    
    if (IsEnough(*SqQueue)) {
        //队满
        printf("此队列已满!无法入队\n");
        return ERROR;
    }
    
    SqQueue->data[SqQueue->rear] = data;
    SqQueue->rear = (SqQueue->rear + 1) % MAXSIZE;
    return OK;
}

遍历

//从队首到队尾依次每个元素打印
Status QueueReverse(SqQueue SqQueue){
    
    if (IsEmpty(SqQueue)){
        
        printf("此队列为空!\n");
        return ERROR;
    }
    int index = SqQueue.front;
    printf("此队列长度为:%d\n",QueueLength(SqQueue));
    while (index < SqQueue.rear) {
        
        printf("%d ",SqQueue.data[index]);
        index = (index + 1) % MAXSIZE;
    }
    printf("\n");

    return OK;
}

代码示例:

        SqQueue SqQueue;
        Status iStatus;
        iStatus = InitSqQueue(&SqQueue);
        if (iStatus == OK) {
            
            QueueReverse(SqQueue);
            //入队
            printf("入队1~10\n");
            for (int i = 1; i < 10; i++) {
                
                QueueEnter(&SqQueue, i);
            }
            QueueReverse(SqQueue);
            
            printf("清空队列\n");
            ClearSqQueue(&SqQueue);
            QueueReverse(SqQueue);
            //入队
            printf("入队101~110\n");
            for (int i = 101; i < 110; i++) {
                
                QueueEnter(&SqQueue, i);
            }
            QueueReverse(SqQueue);
            
            QElementType pushData;
            QueueAway(&SqQueue, &pushData);
            printf("当前出队的是:%d\n",pushData);
            QueueReverse(SqQueue);

            QueueAway(&SqQueue, &pushData);
            printf("当前出队的是:%d\n",pushData);
            QueueReverse(SqQueue);

            QueueAway(&SqQueue, &pushData);
            printf("当前出队的是:%d\n",pushData);
            QueueReverse(SqQueue);
            
            QueueAway(&SqQueue, &pushData);
            printf("当前出队的是:%d\n",pushData);
            QueueReverse(SqQueue);
           
        }else{
            
            printf("此队列初始化失败!\n");
        }

你可能感兴趣的:(数据结构与算法-线性表专题(五)-队列)