数据结构 ⑦ 队列

队列的概念

队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。

和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。

队列的数据元素又称为队列元素。

在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。

因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出线性表。


队列

顺序队列

建立顺序队列结构必须为其静态分配或动态申请一片连续的存储空间,并设置两个指针进行管理。一个是队头指针front,它指向队头元素;另一个是队尾指针rear,它指向下一个入队元素的存储位置。

  • "假上溢"现象**
    由于入队和出队操作中,头尾指针只增加不减小,致使被删元素的空间永远无法重新利用。当队列中实际的元素个数远远小于向量空间的规模时,也可能由于尾指针已超越向量空间的上界而不能做入队操作。该现象称为"假上溢"现象。


    顺序队列-假溢出
  • 循环队列
    在实际使用队列时,为了使队列空间能重复使用,往往对队列的使用方法稍加改进:无论插入或删除,一旦rear指针增1或front指针增1 时超出了所分配的队列空间,就让它指向这片连续空间的起始位置。
    MaxSize-1增1变到0,可用取余运算rear%MaxSizefront%MaxSize来实现。
    在循环队列中,队列判空的条件时front=rear,而队列判满的条件时front=(rear+1)%MaxSize,实际使用空间为 MaxSize - 1

  • 代码实现

    1. 结构
    typedef struct 
    {
        int data[MaxSize];//数据
        int front;//队头
        int rear;//队尾
    }SeQueue;
    
    1. 初始化(初始条件:队列 不存在。操作结果:构造了一个空队;)
    SeQueue *Init_queue(){
    
       SeQueue *queue = (SeQueue *)malloc(sizeof(MaxSize));
       if (queue == NULL)
       {
          printf("初始化队列失败\n");
          return NULL;
       }
       queue->front = 0;
       queue->rear = 0;
       printf("初始化队列成功\n");
       return queue;
    }
    
    1. 入队(初始条件: 队列存在且队未满。操作结果: 对已存在的队列q,插入一个元素x 到队尾,队发生变化;)
    void Insert_queue(SeQueue *queue,int value){
          
           if ((queue->rear + 1) % MaxSize == queue->front)
           {
               printf("队满\n");
               return;
           }
           queue->data[queue->rear] =  value;
           queue->rear = (queue->rear + 1) % MaxSize;
           printf("%d\n", queue->rear);
          }
    
    1. 出队 (初始条件: 队列存在且非空,操作结果: 删除队首元素,并返回其值,队发生变化;)
    void delete_queue(SeQueue *queue){
           if (queue->rear == queue->front)
           {
               printf("队空\n");
               return;
           }
           queue->front = (queue->front + 1) % MaxSize;    
    }
    
    1. 遍历
    void queueDescription(SeQueue queue){
       
        for (int i = queue.front; i != queue.rear; i=(i+1)%MaxSize)
        {
           printf("i=%d--data=%d   ", i,queue.data[I]);
        }
       printf("\n");
    }
    
    1. 清空队列
        void clearQueue(SeQueue *queue){
       queue->front = 0;
       queue->rear = 0;
       printf("清空队列\n");
    }
    
    1. 获取当前队列长度
            int getQueueLength(SeQueue queue){
            
            return (queue.rear - 0 + MaxSize - queue.front) % MaxSize ;
        }
    

链式队列

在队列的形成过程中,可以利用线性链表的原理,来生成一个队列。

基于链表的队列,要动态创建和删除节点,效率较低,但是可以动态增长。

每次读取一个元素,释放一个元素。所谓的动态创建,动态释放。因而也不存在溢出等问题。由于链表由结构体间接而成,遍历也方便。

链式队列
  • 代码实现

    1. 结构

       typedef struct SeQueueNode
      {
          int data;//数据
             struct SeQueueNode * next;
        }SeQueueNode,*LinkQueueNode;
       typedef struct 
      {
          LinkQueueNode rear;
          LinkQueueNode front;
      }LinkQueue;
      
    2. 初始化(初始条件:队列 不存在。操作结果:构造了一个空队;)

       LinkQueue init_LinkQueue(){
         LinkQueue *queue = (LinkQueue *)malloc(sizeof(LinkQueue));
         queue->rear = queue->front = (LinkQueueNode)malloc(sizeof(LinkQueueNode));
         return *queue; 
       }
      
    3. 入队(初始条件: 队列存在。操作结果: 对已存在的队列q,插入一个元素x 到队尾,队发生变化;)

          void insert_LinkQueue(LinkQueue *Q,int data){
         
         LinkQueueNode node = (LinkQueueNode )malloc(sizeof(LinkQueueNode));
         if (node == NULL)
         {
             //创建失败
             return;
         }
         node->next = NULL;
         node->data = data;
         Q->rear->next = node;
         Q->rear = node;
       }
      
    4. 出队 (初始条件: 队列存在且非空,操作结果: 删除队首元素,并返回其值,队发生变化;)

       void delete_LinkQueue(LinkQueue *Q){
       
       if (Q->front == Q->rear)
       {
           return;
       }
       LinkQueueNode node = Q->front->next;
      
       Q->front->next = node->next;
      
       if(Q->rear == node) Q->rear = Q->front;
      
       free(node);
       }
      
    5. 遍历

      void LinkQueueTraverse(LinkQueue Q){
      LinkQueueNode node = Q.front->next;
      while(node){
      printf("%d", node->data);
      node = node ->next;
      }
      printf("\n");
      }
      
    6. 清空队列

        void ClearQueue(LinkQueue *Q){
      
      LinkQueueNode node = Q->front->next;
      Q->rear = Q->front;
      Q->front->next = NULL;
      while (node) {
        
        LinkQueueNode temp = node;
        node = node->next;
        free(temp);
        
      }
      }
       ```
      
    7. 获取当前队列长度

      int getLinkQueueLength(LinkQueue Q){
        int i= 0;
        LinkQueueNode p;
        p = Q.front;
        while (Q.rear != p) {
            I++;
            p = p->next;
        }
        return I;
      }
      
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,591评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,448评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,823评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,204评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,228评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,190评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,078评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,923评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,334评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,550评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,727评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,428评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,022评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,672评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,826评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,734评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,619评论 2 354

推荐阅读更多精彩内容

  • 循环队列 #include #include #defineFALSE0 #defineTRUE1 typedef...
    百合_b06b阅读 599评论 0 0
  • /***************利用数组模拟循环队列***************/ #include "stdi...
    HanMeng阅读 734评论 0 0
  • 注:不足及错误请指正 +qq1366963396讨论 队列(queue)是只允许在一端进行插入操作,而在另一端进行...
    lxr_阅读 874评论 0 0
  • C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构。C程...
    小辰带你看世界阅读 1,830评论 0 1
  • 数据结构 第7讲 循环队列 过了一段时间,小张再也受不了...
    rainchxy阅读 8,990评论 4 16