队列与广度优先搜索概述+一本通1362

在C++中有很多数据结构,包括栈(stack)、队列(queue)、容器(vector)、数对(pair)等。这篇博客的重点是队列。

1.队列的定义:一种线性数据结构,可以插入和弹出数据。每个队列除了有数据,还有两个指针,“头指针”指向队列的第一个元素(以下简称队首),“尾指针”指向队列的最后一个元素(以下简称队尾)。插入数据时在队列的队尾后插入,并使尾指针后移一位。弹出时是弹出队首的元素,并使头指针后移一位。也就是说,先插入的元素会先被弹出,这一特性叫做“先进先出”(FIFO,“First in first out”)。

以下是一个队列的例子,其中Enqueue函数是插入操作,Dequeue函数是弹出操作。

(来自百度)

2.队列的基本操作:

(1)头文件:<queue>

(2)声明一个队列:queue<typename T>  q;  (typename是指队列中存放的数据类型,最常见的如int、char)

(3)插入操作:void push(T a);(这里是指a的类型由上述typename决定,下同)

(4)弹出操作:void pop(); 

(5)获得队首元素:T front();

(6)获得队尾元素:T back();

(7)获得队列里的元素数量:size_type size();

(8)检验队列是否为空:bool empty();

3.广度优先搜索(bfs)是指从当前节点访问所有与它相邻的节点(称为第一层),全部访问完以后,再访问与第一层相连的所有节点(第二层)......以此类推,直到所有节点都搜索完为止。

上面的树,广度优先搜索会得到以下的搜索次序:1 2 3 4 5 6 7 8 。而深度优先搜索则是:1 2 6 7 3 4 8 5。

队列是一端插入,另一端弹出的线性数据结构,这给广度优先搜索的实现带来了极大便利。先把根节点插入队列,再插入与它相连的节点,依次访问,访问节点的同时把与它相连的节点插入队列,访问后弹出该节点。若队列为空,则证明搜索结束。

4.例题(ybt1362:家庭问题(family))

【题目描述】有n个人,编号为1,2,……n,另外还知道存在K个关系。一个关系的表达为二元组(α,β)形式,表示α,β为同一家庭的成员。当n,k和k个关系给出之后,求出其中共有多少个家庭、最大的家庭中有多少人?例如:n=6,k=3,三个关系为(1,2),(1,3),(4,5)此时,6个人组成三个家庭,即:{1,2,3}为一个家庭,{4,5}为一个家庭,{6}单独为一个家庭,第一个家庭的人数为最多。

【输入】第一行为n,k二个整数(1≤n≤100)(用空格分隔);接下来的k行,每行二个整数(用空格分隔)表示关系。

【输出】二个整数(分别表示家庭个数和最大家庭人数)。

【输入样例】

6 3

1 2

1 3

4 5

【输出样例】

3 3

代码如下:(以下代码用到了pair,它表示一个数组,包含于iostream里,第一个数用first表示,第二个用second表示)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<queue>
 5 using namespace std;
 6 int n,k;
 7 pair<int,int> rela[1000];//记录一对关系 
 8 int inWhichFamily[105];//记录每个人在编号为几的家庭中,0表示这个人独自成为一个家庭 
 9 queue<int> family[105];//模拟家庭 
10 
11 int main()
12 {
13     cin>>n>>k;
14     int p=1;//目前的家庭编号 
15     for(int i=1;i<=k;i++)
16     {
17         cin>>rela[i].first>>rela[i].second;
18         if((!inWhichFamily[rela[i].first])&&(!inWhichFamily[rela[i].second])&&rela[i].first!=rela[i].second)//这对关系不属于任何一个家庭,是一个新家庭。(注意排除关系的两个人相同的情况) 
19         {
20             family[p].push(rela[i].first);//新家庭的两个人 
21             family[p].push(rela[i].second);
22             inWhichFamily[rela[i].first]=p;//这两个人属于第p个家庭 
23             inWhichFamily[rela[i].second]=p;
24             p++;//家庭数量增加 
25         }
26         else if((!inWhichFamily[rela[i].first])&&(inWhichFamily[rela[i].second]))//有个人已经有所属家庭 
27         {
28             family[inWhichFamily[rela[i].second]/*那个人所属家庭的编号*/].push(rela[i].first);//将另一个人加入这个家庭中 
29             inWhichFamily[rela[i].first]=inWhichFamily[rela[i].second];//这个人获得了家庭编号 
30         }
31         else if((inWhichFamily[rela[i].first])&&(!inWhichFamily[rela[i].second]))//与上面的同理 
32         {
33             family[inWhichFamily[rela[i].first]].push(rela[i].second);
34             inWhichFamily[rela[i].second]=inWhichFamily[rela[i].first];        
35         }
36     }
37     int _max=1;
38     for(int i=1;i<=n;i++)
39     {
40     //    cout<<family[i].size();
41         if(!inWhichFamily[i]) p++;//再考虑独自成家的人 
42         if(family[i].size() > (unsigned)_max)//得到最大的家庭大小 
43         {
44             _max=family[i].size();
45         } 
46     }
47     cout<<p-1<<" "<<_max<<endl;//前面应该是多加了一个1 
48 }

好像和广度优先搜索没什么关系......算了不管了,开溜

posted @ 2020-03-22 18:14  梦中霜雪梨花白  阅读(372)  评论(0编辑  收藏  举报