深度优先搜索算法

 

学自《ANDROID_2.0游戏开发实战宝典》

 

深度优先路径搜索

 

深度优先搜索DFS在搜索过程中不考虑各个边的开销,只考虑路径的选择。其思路是站在一个连通图的点上,然后尽可能沿着一条边深入,当遇到死胡同就进行回溯,然后继续搜索,直到找到目标为止。

 

 

 

 

 

直接上例子,例子中注释有详细说明:

MapList.java

package com.liangbinny.my;

public class MapList {
    public static int[] source={1,1};//出发点
    public static int[][] target={//目标点坐标数组
        {5,4}
    };
    public static int[][] map = new int[][] //地图数组 , 1表示不可达区域
    {
        {1,1,1,1,1,1,1},
        {1,0,0,0,0,0,1},
        {1,1,0,1,1,0,1},
        {1,1,0,0,1,0,1},
        {1,1,1,1,0,0,1},
        {1,1,1,1,0,1,1},
        {1,1,1,1,1,1,1}
    };
}

 

 

深搜例子DFS.java

package com.liangbinny.my;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Stack;


/**
 * <p><b>
 * 深度优先搜索算法 (depth first search)
 * 算法原理是:从原点出发,尽可能沿着一条边深入,
 * 当遇到叶子结点(顶结点)就进行回溯,然后继续搜索,直到找到目标为止
 * 主要利用栈(Stack),利用栈的先进后出的原理,深度依次搜索,利用栈来存储待访问的边
 * </b></p>
 */
public class DFS {
    int[] source = MapList.source; //出发点
    int[] target = MapList.target[0]; //目标点
    Stack<int[][]> stack = new Stack<int[][]>();  //深度优先所用栈,栈里存放的是边,两相邻点作为一条边
    int[][] visited = new int[MapList.map.length][MapList.map[0].length];
    ArrayList<int[][]> searchProcess=new ArrayList<int[][]>();//搜索过程
    HashMap<String,int[][]> hm=new HashMap<String,int[][]>();//结果路径记录
   
    //这个就是记录一个点的8个方向的点
    int[][] sequence={
        {0,1},{0,-1},
        {-1,0},{1,0},
        {-1,1},{-1,-1},
        {1,-1},{1,1}
    };
   
    int[][] map = MapList.map;
   
    public void calcDFS(){  //深度优先算法
        int[][] start = {  //开始状态
            {source[0],source[1]},
            {source[0],source[1]}
        };
        stack.push(start);
        while(true){
            int[][] currentEdge = stack.pop();  //从栈顶取出边
            int[] tempTarget = currentEdge[1]; //取该边的终点(起点在之前循环已经处理了,或者是原点,无须再处理)
            //判断目的点是否去过,若去过则直接进入下次循环
            if (visited[tempTarget[1]][tempTarget[0]]==1) {   //(2,3)的点,3相当于数组的行,2相当于数组的列,行列要倒置来看,要小心
                continue;
            }
            visited[tempTarget[1]][tempTarget[0]]=1;//标识目的点为访问过
            //将临时目的点加入搜索过程中,表示曾经搜索过这个点,这条边
            searchProcess.add(currentEdge);
           
            //记录此临时目的点的父节点,存储这条边
            //最终搜索到显示时,就是根据这个hashmap,从目标点出发,一直往回找寻经过的点
            hm.put(tempTarget[0]+":"+tempTarget[1], new int[][]{currentEdge[1],currentEdge[0]});
            //找到目标点
            if (tempTarget[0]==target[0]&&tempTarget[1]==target[1]) {
                break;
            }
           
            //将所有可能的边入栈.无非就是这个点的8个方向的点(sequence取),只要不是不可到达的区域(1),就都放入栈中
            //对于一个坐标指向数组,比如(13,2),x坐标13是数组里的列,y坐标2是数组里的行
            int currCol=tempTarget[0];
            int currRow=tempTarget[1];
            for(int[] rc:sequence){  //循环遍历它的8个点
                int i = rc[1];
                int j = rc[0];
                if(i==0&&j==0){continue;}  //表示无位移
                if (currRow+i>=0&&currRow+i<map.length&&currCol+j>=0&&currCol+j<map[0].length&&map[currRow+i][currCol+j]!=1) {
                    int[][] tempEdge={
                        {tempTarget[0],tempTarget[1]},
                        {currCol+j,currRow+i}
                    };
                    //因为是栈,所以是后处理,所以8个方向的点的进栈顺序是{0,1},{0,-1}...{1,-1},{1,1}
                    //但处理顺序是后处理,所以处理顺序是{1,1},{1,-1}...{0,-1},{0,1}
                    stack.push(tempEdge); 
                }
            }
        }
    }
   
    public static void main(String[] args) {
        DFS dfs = new DFS();
        dfs.calcDFS();  //搜索
        System.out.println("====================深度搜索过程=========================");
        //打印搜索过程路径
        ArrayList<int[][]> list = dfs.searchProcess;
        for (int[][] is : list) {
            System.out.println("start:"+is[0][0]+","+is[0][1]+";end:"+is[1][0]+","+is[1][1]);
        }
       
        System.out.println("====================最终路径=========================");
        //打印最终的结果路径
        //本质是根据搜索路径过程,原着目标点反序,只需要依次找父结点,最后得到的是原点即可
        int[] temp=dfs.target;
        while(true){
            int[][] tempA=dfs.hm.get(temp[0]+":"+temp[1]);
            System.out.println("start:"+tempA[0][0]+","+tempA[0][1]+";end:"+tempA[1][0]+","+tempA[1][1]);
            if(tempA[1][0]==dfs.source[0]&&tempA[1][1]==dfs.source[1]){//判断有否到出发点
                break;
            }
            temp=tempA[1]; 
        }
    }
}

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值