Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 356|回复: 0

[算法学习]深度优先搜索和广度优先搜索

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-10-30 23:59:34 | 显示全部楼层 |阅读模式
    一、深度优先搜索
         深度优先搜索就是在搜索树的每一层始终先只扩展一个子节点,不断地向纵深前进直到不能再前进(到达叶子节点或受到深度限制)时,才从当前节点返回到上一级节点,沿另一方向又继续前进。这种方法的搜索树是从树根开始一枝一枝逐渐形成的。

           深度优先搜索亦称为纵向搜索。由于一个有解的问题树可能含有无穷分枝,深度优先搜索如果误入无穷分枝(即深度无限),则不可能找到目标节点。所以,深度优先搜索策略是不完备的。另外,应用此策略得到的解不一定是最佳解(最短路径)。

    二、    重排九宫问题游戏
    在一个3乘3的九宫中有1-8的8个数及一个空格随机摆放在其中的格子里。如下面左图所示。现在要求实现这样的问题:将该九宫调整为如下图右图所示的形式。调整规则是:每次只能将与空格(上,下或左,右)相临的一个数字平移到空格中。试编程实现。

    | 2 | 8  | 3 |                 | 1 | 2 | 3 |
    -
    | 1 |     | 4 |                 | 8 |    | 4 |

    | 7 | 6  | 5 |                 | 7 | 6 | 5 |

    深度优先搜索的路径示意图:


      
       
      
       
       
       

       
      
      
      
       
      
        三、广度优先搜索     在深度优先搜索算法中,是深度越大的结点越先得到扩展。如果在搜索中把算法改为按结点的层次进行搜索, 本层的结点没有搜索处理完时,不能对下层结点进行处理,即深度越小的结点越先得到扩展,也就是说先产生 的结点先得以扩展处理,这种搜索算法称为广度优先搜索法。
      广度优先搜索路径示意图:

        四、航班问题(来自《The Art of java》)
         一位顾客要预定一张从New York到Los Angeles的航班机票,下面是航班线路,请你为顾客找一种购票方案。

      

      
      
       
        航班
       
      
       
        距离
       
      
      
      New York到Chicago
      
       
        900英里
       
      
      
      Chicago到Denver
      
       
        1000英里
       
      
      
      New York到Toronto
      
       
        500英里
       
      
      
      New York到Denver  
      
       
        1800英里
       
      
      
      Toronto到Calgary
      
       
        1700英里
       
      
      
      Toronto到Los Angeles  
      
       
        2500英里
       
      
      
      Toronto到Chicago
      
       
        500英里
       
      
      
      Denver到Urbana
      
       
        1000英里
       
      
      
      Denver到Houston
      
       
        1000英里
       
      
      
      Houston到Los Angeles  
      
       
        1500英里
       
      
      
      Denver到Los Angeles  
      
       
        1000英里
       
      
    下面是用深度优先搜索求解的程序:
    // Find connections using a depth-first search.
    import java.util.*;
    import java.io.*;
    // Flight information.
    class FlightInfo {
      String from;
      String to;
      int distance;
      boolean skip; // used in backtracking
      FlightInfo(String f, String t, int d) {
        from = f;
        to = t;
        distance = d;
        skip = false;
      }
    }
    class Depth {
      final int MAX = 100;
      // This array holds the flight information.
      FlightInfo flights[] = new FlightInfo[MAX];
      int numFlights = 0; // number of entries in flight array
      Stack btStack = new Stack(); // backtrack stack
      public static void main(String args[])
      {
       
        String to, from;
        Depth ob = new Depth();
        BufferedReader br = new
          BufferedReader(new InputStreamReader(System.in));

        ob.setup();  
        try {
          System.out.print("From? ");
          from = br.readLine();
          System.out.print("To? ");
          to = br.readLine();
          ob.isflight(from, to);
          if(ob.btStack.size() != 0)
            ob.route(to);
        } catch (IOException exc) {
          System.out.println("Error on input.");
        }
      }
      
      // Initialize the flight database.
      void setup()
      {
        addFlight("New York", "Chicago", 900);
        addFlight("Chicago", "Denver", 1000);
        addFlight("New York", "Toronto", 500);
        addFlight("New York", "Denver", 1800);
        addFlight("Toronto", "Calgary", 1700);
        addFlight("Toronto", "Los Angeles", 2500);
        addFlight("Toronto", "Chicago", 500);
        addFlight("Denver", "Urbana", 1000);
        addFlight("Denver", "Houston", 1000);
        addFlight("Houston", "Los Angeles", 1500);
        addFlight("Denver", "Los Angeles", 1000);
      }
      
      // Put flights into the database.
      void addFlight(String from, String to, int dist)
      {
      
        if(numFlights < MAX) {
          flights[numFlights] =
            new FlightInfo(from, to, dist);
          numFlights++;
        }
        else System.out.println("Flight database full.
    ");
      }
      // Show the route and total distance.
      void route(String to)
      {
        Stack rev = new Stack();
        int dist = 0;
        FlightInfo f;
        int num = btStack.size();
        // Reverse the stack to display route.
        for(int i=0; i < num; i++)
          rev.push(btStack.pop());
        for(int i=0; i < num; i++) {
          f = (FlightInfo) rev.pop();
          System.out.print(f.from + " to ");
          dist += f.distance;
        }
        System.out.println(to);
        System.out.println("Distance is " + dist);
      }
      /* If there is a flight between from and to,
         return the distance of flight;
         otherwise, return 0. */
      int match(String from, String to)
      {
        for(int i=numFlights-1; i > -1; i--) {
          if(flights.from.equals(from) &&
             flights.to.equals(to) &&
             !flights.skip)
          {
            flights.skip = true; // prevent reuse
            return flights.distance;
          }
        }
        return 0; // not found
      }
      
      // Given from, find any connection.
      FlightInfo find(String from)
      {
        for(int i=0; i < numFlights; i++) {
          if(flights.from.equals(from) &&
             !flights.skip)
          {
            FlightInfo f = new FlightInfo(flights.from,
                                 flights.to,
                                 flights.distance);
            flights.skip = true; // prevent reuse
            return f;
          }
        }
        return null;
      }
      
      // Determine if there is a route between from and to.
      void isflight(String from, String to)
      {
        int dist;
        FlightInfo f;
        // See if at destination.
        dist = match(from, to);
        if(dist != 0) {
          btStack.push(new FlightInfo(from, to, dist));
          return;
        }
        // Try another connection.
        f = find(from);
        if(f != null) {
          btStack.push(new FlightInfo(from, to, f.distance));
          isflight(f.to, to);
        }
        else if(btStack.size() > 0) {
          // Backtrack and try another connection.
          f = (FlightInfo) btStack.pop();
          isflight(f.from, f.to);
        }
      }
    }  
      [/code]   解释:isflight()方法用递归方法进行深度优先搜索,它先调用match()方法检查航班的数据库,判断在from和to之间有没有航班可达。如果有,则获取目标信息,并将该线路压入栈中,然后返回(找到一个方案)。否则,就调用find()方法查找from与任意其它城市之间的线路,如果找到一条就返回描述该线路的FlightInfo对象,否则返回null。如果存在这样的一条线路,那么就把该线路保存在f中,并将当前航班信息压到栈的顶部,然后递归调用isflight()方法 ,此时保存在f.to中的城市成为新的出发城市.否则就进行回退,弹出栈顶的第一个节点,然后递归调用isflight()方法。该过程将一直持续到找到目标为止。     程序运行结果:
    C:java>java Depth
    From? New York
    To? Los Angeles
    New York to Chicago to Denver to Los Angeles
    Distance is 2900 C:java>      深度优先搜索能够找到一个解,同时,对于上面这个特定问题,深度优先搜索没有经过回退,一次就找到了一个解;但如果数据的组织方式不同,寻找解时就有可能进行多次回退。因此这个例子的输出并不具有普遍性。而且,在搜索一个很长,但是其中并没有解的分支的时候,深度优先搜索的性能将会很差,在这种情况下,深度优先搜索不仅在搜索这条路径时浪费时间,而且还在向目标的回退中浪费时间。  再看对这个例子使用广度优先搜索的程序:
    1. // Find connections using a breadth-first search.
    2. import java.util.*;
    3. import java.io.*;
    4. // Flight information.
    5. class FlightInfo {
    6.   String from;
    7.   String to;
    8.   int distance;
    9.   boolean skip; // used in backtracking
    10.   FlightInfo(String f, String t, int d) {
    11.     from = f;
    12.     to = t;
    13.     distance = d;
    14.     skip = false;
    15.   }
    16. }
    17. class Breadth {
    18.   final int MAX = 100;
    19.   // This array holds the flight information.
    20.   FlightInfo flights[] = new FlightInfo[MAX];
    21.   int numFlights = 0; // number of entries in flight array
    22.   Stack btStack = new Stack(); // backtrack stack
    23.   public static void main(String args[])
    24.   {
    25.     String to, from;
    26.     Breadth ob = new Breadth();
    27.     BufferedReader br = new
    28.       BufferedReader(new InputStreamReader(System.in));

    29.     ob.setup();  
    30.     try {
    31.       System.out.print("From? ");
    32.       from = br.readLine();
    33.       System.out.print("To? ");
    34.       to = br.readLine();
    35.       ob.isflight(from, to);
    36.       if(ob.btStack.size() != 0)
    37.         ob.route(to);
    38.     } catch (IOException exc) {
    39.       System.out.println("Error on input.");
    40.     }
    41.   }
    42.   
    43.   // Initialize the flight database.
    44.   void setup()
    45.   {
    46.     addFlight("New York", "Chicago", 900);
    47.     addFlight("Chicago", "Denver", 1000);
    48.     addFlight("New York", "Toronto", 500);
    49.     addFlight("New York", "Denver", 1800);
    50.     addFlight("Toronto", "Calgary", 1700);
    51.     addFlight("Toronto", "Los Angeles", 2500);
    52.     addFlight("Toronto", "Chicago", 500);
    53.     addFlight("Denver", "Urbana", 1000);
    54.     addFlight("Denver", "Houston", 1000);
    55.     addFlight("Houston", "Los Angeles", 1500);
    56.     addFlight("Denver", "Los Angeles", 1000);
    57.   }
    58.   
    59.   // Put flights into the database.
    60.   void addFlight(String from, String to, int dist)
    61.   {  
    62.     if(numFlights < MAX) {
    63.       flights[numFlights] =
    64.         new FlightInfo(from, to, dist);
    65.       numFlights++;
    66.     }
    67.     else System.out.println("Flight database full.
    68. ");
    69.   }
    70.   // Show the route and total distance.
    71.   void route(String to)
    72.   {
    73.     Stack rev = new Stack();
    74.     int dist = 0;
    75.     FlightInfo f;
    76.     int num = btStack.size();
    77.     // Reverse the stack to display route.
    78.     for(int i=0; i < num; i++)
    79.       rev.push(btStack.pop());
    80.     for(int i=0; i < num; i++) {
    81.       f = (FlightInfo) rev.pop();
    82.       System.out.print(f.from + " to ");
    83.       dist += f.distance;
    84.     }
    85.     System.out.println(to);
    86.     System.out.println("Distance is " + dist);
    87.   }
    88.   /* If there is a flight between from and to,
    89.      return the distance of flight;
    90.      otherwise, return 0. */
    91.   int match(String from, String to)
    92.   {
    93.     for(int i=numFlights-1; i > -1; i--) {
    94.       if(flights[i].from.equals(from) &&
    95.          flights[i].to.equals(to) &&
    96.          !flights[i].skip)
    97.       {
    98.         flights[i].skip = true; // prevent reuse
    99.         return flights[i].distance;
    100.       }
    101.     }
    102.     return 0; // not found
    103.   }
    104.   
    105.   // Given from, find any connection.
    106.   FlightInfo find(String from)
    107.   {
    108.     for(int i=0; i < numFlights; i++) {
    109.       if(flights[i].from.equals(from) &&
    110.          !flights[i].skip)
    111.       {
    112.         FlightInfo f = new FlightInfo(flights[i].from,
    113.                              flights[i].to,
    114.                              flights[i].distance);
    115.         flights[i].skip = true; // prevent reuse
    116.         return f;
    117.       }
    118.     }
    119.     return null;
    120.   }
    121.   
    122.   /* Determine if there is a route between from and to
    123.      using breadth-first search. */
    124.   void isflight(String from, String to)
    125.   {
    126.     int dist, dist2;
    127.     FlightInfo f;
    128.     // This stack is needed by the breadth-first search.
    129.     Stack resetStck = new Stack();
    130.     // See if at destination.
    131.     dist = match(from, to);
    132.     if(dist != 0) {
    133.       btStack.push(new FlightInfo(from, to, dist));
    134.       return;
    135.     }
    136.     /* Following is the first part of the breadth-first
    137.        modification.  It checks all connecting flights
    138.        from a specified node. */
    139.     while((f = find(from)) != null) {
    140.       resetStck.push(f);
    141.       if((dist = match(f.to, to)) != 0) {
    142.         resetStck.push(f.to);
    143.         btStack.push(new FlightInfo(from, f.to, f.distance));
    144.         btStack.push(new FlightInfo(f.to, to, dist));
    145.         return;
    146.       }
    147.     }
    148.     /* The following code resets the skip fields set by
    149.        preceding while loop. This is also part of the
    150.        breadth-first modifiction. */
    151.     int i = resetStck.size();
    152.     for(; i!=0; i--)
    153.       resetSkip((FlightInfo) resetStck.pop());
    154.     // Try another connection.
    155.     f = find(from);
    156.     if(f != null) {
    157.       btStack.push(new FlightInfo(from, to, f.distance));
    158.       isflight(f.to, to);
    159.     }
    160.     else if(btStack.size() > 0) {
    161.       // Backtrack and try another connection.
    162.       f = (FlightInfo) btStack.pop();
    163.       isflight(f.from, f.to);
    164.     }
    165.   }
    166.   // Reset skip field of specified flight.
    167.   void resetSkip(FlightInfo f) {
    168.     for(int i=0; i< numFlights; i++)
    169.       if(flights[i].from.equals(f.from) &&
    170.          flights[i].to.equals(f.to))
    171.            flights[i].skip = false;
    172.   }
    173. }
    复制代码
    程序运行结果:

    C:java>java Breadth
    From? New York
    To? Los Angeles
    New York to Toronto to Los Angeles
    Distance is 3000 C:java> 它找到了一个合理的解,但这不具有一般性。因为找到的第一条路径取决于信息的物理组织形式。     如果目标在搜索空间中隐藏得不是太深,那么广度优先搜索的性能会很好。

      
      
       
       

         
       

         
       
      



    源码下载:http://file.javaxxz.com/2014/10/30/235934546.zip
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-25 19:02 , Processed in 0.361091 second(s), 48 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表