zoukankan      html  css  js  c++  java
  • 循环队列的基本算法

    一、介绍

    正是因为队列从队头删除,从队尾添加的特点,所以在使用数组来表现队列时,元素的位置移动采用下标也即出队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
  • 相关阅读:
    Android 千牛数据库分析
    Flutter 你需要知道的那些事 01
    Flutter 异常处理之图片篇
    Flutter 即学即用系列博客——09 EventChannel 实现原生与 Flutter 通信(一)
    Flutter 即学即用系列博客——08 MethodChannel 实现 Flutter 与原生通信
    Flutter 即学即用系列博客——06 超实用 Widget 集锦
    Kingfisher-swift缓存图片框架
    swift冒泡排序,swift快速排序,swift归并排序,swift插入排序,swift基数排序
    swift声明属性为某个类型同时遵循某协议
    Xcode真机运行报错iPhone has denied the launch request
  • 原文地址:https://www.cnblogs.com/XYQ-208910/p/11700048.html
Copyright © 2011-2022 走看看