利用广度优先搜索(BFS)与深度优先搜索(DFS)实现岛屿个数的问题(java)
需要说明一点,要成功运行本贴代码,需要重新复制我第一篇随笔《简单的循环队列》代码(版本有更新)。
进入今天的主题。
今天这篇文章主要探讨广度优先搜索(BFS)结合队列和深度优先搜索(DFS)结合栈的示例应用。
一、队列和 BFS
众所周知,广度优先搜索(BFS)最为广泛使用场景是找出从根结点到目标结点的最短路径,而
结点的处理顺序与添加到队列的顺序是完全相同的顺序,即先进先出(FIFO)。
这就是我们在 BFS 中使用队列的原因。
二、栈和DFS
深度优先搜索(DFS),与 BFS 类似,也可用于查找从根结点到目标结点的路径。(请记住,是路径,但不是最短路径)
当我们到达最深的结点 时,我们需要回溯。当我们回溯时,我们将从栈中弹出最深结点
,这实际上是推入到栈中的最后一个结点
。
结点的处理顺序是完全相反的顺序
,就像是被添加
到栈中一样,它是后进先出(LIFO)。这就是我们在 DFS 中使用栈的原因。
以上分别说明了使用在BFS中使用队列与在DFS中使用栈的原因,下面展示一示例说明其应用。
例:给定一个由 land
(陆地)和 sea
(海水)组成的的二维网格,计算岛屿的数量。一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设网格的四个边均被水包围
设计思路:通过BFS找出所有的land存入哈希表中,然后对其排序,最后通过DFS递归完成岛屿的统计。(其实本题不用这么复杂,直接递归即可,但为了阐述BFS和DFS,带此目的找了这个例题一起应用求解)。
测试用例为:
- iSea iSea iSea iSea iSea iSea iSea
- iSea Land iSea iSea Land iSea iSea
- iSea Land Land iSea iSea iSea iSea
- iSea iSea iSea Land iSea iSea iSea
- iSea Land iSea Land Land Land iSea
- iSea iSea iSea iSea iSea iSea iSea
- 岛屿的数量为:4
贴上源码(如只是阅读只看Main应该是可以理解):
1. IConnectable可连接器
- package com.chengcai.util;
- /**
- * Created by chengcai on 2019/3/14.
- */
- public interface IConnectable<T> {
- Connector<T> connector();
- }
- package com.chengcai.util;
- /**
- * Created by chengcai on 2019/3/14.
- */
- public class Connector<T> {
- public boolean isConnect=false;
- public Connector()
- {
- isConnect=true;
- }
- public boolean hasNext()
- {
- return isConnect;
- }
- }
- package com.chengcai.util;
- /**
- * Created by chengcai on 2019/3/18.
- */
- public interface Ilivable {
- }
- 2.抽象地表对象AbstractEarthSurface
- package com.chengcai.util;
- import java.util.ArrayList;
- import java.util.List;
- /**
- * Created by chengcai on 2019/3/18.
- */
- public abstract class AbstractEarthSurface {
- public static int HashCode=1;
- private int icon=0;
- private AbstractEarthSurface right=null;
- private AbstractEarthSurface down=null;
- private AbstractEarthSurface left=null;
- private AbstractEarthSurface up=null;
- int row=0;
- int col=0;
- private String name;
- private List<AbstractEarthSurface> list=new ArrayList<AbstractEarthSurface>();
- public AbstractEarthSurface getRight()
- {
- return right;
- }
- public AbstractEarthSurface getDown()
- {
- return down;
- }
- public AbstractEarthSurface getLeft(){return left;}
- public AbstractEarthSurface getUp(){return up;}
- public String getName()
- {
- return name;
- }
- public int getIcon(){return icon;}
- public void setIcon(int s){
icon=s;- }
- public int getRow() {
- return row;
- }
- public int getCol(){
- return col;
- }
- public void setRow(int r){
- row=r;
- }
- public void setCol(int c){
- col=c;
- }
- public void setRight(AbstractEarthSurface r)
- {
- if(r==null)
- return;
- list.add(r);
- right=r;
- }
- public void setDown(AbstractEarthSurface d)
- {
- if (d==null)
- return;
- list.add(d);
- down=d;
- }
- public void setLeft(AbstractEarthSurface l)
- {
- if(l==null)
- return;
- left=l;
- }
- public void setUp(AbstractEarthSurface u)
- {
- if(u==null)
- return;
- up=u;
- }
- public List<AbstractEarthSurface> getList()
- {
- return list;
- }
- }
- 3.定义统一对外操作对象Map,分别可操作sea,land,island对象
- package com.chengcai.util;
- import java.util.ArrayList;
- import java.util.Hashtable;
- import java.util.List;
- /**
- * Created by chengcai on 2019/3/14.
- */
- public class Map
- {
private AbstractEarthSurface[][] map = null;- private island ild=null;
- public Map() {
- }
- public AbstractEarthSurface getLand() {
- return new Land();
- }
- public AbstractEarthSurface getSea() {
- return new Sea();
- }
- public island getIsland()
- {
- if (ild==null) {
- ild= new island();
- }
- return ild;
- }
- public void setMap(AbstractEarthSurface[][] imap)
- {
- map=imap;
- }
- public AbstractEarthSurface[][] getMap()
- {
- return this.map;
- }
- public class Land extends AbstractEarthSurface implements IConnectable
- {
- private int icon=1;
- public Land()
- {
- }
- public Connector connector()
- {
- return new Connector();
- }
- @Override
- public String getName()
- {
- return "Land";
- }
- @Override
- public void setIcon(int s)
- {
- icon=s;
- }
- @Override
- public int getIcon()
- {
- return icon;
- }
- }
- public class Sea extends AbstractEarthSurface
- {
- private int icon=0;
- public Sea()
- {
- }
- @Override
- public String getName()
- {
- return "iSea";
- }
- @Override
- public void setIcon(int s)
- {
- icon=s;
- }
- @Override
- public int getIcon()
- {
- return icon;
- }
- }
- public class island implements Ilivable
- {
- Hashtable<Integer,AbstractEarthSurface> islandList=null;
- Hashtable<String,AbstractEarthSurface> coordinate=null;
- List<AbstractEarthSurface> tempList=null;
- public island()
- {
- islandList=new Hashtable<Integer,AbstractEarthSurface>();
- tempList=new ArrayList();
- }
- public void addCoordinateHashTable(int r,int c,AbstractEarthSurface es)
- {
- if (coordinate==null)
- coordinate=new Hashtable<String,AbstractEarthSurface>();
- this.coordinate.put(Integer.toString(r)+Integer.toString(c),es);
- }
- public AbstractEarthSurface getEarthSurface(int r, int c)
- {
- return this.coordinate.get(Integer.toString(r)+Integer.toString(c));
- }
- public boolean isRowLastElement(String str,List<String> sls)
- {
- int index;
- index=sls.indexOf(str)+1;
- if(index>sls.size()-1)
- return true;
- return this.coordinate.get(str).getRow()< this.coordinate.get(sls.get(index)).getRow();
- }
- public Hashtable<String,AbstractEarthSurface> getCoordinateHashtable()
- {
- if (coordinate==null)
- coordinate=new Hashtable<String,AbstractEarthSurface>();
- return this.coordinate;
- }
- public void Put(Integer hash, AbstractEarthSurface es)
- {
- if (!(es instanceof IConnectable))
- return;
- this.islandList.put(hash,es);
- }
- public void remove()
- {
- this.islandList.remove(this);
- }
- public Hashtable getIsland()
- {
- return this.islandList;
- }
- public void Add(AbstractEarthSurface es)
- {
- if (!(es instanceof IConnectable))
- return;
- this.tempList.add(es);
- }
- public void ClearTemp()
- {
- if (tempList ==null )
- return;
- this.tempList.clear();
- }
- public List<AbstractEarthSurface> getTempList()
- {
- return this.tempList;
- }
}- }
- 4.主函数
- package com.chengcai;
- import com.chengcai.util.*;
- import com.chengcai.util.Map;
- import java.util.*;
- public class Main {
- //初始化测试用例
- private static Map initMap()
- {
- Map map=new Map();
- AbstractEarthSurface[]d1 ={map.getSea(),map.getSea(),map.getSea(),map.getSea(),
- map.getSea(),map.getSea(),map.getSea()};
- AbstractEarthSurface[]d2 ={map.getSea(),map.getLand(),map.getSea(),map.getSea(),map.getLand(),
- map.getSea(),map.getSea()};
- AbstractEarthSurface[]d3 ={map.getSea(),map.getLand(),map.getLand(),map.getSea(),
- map.getSea(),map.getSea(),map.getSea()};
- AbstractEarthSurface[]d4 ={map.getSea(),map.getSea(),map.getSea(),map.getLand(),
- map.getSea(),map.getSea(),map.getSea()};
- AbstractEarthSurface[]d5 ={map.getSea(),map.getLand(),map.getSea(),map.getLand(),
- map.getLand(),map.getLand(),map.getSea()};
- AbstractEarthSurface[]d6 ={map.getSea(),map.getSea(),map.getSea(),map.getSea(),
- map.getSea(),map.getSea(),map.getSea()};
- AbstractEarthSurface [][] data=new AbstractEarthSurface[6][7];
- for (int i=0;i<6;i++)
- {
- for(int j=0;j<7;j++)
- {
if (i==0) {- data[i][j] = d1[j];
- data[i][j].setUp(null);
- if (j>0)
- data[i][j].setLeft(data[i][j-1]);
- if (j+1<7)
- data[i][j].setRight(d1[j+1]);
- data[i][j].setDown(d2[j]);
- }
- if (i==1) {
- data[i][j] = d2[j];
- data[i][j].setUp(data[i-1][j]);
- if (j>0)
- data[i][j].setLeft(data[i][j-1]);
- if (j+1<7)
- data[i][j].setRight(d2[j+1]);
- data[i][j].setDown(d3[j]);
- }
- if (i==2) {
- data[i][j] = d3[j];
- data[i][j].setUp(data[i-1][j]);
- if (j>0)
- data[i][j].setLeft(data[i][j-1]);
- if (j+1<7)
- data[i][j].setRight(d3[j+1]);
- data[i][j].setDown(d4[j]);
- }
- if (i==3) {
- data[i][j] = d4[j];
- data[i][j].setUp(data[i-1][j]);
- if (j>0)
- data[i][j].setLeft(data[i][j-1]);
- if (j+1<7)
- data[i][j].setRight(d4[j+1]);
- data[i][j].setDown(d5[j]);
- }
- if (i==4) {
- data[i][j] = d5[j];
- data[i][j].setUp(data[i-1][j]);
- if (j>0)
- data[i][j].setLeft(data[i][j-1]);
- if (j+1<7)
- data[i][j].setRight(d5[j+1]);
- data[i][j].setDown(d6[j]);
- }
- if (i==5) {
- data[i][j] = d6[j];
- data[i][j].setUp(data[i-1][j]);
- if (j>0)
- data[i][j].setLeft(data[i][j-1]);
- if (j+1<7)
- data[i][j].setRight(d6[j+1]);
- data[i][j].setDown(null);
- }
- data[i][j].setRow(i);
- data[i][j].setCol(j);
- }
- }
- map.setMap(data);
- return map;
- }
- private static int getIslandNumBFS(ICircleQueue q,Map map)
- {
- AbstractEarthSurface[][] data=map.getMap();
- List<AbstractEarthSurface> cacheList=new ArrayList<AbstractEarthSurface>();
- //用队列辅助实现广度优先查找所有Land
- q.enQueue(data[0][0]);
- while (!q.isEmpty())
- {
- int head=q.getQueueEntity().getHead();
- AbstractEarthSurface queueFirstElement=(AbstractEarthSurface)q.getQueueEntity().getListCollection().get(head);
- if (queueFirstElement instanceof IConnectable & !(map.getIsland().getCoordinateHashtable().containsValue(queueFirstElement))){
- map.getIsland().addCoordinateHashTable(queueFirstElement.getRow(),queueFirstElement.getCol(),queueFirstElement);
- }
- for (AbstractEarthSurface obj:queueFirstElement.getList()) {
- cacheList.add(obj);
- }
- Iterator<AbstractEarthSurface> it =cacheList.iterator();
- while (it.hasNext())
- {
- if (q.enQueue(it.next()))
- it.remove();
- }
- q.deQueue();
- }
- //对结果排序,便于AbstractEarthSurface.HashCode哈希值计算
- Hashtable<String,AbstractEarthSurface> ht=map.getIsland().getCoordinateHashtable();
- List<String> li=new ArrayList<String>(ht.keySet());
- li.sort(new Comparator<String>() {
@Override- public int compare(String o1, String o2) {
- return o1.compareTo(o2);
- }
- });
- for (String str:li) {
- if (ht.get(str).getIcon()==1)
- {
- AbstractEarthSurface.HashCode++;
- getIslandConnected(ht.get(str));
- map.getIsland().Put(AbstractEarthSurface.HashCode, ht.get(str));
- }
- }
- return map.getIsland().getIsland().keySet().size();
- }
- //递归实现标识已访问的对象
- private static void getIslandConnected(AbstractEarthSurface es)
- {
- if((es==null) || !(es instanceof IConnectable) || (es.getIcon()==3))
- return;
- es.setIcon(3);
- getIslandConnected(es.getRight());
- getIslandConnected(es.getLeft());
- getIslandConnected(es.getUp());
- getIslandConnected(es.getDown());
- }
- private static void printResult(Map map,int IslandCount)
- {
- AbstractEarthSurface[][] printMap=map.getMap();
- StringBuilder sb =new StringBuilder();
- for(int i=0;i<printMap.length;i++)
- {
- for (int j=0;j<printMap[0].length;j++)
- {
- sb.append(printMap[i][j].getName() +" ");
- if (j==printMap[0].length-1)
- sb.append("\n\r");
- }
- }
- System.out.print("测试用例为:"+"\n\r");
- System.out.print(sb.toString());
- System.out.print("岛屿的数量为:"+ IslandCount +"\n\r");
- }
- public static void main(String[] args) {
- Map map=null;
- int islandNums=0;
- ICircleQueue<AbstractEarthSurface> q=new CircleQueue<AbstractEarthSurface>();
- map=initMap();
- islandNums=getIslandNumBFS(q,map);
- printResult(map,islandNums);
- }
- }
- 5.运行结果:
- 测试用例为:
- iSea iSea iSea iSea iSea iSea iSea
- iSea Land iSea iSea Land iSea iSea
- iSea Land Land iSea iSea iSea iSea
- iSea iSea iSea Land iSea iSea iSea
- iSea Land iSea Land Land Land iSea
- iSea iSea iSea iSea iSea iSea iSea
- 岛屿的数量为:4
利用广度优先搜索(BFS)与深度优先搜索(DFS)实现岛屿个数的问题(java)的更多相关文章
- matlab练习程序(广度优先搜索BFS、深度优先搜索DFS)
如此经典的算法竟一直没有单独的实现过,真是遗憾啊. 广度优先搜索在过去实现的二值图像连通区域标记和prim最小生成树算法时已经无意识的用到了,深度优先搜索倒是没用过. 这次单独的将两个算法实现出来,因 ...
- (转)广度优先搜索BFS和深度优先搜索DFS
1. 广度优先搜索介绍 广度优先搜索算法(Breadth First Search),又称为"宽度优先搜索"或"横向优先搜索",简称BFS. 它的思想是:从图中 ...
- 广度优先遍历-BFS、深度优先遍历-DFS
广度优先遍历-BFS 广度优先遍历类似与二叉树的层序遍历算法,它的基本思想是:首先访问起始顶点v,接着由v出发,依次访问v的各个未访问的顶点w1 w2 w3....wn,然后再依次访问w1 w2 w3 ...
- 广度优先算法(BFS)与深度优先算法(DFS)
一.广度优先算法BFS(Breadth First Search) 基本实现思想 (1)顶点v入队列. (2)当队列非空时则继续执行,否则算法结束. (3)出队列取得队头顶点v: (4)查找顶点v的所 ...
- 数据结构和算法总结(一):广度优先搜索BFS和深度优先搜索DFS
前言 这几天复习图论算法,觉得BFS和DFS挺重要的,而且应用比较多,故记录一下. 广度优先搜索 有一个有向图如图a 图a 广度优先搜索的策略是: 从起始点开始遍历其邻接的节点,由此向外不断扩散. 1 ...
- 广度优先搜索(BFS)与深度优先搜索(DFS)的对比及优缺点
深搜,顾名思义,是深入其中.直取结果的一种搜索方法. 如果深搜是一个人,那么他的性格一定倔得像头牛!他从一点出发去旅游,只朝着一个方向走,除非路断了,他绝不改变方向!除非四个方向全都不通或遇到终点,他 ...
- 采用邻接矩阵表示图的深度优先搜索遍历(与深度优先搜索遍历连通图的递归算法仅仅是DFS的遍历方式变了)
//采用邻接矩阵表示图的深度优先搜索遍历(与深度优先搜索遍历连通图的递归算法仅仅是DFS的遍历方式变了) #include <iostream> using namespace std; ...
- 广度优先(bfs)和深度优先搜索(dfs)的应用实例
广度优先搜索应用举例:计算网络跳数 图结构在解决许多网络相关的问题时直到了重要的作用. 比如,用来确定在互联网中从一个结点到另一个结点(一个网络到其他网络的网关)的最佳路径.一种建模方法是采用无向图, ...
- 搜索与图论①-深度优先搜索(DFS)
深度优先搜索(DFS) 例题一(指数型枚举) 把 1∼n 这 n 个整数排成一行后随机打乱顺序,输出所有可能的次序. 输入格式 一个整数 n. 输出格式 按照从小到大的顺序输出所有方案,每行 1 个. ...
随机推荐
- 2059 - Authentication plugin 'caching_sha2_password' cannot be loaded: dlopen(../Frameworks/caching_sha2_password.so, 2): image not found
mac本地安装mysql后,navicat连接报错: - Authentication plugin ): image not found 解决方法 在控制台登陆后重新改下密码即可 ALTER USE ...
- UnicodeDecodeError: 'ascii' codec can't decode byte 0xa0 in position 0: ordinal not in range(128)
- HDU - 3247 Resource Archiver (AC自动机,状压dp)
\(\quad\)Great! Your new software is almost finished! The only thing left to do is archiving all you ...
- 51nod1556 计算(默慈金数)
Problem 有一个\(1*n\)的矩阵,固定第一个数为\(1\),其他填正整数, 且相邻数的差不能超过\(1\),求方案数. \(n\le 10^6\) Solution 容易发现答案是\(f_n ...
- ant 执行jmeter
构建-invoke ant -properties jmeter.home=/home/userapp/apps/apache-jmeter-5.0report.title=kyh_register_ ...
- 新系统添加sshkey/pexpect基本使用
Ansible密码认证 //配置Inventory [db] 10.10.10.12 10.10.10.162 [db:vars] #给db组下的主机设置变量 ansible_ssh_user=&qu ...
- Entity Framework系列教程汇总
翻译自http://www.entityframeworktutorial.net/,使用EF几年时间了,一直没有系统总结过,所以翻译这一系统文章作为总结,由于英语功底有限,翻译的可能有些问题,欢迎指 ...
- Ubuntu屏幕分辨率无1920 1080
xrandr 没有1920X1080分辨率,所以手动添加一个1080P分辨率,先输入“cvt 1920 1080”命令,查询一下1080P分辨率的有效扫描频率 然后 sudo xrandr --new ...
- MATLAB cftool工具数据拟合结果好坏判断
SSE和RMSE比较小 拟合度R接近于1较好 * 统计参数模型的拟合优度 1.误差平方和(SSE) 2. R-Square(复相关系数或复测定系数) 3. Adjusted R-Square(调整自由 ...
- 解析中国天气网页面获取七日天气 (Java, Python)
说明 解析中国天气网的页面,获取七日天气. 使用 htmlparser .这是它的 API 文档. 代码 SevenDayWeather.java import java.io.BufferedRea ...