1. 程式人生 > >循環隊列

循環隊列

n-1 std build 4類 ++ can png col 元素

循環隊列

隊列:先進先出,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 }

循環隊列