關於隊列(還有廣度優先搜索的例題)
本博文的目錄:
$1 隊列
$2 隊列的例題
$3 廣度優先搜索的例題
$1 隊列:
•隊列是什麽?
隊列是一種特殊的線性表,與棧不同,這種線性表只允許在表的前端(我們稱為front或head)進行刪除操作,在表的後端(我們稱作rear或tail)進行插入操作。所以又叫F(First)I(In)F(First)O(Out)表。(對於棧來說,因為棧只允許在表的後端進行刪除操作,所以叫做L(Last)I(In)F(First)O(Out)表)
•在隊列裏的元素設定:
tail / rear:表示隊尾指針,應該指向隊尾元素的所在位置
head / front :表示隊頭指針,應指向隊頭元素的前一個位置
•入隊算法:
1 int q[maxn];
2 int head,tail;
3 int n;
4 head=0;//當前隊列的頭指針
5 tail=1;//當前隊列的為指針
6 cin>>n;
7 q[tail]=n;//在當前尾指針處存上n的值
8 tail++;//將尾指針加一
•出隊算法:
1 int q[maxn];
2 int head=0,tail=5;//假設隊中有5個元素
3 cout<<q[head++]<<endl;//將隊頭元素輸出
•循環隊列:
(1)循環隊列是啥?
當尾指針指向數組的最後一個元素時,數組將不能再繼續存儲,我們叫做“溢出”。但當隊列的指針指向最後一個元素時,不一定是溢出了,因為對頭指針不一定是0。若隊頭指針不為0,但隊尾指針指向隊列的最後一個元素時,這個隊列理論上是不能繼續存數據的,但是為隊列所開的數組確實有空間,我們稱之為“假溢出”。如果不對隊列進行循環處理,就會造成對空間的極大浪費。這個時候,我們可以將整個隊列看成是一個環,環上的元素就是隊列的元素,隊列的第maxn項後面為隊列的第1項,這樣就可以進行循環數組的使用啦!
(2)代碼實現:
光說概念大家肯定不會完全理解,接下來是代碼實現:
1 int q[maxn]; 2 int tail,head; 3 int n; 4 cin>>n; 5 q[tail%maxn]=n;//maxn表示q數組(隊列)的長度 6 tail=(tail+1)%maxn;
(這只是一個模板,具體的使用方法視情況而定);
$2 隊列的例題
•例--周末舞會:
【題目描述】
假設在周末舞會上,男士們和女士們進入舞廳時,各自排成一隊。跳舞開始時,依次從男隊和女隊的隊頭上各出一人配成舞伴。規定每個舞曲能有一對跳舞者。若兩隊初始人數不相同,則較長的那一隊中未配對者等待下一輪舞曲。現要求寫一個程序,模擬上述舞伴配對問題。
【輸入】
第一行兩隊的人數;
第二行舞曲的數目。
【輸出】
配對情況。
【輸入樣例】
4 6 7
【輸出樣例】
1 1
2 2
3 3
4 4
1 5
2 6
3 1
直接上代碼:
1 #include<cstdio>
2 #include<iostream>
3 #include<cstdlib>
4 #define maxn 1000010
5 using namespace std;
6 int head,tailw,tailm;//將兩個隊列看成一個,頭指針是一樣的,而尾指針則根據男女的人數決定;
7 int man[maxn],woman[maxn];//將所有男人的編號和所有女人的編號分別存到man和woman隊列裏;
8 int men,women,m;//men、women代表男人和女人的總數量;
9 int main(){
10 scanf("%d%d",&men,&women);
11 scanf("%d",&m);
12 for(int i = 0;i < men;++i){
13 man[i] = i+1; //讀入男人的編號;
14 }
15 for(int i = 0;i < women;++i){
16 woman[i] = i+1;//讀入女人的編號;
17 }
18 head = 0;
19 tailw = women; tailm = men;
20 while(head < m){
21 printf("%d %d\n",man[head],woman[head]);
22 man[tailm++] = man[head]; woman[tailw++] = woman[head];
23 head++;
24 }
25 return 0;
26 }//簡單易懂qaq
$3 廣度優先搜索的例題
•例--連通塊:
【題目描述】
一個n * m的方格圖,一些格子被塗成了黑色,在方格圖中被標為1,白色格子標為0。問有多少個四連通的黑色格子連通塊。四連通的黑色格子連通塊指的是一片由黑色格子組成的區域,其中的每個黑色格子能通過四連通的走法(上下左右),只走黑色格子,到達該聯通塊中的其它黑色格子。
【輸入】
第一行兩個整數n,m(1≤n,m≤100),表示一個n * m的方格圖。
接下來n行,每行m個整數,分別為0或1,表示這個格子是黑色還是白色。
【輸出】
一行一個整數ans,表示圖中有ans個黑色格子連通塊。
【輸入樣例】
3 3 1 1 1 0 1 0 1 0 1
【輸出樣例】
3
1 #include<cstdio>
2 #include<iostream>
3 #include<cstdlib>
4 #define maxn 110
5 using namespace std;
6 const int flag[4][2] = {{0,1},{0,-1},{1,0},{-1,0}};//設了一個數組,表示在(i,j)的情況下向4個方向搜索
7 int a[maxn][maxn],queue[maxn * maxn][2];//queue中存的是搜索到的聯通塊的橫縱坐標
8 int n,m,ans;
9 bool p[maxn][maxn];
10
11 void bfs(int x,int y){
12 int head = 0, tail = 2;
13 queue[1][0] = x,queue[1][1] = y;
14 while(head < tail - 1){
15 ++head;
16 x = queue[head][0];
17 y = queue[head][1];
18 for(int i = 0;i < 4;++i){
19 int x1 = x + flag[i][0];
20 int y1 = y + flag[i][1];
21 if(x1 < 1 || y1 < 1 || x1 > n || y1 > m || !a[x1][y1] || p[x1][y1]) continue;
22 p[x1][y1] = true;
23 queue[tail][0] = x1;
24 queue[tail++][1] = y1;
25 }
26 }
27 }
28
29 int main(){
30 cin>>n>>m;
31 for(int i = 1;i <= n;++i)
32 for(int j = 1;j <= m ;++j) cin>>a[i][j];
33 for(int i = 1;i <= n;++i)
34 for(int j = 1;j <= m ;++j)
35 if(a[i][j] && !p[i][j]){
36 ++ans;bfs(i,j);
37 }
38 cout<<ans<<endl;
39 return 0;
40 }
//本題的思路:搜索為1的元素-->如果為1,將聯通塊的附近搜索-->將搜過的元素標為0-->搞定!
關於隊列(還有廣度優先搜索的例題)