BFS识别矩阵中的块数

题目描述:
给出一个m*n的矩阵,矩阵中的元素为0或1.称位置(x,y)与其上下左右四个位置是相邻的。如果矩阵中有若干个1相邻,则称这些1构成了一个块。求给定矩阵中的块数。
输入:
0 1 1 1 0 0 1
0 0 1 0 0 0 0
0 0 0 0 1 0 0
0 0 0 1 1 1 0
1 1 1 0 1 0 0
1 1 1 1 0 0 0

解题思路:对于这个问题,求解的基本思想是:枚举每一个位置的元素,如果为0,则跳过;如果为1则使用BFS查询与该位置相邻

的4个位置(前提是不出界),判断它们是否为1(如果某个位置为1,则应当继续查询与该位置相邻的4个位置,直到整个‘1’块

访问完毕)。为了防止走回头路,可以设置一个数据索引记录记录每个位置是否在BFS中已入队。

  另外,我们可以设置增量数组来表示四个方向。

(这道题目也可以使用DFS解决,具体解法参见DFS求矩阵中的连通块数

1 int x[] = {0,0,1,-1};
2 int y[] = {1,-1,0,0};

参考代码:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <math.h>
  4 #include <string.h>
  5 #include <ctype.h>
  6 
  7 #define maxn 100
  8 #define MAX_SIZE 5    //最大队列长度+1
  9 
 10 
 11 struct postion{
 12     int x;
 13     int y;
 14 }pos;
 15 
 16 typedef struct postion ElemType;
 17 typedef struct SqQueue{
 18     ElemType *base;    //初始化的动态分配存储空间
 19     int front;    //头指针
 20     int rear;    //尾指针,若队列不空,指向队列尾元素的下一个位置 
 21 }SqQueue; 
 22 
 23 
 24 int n,m;    //矩阵大小n*m
 25 int martix[maxn][maxn] = {0};    //01矩阵
 26 int hashflag[maxn][maxn] = {0};    //记录位置x,y是否已经入队
 27 
 28 int X[] = {0,0,1,-1};
 29 int Y[] = {1,-1,0,0}; 
 30 
 31 void BFS(int x,int y);
 32 
 33 void InitQueue(SqQueue *Q);
 34 
 35 int QueueEmpty(SqQueue *Q);
 36 
 37 int EnQueue(SqQueue *Q,ElemType e);
 38 
 39 ElemType DeQueue(SqQueue *Q);
 40 
 41 int judge(int x,int y);
 42 
 43 int main(){
 44     
 45 
 46     
 47 
 48     scanf("%d%d",&n,&m);        //输入矩阵大小
 49     
 50     for(int x=0;x<n;x++){
 51         for(int y=0;y<m;y++){
 52             scanf("%d",&martix[x][y]);
 53         }
 54     } 
 55     
 56     
 57 
 58     int ans = 0;//统计块数
 59     
 60     for(int x=0;x<n;x++){
 61         for(int y=0;y<m;y++){
 62             //如果元素为1,且未入队
 63             if(martix[x][y]==1&&hashflag[x][y]==0){
 64                 ans++;
 65                 BFS(x,y);
 66             } 
 67         } 
 68     } 
 69     
 70     printf("%d\n",ans);
 71     return 0;
 72 }
 73 
 74 
 75 void BFS(int x,int y){
 76     //BFS函数访问x,y所在的块,将该块中所有“1”的hashflag设置为1
 77     SqQueue Q;
 78     InitQueue(&Q);
 79     
 80     pos.x = x;
 81     pos.y = y;
 82     
 83     EnQueue(&Q,pos);
 84     
 85     hashflag[x][y] = 1;//记录其已经入队
 86     
 87     while(QueueEmpty(&Q)!=1){
 88         //printf("==============\n");
 89         ElemType top = DeQueue(&Q);    //取出队首元素,出队
 90         
 91         //printf("%d %d\n",top.x,top.y);
 92         for(int i = 0;i<4;i++){    //循环四次得到四个位置 
 93             int newX = top.x+X[i];
 94             int newY = top.y+Y[i];
 95             if(judge(newX,newY)){
 96                 //如果新位置需要访问
 97                 pos.x = newX;
 98                 pos.y = newY;
 99                 
100                 //入队
101                 EnQueue(&Q,pos);
102                 
103                 hashflag[newX][newY] = 1;//设置该位置已经入队了,防止走回头路 
104                  
105             }    
106         }         
107     }     
108 }
109 
110 
111 void InitQueue(SqQueue *Q){
112     //构造一个空的队列 
113     (*Q).base = (ElemType*)malloc(MAX_SIZE*sizeof(ElemType));
114     if(!(*Q).base) {
115         exit(1);
116     }
117     Q->front = Q->rear = 0;
118 }
119 
120 int QueueEmpty(SqQueue *Q){
121     //若队列Q为空队列,则返回1;否则返回0
122     if(Q->front == Q->rear){
123         //printf("-------------------------\n");
124         return 1;
125     }else{
126         return 0;
127     }
128 }
129 
130 ElemType GetHead(SqQueue *Q){
131     //若队列Q非空,则返回队列头元素
132     if(Q->front != Q->rear){
133         return Q->base[Q->front];
134     }
135 }
136 
137 int EnQueue(SqQueue *Q,ElemType e){
138     //进队元素e
139     if((Q->rear+1)%MAX_SIZE==Q->front){
140         return 0;
141     }
142     Q->base[Q->rear] = e;
143     Q->rear = (Q->rear+1)%MAX_SIZE;
144     return 1;
145     
146 }
147 
148 
149 ElemType DeQueue(SqQueue *Q){
150     ElemType e;
151     if(Q->rear != Q->front){
152 
153         e = Q->base[Q->front];
154         Q->front = (Q->front+1)%MAX_SIZE;
155         return  e;
156     }
157     
158 }
159 
160 int judge(int x,int y){    //判断坐标x,y是否需要访问处理 
161     //如果出界,返回0,不需要进一步访问
162     if(x>=n||x<0||y>=m||y<0){
163         return 0;
164     }
165     //或者已经入队或者元素为0 
166     if(martix[x][y] == 0||hashflag[x][y] == 1){
167         return 0;
168     }
169     
170     return 1;    
171 }

为什么代码这么长?……,主要是因为我试着实现了一下队列的常见操作,毕竟复试的OJ上能不能用STL我还不知道呢。

所以自己顺便练练。

posted @ 2020-03-24 22:23  focusDing  阅读(326)  评论(0编辑  收藏  举报