关于bfs广度优先搜索,移步:
这里讲述队列的应用,使用 bfs (广度优先搜索)
例1.寻找最近相同字母位置
想法思路: 先将黄色的X进入队列,然后向左一步,向右一步分开扩展,直至找到最近的相同字母。
注意:同一个位置不能重复进入队列,,需要用数组 flag 标记进入队列的下标,避免重复进入
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define maxn 100
typedef struct node
{
int front,rear=-1;
char data[maxn];
int id[maxn];
int count;
}Squeue;
int n,flag[1001];
char ch[1001];
void init(Squeue &s) {s.count=0; s.front=0; s.rear=-1;} //初始化
void push(Squeue &s,int x) // 入队列
{
s.count++;
s.data[++s.rear]=ch[x];
s.id[s.rear]=x; // 在原字符串中的位置
}
char pop(Squeue &s) // 出队列
{
s.count--;
return s.data[s.front++];
}
char getpop(Squeue &s) {return s.data[s.front];} // 返回队首
int getpopid(Squeue &s) {return s.id[s.front];} // 返回队首
bool empty(Squeue s) {if(s.front==s.rear && s.count==0) return true; else return false;} // 判断队列是否为空
void bfs(Squeue &s)
{
if(empty(s)) return ;
push(s,n); flag[n]=1; // 入队列 标记为已入队列
while(!empty(s)) // 如果找不到,则在为空时,返回空
{
int x=getpopid(s);
pop(s); // 取出
if(ch[x-1]==ch[n]) // 左边一个判断
{
printf("%d",x-1);
return ;
}
if(ch[x+1]==ch[n]) // 右边一个判断
{
printf("%d",x+1);// 判断到最近的即可直接输出返回
return ;
}
if(flag[x-1]==0) {push(s,ch[x-1]); flag[x-1]=1;} // 左右如果没进入队列过,分别进入队列
if(flag[x+1]==0) {push(s,ch[x+1]); flag[x+1]=1;}
}
}
int main()
{
Squeue S;
scanf("%s",ch); scanf("%d",&n);
init(S);
bfs(S);
system("pause");
return 0;
}
上面的例题为一维,扩展到二维。
例题2.
如同一维数组向左向右扩展一样,这里分别向上,向下,向左,向右扩展(同上面一样,同一个位置不能重复进入队列),这里由于是二维,所以各需要横纵坐标记录位置。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
using namespace std;
#define maxn 100
typedef struct node
{
int front,rear=-1;
char data[101];
int id1[maxn]; // 二维横坐标
int id2[maxn];// 纵坐标
int count;
}Squeue;
char ansc;
int ans=100001;
int n,flag[101][101],m;
char ch[101][101];
void init(Squeue &s) {s.count=0; s.front=0; s.rear=-1;}
void push(Squeue &s,int x,int y)
{
s.count++;
s.data[++s.rear]=ch[x][y];
s.id1[s.rear]=x;
s.id2[s.rear]=y;
}
char pop(Squeue &s)
{
s.count--;
return s.data[s.front++];
}
char getpop(Squeue &s) {return s.data[s.front];}
int getpopid1(Squeue &s) {return s.id1[s.front];}
int getpopid2(Squeue &s) {return s.id2[s.front];}
bool empty(Squeue s) {if(s.front>s.rear) return true; else return false;}
void bfs(Squeue &s,int x,int y)
{
push(s,x,y); flag[x][y]=1;
while(!empty(s))
{
int x1=getpopid1(s);
int y1=getpopid2(s);
pop(s);
if(ch[x1+1][y1]==ch[x][y] && x1+1<=n && !(x1+1==x && y1==y)) //向右扩展,注意不能超出边界
{
if(ans>(abs(x1+1-x)+abs(y1-y)))
{
ans=abs(x1+1-x)+abs(y1-y);
ansc=ch[x][y];
}
}
if(ch[x1][y1+1]==ch[x][y] && y1+1<=m && !(x1==x && y1+1==y)) // 向下扩展,不能超出边界
{
if(ans>(abs(x1-x)+abs(y1+1-y)))
{
ans=abs(x1-x)+abs(y1+1-y);
ansc=ch[x][y];
}
}
if(ch[x1-1][y1]==ch[x][y] && x1-1>=1 && !(x1-1==x && y1==y)) // 向上扩展,不能超出边界
{
if(ans>(abs(x1-1-x)+abs(y1-y)))
{
ans=abs(x1-1-x)+abs(y1-y);
ansc=ch[x][y];
}
}
if(ch[x1][y1-1]==ch[x][y] && y1-1>=1 && !(x1==x && y1-1==y))// 向左扩展,不能超出边界
{
if(ans>(abs(x1-x)+abs(y1-1-y)))
{
ans=abs(x1-x)+abs(y1-1-y);
ansc=ch[x][y];
}
}
// 注意无论是怎么扩展,一定不能是原来的点
if(flag[x1-1][y1]==0 && x1-1>=1 && y1>=1) {push(s,x1-1,y1); flag[x1-1][y1]=1;}
if(flag[x1+1][y1]==0 && x1+1<=n && y1>=1) {push(s,x1+1,y1); flag[x1+1][y1]=1;}
if(flag[x1][y1+1]==0 && y1+1<=m && x1>=1) { push(s,x1,y1+1);flag[x1][y1+1]=1;}
if(flag[x1][y1-1]==0 && y1-1>=1 && x1>=1) {push(s,x1,y1-1); flag[x1][y1-1]=1;}
} // 没有入队列的入队列
}
int main()
{
Squeue S;
memset(S.id1,0,sizeof(S.id1));
memset(S.id2,0,sizeof(S.id2));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
cin>>ch[i][j];
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
init(S);
bfs(S,i,j);
memset(flag,0,sizeof(flag));
}
printf("%c",ansc);
system("pause");
return 0;
}
如果熟练的采用 bfs(广度优先搜索)的话,可以直接用bfs搜索的方法
#include<stdio.h>
#include<iostream>
using namespace std;
#include<string.h>
#include<math.h>
char ch[101][101];
int n,m;
int flag[1001][1001];
int ans=100001;
char ansc;
void bfs(int x1,int y1,int x,int y)
{
if(flag[x1][y1]==1) return ; // 经历过的点,直接返回
flag[x1][y1]=1;
if(ch[x1][y1]==ch[x][y] && !(x1==x && y1==y) )
{
if(ans>abs(x1-x)+abs(y1-y))
{
ans=abs(x1-x)+abs(y1-y);
ansc=ch[x][y];
}
}
if(x1+1<=n && flag[x1+1][y1]==0) bfs(x1+1,y1,x,y); // 均不能超出边界
if(x1-1>=1 && flag[x1-1][y1]==0) bfs(x1-1,y1,x,y);
if(y1+1<=m && flag[x1][y1+1]==0) bfs(x1,y1+1,x,y);
if(y1-1>=1 && flag[x1][y1-1]==0) bfs(x1,y1-1,x,y);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) cin>>ch[i][j];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
bfs(i,j,i,j);
memset(flag,0,sizeof(flag));
}
printf("%c",ansc);
}