循環隊列
阿新 • • 發佈:2017-05-06
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 89 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 }
循環隊列