循环队列

Posted congmingyige

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了循环队列相关的知识,希望对你有一定的参考价值。

循环队列

队列:先进先出,FIFO。

牺牲一个单元,使队列为空和只有一个元素时不要产生歧义

 

队首front,队尾rear,队列为a[front+1]~a[rear]

开一个大小为n的数组,a:array[0..n-1] of longint ,当rear=n-1时,需要在队尾增加一个数据,此时没有存储空间,但此时使用的内存单元只是a[front+1]~a[rear],前面的a[1]~a[front]内存单元未被使用,却没有存储空间,导致假溢出。

 

可以使用循环队列,当rear=n-1,增加一个数据,则rear变为0,即回到原点。相当于把数组看成一个圆,设置圆的开头和结尾(相邻),从开头到结尾存储数据,当到了结尾,又重新返回开头。

 

Spfa常使用循环队列,从而节省队列的内存。

注意:

1.在队列里的点都不重复,所以队列的长度小于等于n(点的总个数)+1(牺牲的一个单元),

2.不用判断队列大小单元不够,只要开的足够大即可

 

 

ccf20170304类似spfa:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <malloc.h>
  4 #include <stdbool.h>
  5 #define maxn 100000
  6 #define maxm 200000
  7 #define maxc 1000000
  8  
  9 long max(long a,long b)
 10 {
 11     if (a>b)
 12         return a;
 13     else
 14         return b;
 15 }
 16  
 17 int main()
 18 {
 19     struct node
 20     {
 21         long d,len;
 22         struct node *next;
 23     };
 24     long n,m,head,tail,d,value,i,a,b,c;
 25     long *dis=(long *) malloc (sizeof(long)*(maxn+1));
 26     //循环队列
 27     long *line=(long *) malloc (sizeof(long)*(maxn+1));
 28     bool *vis=(bool *) malloc (sizeof(bool)*(maxn+1));
 29     //本身已经是struct node *point,创建数组再加"*"
 30     struct node **point=(struct node **) malloc (sizeof(struct node *)*(maxn+1));
 31     struct node *t;
 32     scanf("%ld%ld",&n,&m);
 33  
 34     for (i=1;i<=n;i++)
 35     {
 36         point[i]=NULL;
 37         //1 ≤ c ≤ 1000000
 38         //max<=c
 39         dis[i]=maxc;
 40         vis[i]=true;
 41     }
 42     for (i=1;i<=m;i++)
 43     {
 44         scanf("%ld%ld%ld",&a,&b,&c);
 45         //build a
 46         t=(struct node *) malloc (sizeof(struct node));
 47         t->d=b;
 48         t->len=c;
 49         if (point[a]!=NULL)
 50             t->next=point[a];
 51         else
 52             t->next=NULL;
 53         point[a]=t;
 54         //build b
 55         t=(struct node *) malloc (sizeof(struct node));
 56         t->d=a;
 57         t->len=c;
 58         if (point[b]!=NULL)
 59             t->next=point[b];
 60         else
 61             t->next=NULL;
 62         point[b]=t;
 63     }
 64     dis[1]=0;
 65     vis[1]=false;
 66     line[1]=1;
 67     //head=front-1 牺牲一个位置 front为队列头位置
 68     head=0;
 69     tail=1;
 70     //这里的循环队列不用判断空或者溢出
 71     //因为如果那样的话,已经不能用了。
 72     //不存在空的情况。而数组要开的足够大,使队列不溢出。
 73     while (head!=tail)
 74     {
 75         //head++;
 76         //队列为0~n
 77         head++;
 78         if (head==n+1)
 79             head=0;
 80         d=line[head];
 81         t=point[d];
 82         while (t)
 83         {
 84             if (dis[d]<t->len)
 85                 value=t->len;
 86             else
 87                 value=dis[d];
 88             if (value<dis[t->d])
 89             {
 90                 dis[t->d]=value;
 91                 //如果该点未被放在队列里,则入队;否则不入队
 92                 //即在队列里的点都不重复
 93                 //则队列(tail-head)最多有n+1个数(n个点+空位置(head))
 94                 if (vis[t->d])
 95                 {
 96                     //tail++;
 97                     tail++;
 98                     if (tail==n+1)
 99                         tail=0;
100                     line[tail]=t->d;
101                     vis[t->d]=false;
102                 }
103             }
104             t=t->next;
105         }
106         vis[d]=true;
107     }
108     printf("%ld\\n",dis[n]);
109     return 0;
110 }
  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <malloc.h>
  4 #include <stdbool.h>
  5 #define maxn 100000
  6 #define maxm 200000
  7 #define maxc 1000000
  8  
  9 long max(long a,long b)
 10 {
 11     if (a>b)
 12         return a;
 13     else
 14         return b;
 15 }
 16  
 17 int main()
 18 {
 19     struct node
 20     {
 21         long d,len;
 22         struct node *next;
 23     };
 24     long n,m,head,tail,d,value,i,a,b,c;
 25     long *dis=(long *) malloc (sizeof(long)*(maxn+1));
 26     //循环队列
 27     long *line=(long *) malloc (sizeof(long)*(maxn+1));
 28     bool *vis=(bool *) malloc (sizeof(bool)*(maxn+1));
 29     //本身已经是struct node *point,创建数组再加"*"
 30     struct node **point=(struct node **) malloc (sizeof(struct node *)*(maxn+1));
 31     struct node *t;
 32     scanf("%ld%ld",&n,&m);
 33  
 34     for (i=1;i<=n;i++)
 35     {
 36         point[i]=NULL;
 37         //1 ≤ c ≤ 1000000
 38         //max<=c
 39         dis[i]=maxc;
 40         vis[i]=true;
 41     }
 42     for (i=1;i<=m;i++)
 43     {
 44         scanf("%ld%ld%ld",&a,&b,&c);
 45         //build a
 46         t=(struct node *) malloc (sizeof(struct node));
 47         t->d=b;
 48         t->len=c;
 49         if (point[a]!=NULL)
 50             t->next=point[a];
 51         else
 52             t->next=NULL;
 53         point[a]=t;
 54         //build b
 55         t=(struct node *) malloc (sizeof(struct node));
 56         t->d=a;
 57         t->len=c;
 58         if (point[b]!=NULL)
 59             t->next=point[b];
 60         else
 61             t->next=NULL;
 62         point[b]=t;
 63     }
 64     dis[1]=0;
 65     vis[1]=false;
 66     line[1]=1;
 67     //head=front-1 牺牲一个位置 front为队列头位置
 68     head=0;
 69     tail=1;
 70     //这里的循环队列不用判断空或者溢出
 71     //因为如果那样的话,已经不能用了。
 72     //不存在空的情况。而数组要开的足够大,使队列不溢出。
 73     while (head!=tail)
 74     {
 75         //head++;
 76         //队列为0~n
 77         head++;
 78         if (head==n+1)
 79             head=0;
 80         d=line[head];
 81         t=point[d];
 82         while (t)
 83         {
 84             if (dis[d]<t->len)
 85                 value=t->len;
 86             else
 87                 value=dis[d];
 88             if (value<dis[t->d])
 89             {
 90                 dis[t->d]=value;
 91                 //如果该点未被放在队列里,则入队;否则不入队
 92                 //即在队列里的点都不重复
 93                 //则队列(tail-head)最多有n+1个数(n个点+空位置(head))
 94                 if (vis[t->d])
 95                 {
 96                     //tail++;
 97                     tail++;
 98                     if (tail==n+1)
 99                         tail=0;
100                     line[tail]=t->d;
101                     vis[t->d]=false;
102                 }
103             }
104             t=t->next;
105         }
106         vis[d]=true;
107     }
108     printf("%ld\\n",dis[n]);
109     return 0;
110 }

 

 

 

以上是关于循环队列的主要内容,如果未能解决你的问题,请参考以下文章

常用python日期日志获取内容循环的代码片段

使用从循环内的代码片段中提取的函数避免代码冗余/计算开销

AVKit – 视频片段仅循环 2 次

如何使用事件侦听器来加载动画片段的循环

用java实现循环队列?

java-----循环队列