循环队列的基本算法

一、介绍

正是因为队列从队头删除,从队尾添加的特点,所以在使用数组来表现队列时,元素的位置移动采用下标也即出队front++或者入队rear++的方式实现,这里会体现出一个局限性,资源空间的浪费。怎么理解呢?

草图所示:

图示解释:

一个数组队列是满的,arr[0]=a1 ,arr[1]=a2,arr[2]=a3,arr[3]=a4, 此时再将a5入队列肯定是失败的。那么可以依次将a1,a2出队列,此时可以看到arr[0],arr[1]的位置空出来了。然而,由于入队的元素必须从队尾进入,所以虽然有空余的位置arr[0],arr[1], a5却不能入队列,这就造成了空间的浪费。在这里可以做一个优化,不再单纯的将位置移动也即front++或者rear++,而是采用一个简单的算法来计算元素应该在数组中放置的位置,其实就是采用循环队列来解决这个问题。循环队列需要注意队列已满的判决条件,由于尾指针始终指向尾元素的下一个位置,所以队列始终会有一个空位置,其实未满,但是这种情况代表了已满。

草图所示:

 

循环队列算法

出队列:front = (front + 1) % maxSize 

入队列:rear = (rear + 1) % maxSize 

空队列:front == rear

满队列:front == (rear + 1) % maxSize

元素数:eleCount = (rear - front + maxSize) % maxSize

  

二、算法

#define MAXQSIZE         5 ///队列的最大长度                                    
#define QUEUE_OVERFLOW  -1                                               
#define OK               1                                               
#define ERROR            0                                               
#define TRUE             1                                               
#define FALSE            0                                               
                                                                         
typedef int QElemType;                                                   
typedef int Status;                                                      
                                                                         
/// ----- 循环队列 ------- 队列的顺序存储结构                                         
                                                                         
typedef struct  {                                                        
    QElemType *base; //初始化的动态分配存储空间,存储元素                                 
    int front;       //队头指针,若队列不空,指向队列头元素                                
    int rear;        //队尾指针,若队列不空,指向队列尾元素的下一个位置                          
}SqQueue;                                                                
                                                                         
                                                                         
Status InitQueue(SqQueue &Q);             //初始化一个空的循环队列                  
int    QueueLength(SqQueue Q);            //获取队元素个数                      
Status EnQueue(SqQueue &Q, QElemType e);  //把元素e从队尾添加队列中                 
Status DeQueue(SqQueue &Q, QElemType &e); //获取队列的头元素,并取出元素值赋给e保存         

 

三、代码

Status InitQueue(SqQueue &Q) {                                                    
                                                                                  
    ///初始化一个空的循环队列                                                                
    Q.base = (QElemType *)malloc(MAXQSIZE * sizeof(QElemType));                   
    if (!Q.base) exit(QUEUE_OVERFLOW); //存储分配失败                                   
    Q.front = Q.rear = 0;                                                         
    cout<<"空队列创建成功"<<endl;                                                        
    return  OK;                                                                   
}                                                                                 
                                                                                  
int QueueLength(SqQueue Q) {                                                      
                                                                                  
    ///获取队元素个数                                                                    
    int eleCount = (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;                      
    cout<<"队列元素有:"<<eleCount<<""<<endl;                                          
    return eleCount;                                                              
                                                                                  
}                                                                                 
                                                                                  
Status EnQueue(SqQueue &Q, QElemType e){                                          
                                                                                  
    ///把元素e从队尾添加队列中                                                               
    if ((Q.rear + 1) % MAXQSIZE == Q.front) {                                     
        cout<<"队列已满"<<endl;                                                       
        return ERROR; //队列已满                                                      
    }                                                                             
    Q.base[Q.rear] = e;                                                           
    Q.rear = (Q.rear + 1) % MAXQSIZE;                                             
    cout<<"入队的元素:"<<e<<",front = "<<Q.front<<",rear = "<<Q.rear<<endl;            
    return OK;                                                                    
}                                                                                 
                                                                                  
Status DeQueue(SqQueue &Q, QElemType &e){                                         
                                                                                  
    ///获取队列的头元素,并取出元素值赋给e保存                                                       
    if(Q.front == Q.rear){                                                        
        cout<<"队列已空"<<endl;                                                       
        return ERROR; //队列已空                                                      
    }                                                                             
    e = Q.base[Q.front];                                                          
    Q.front = (Q.front + 1) % MAXQSIZE;                                           
    cout<<"出队的元素:"<<e<<",front = "<<Q.front<<",rear = "<<Q.rear<<endl;            
    return OK;                                                                    
}                                                                                 

 

四、结果

测试: 

int main() {                                    
                                                
    //构建队列                                      
    SqQueue Q;                                  
    if (InitQueue(Q)) {                         
        for (int i = 0; i < MAXQSIZE; ++i) {    
            //入队列                               
            EnQueue(Q, i + 1);                  
        }                                       
    }                                           
                                                
    //获取队列元素个数                                  
    QueueLength(Q);                             
    cout<<endl;                                 
                                                
    for (int j = 0; j < 3; ++j) {               
        //出队列                                   
        QElemType e;                            
        DeQueue(Q, e);                          
                                                
        //获取队列元素个数                              
        QueueLength(Q);                         
    }                                           
                                                
    return 0;                                   
}                                               

打印:

/Users/xiayuanquan/CLionProjects/cycleQueue/cmake-build-debug/cycleQueue
空队列创建成功
入队的元素:1,front = 0,rear = 1
入队的元素:2,front = 0,rear = 2
入队的元素:3,front = 0,rear = 3
入队的元素:4,front = 0,rear = 4
队列已满
队列元素有:4个

出队的元素:1,front = 1,rear = 4
队列元素有:3个
出队的元素:2,front = 2,rear = 4
队列元素有:2个
出队的元素:3,front = 3,rear = 4
队列元素有:1个

进程已结束,退出代码 0

 

posted @ 2019-10-18 18:34  XYQ全哥  阅读(3863)  评论(1编辑  收藏  举报