遍历算法主要用在在处理迷宫问题,图,最短路径,以及枚举所有可能等问题上。下面我们通过一个简单的例子,来入门深度优先和广度优先算法:

  1 package com.rampage.algorithm.base;
  2 
  3 import java.util.ArrayList;
  4 import java.util.LinkedHashSet;
  5 import java.util.List;
  6 import java.util.Set;
  7 
  8 /**
  9  * 相关的搜索算法实例 假设有1-9,9个数字,现在任意取三个,要求得到一共能得到多少个不同值的数字。如果可能的化输出所有可能的值。
 10  * 
 11  * @author zyq
 12  *
 13  */
 14 public class SearchAlgorithm {
 15     private static int totalCount = 0; // 存储总计数
 16     private static Set<String> results = new LinkedHashSet<String>(); // 存储所有的结果
 17 
 18     public static void main(String[] args) {
 19         deepFirstSearch();
 20         breadthFirstSearch();
 21     }
 22 
 23     /**
 24      * 广度优先搜索:广度优先搜索算法的核心是列表。首先就得到第一步可以放的所有数,然后依次将其放入列表。接下来逐个处理列表中的每个数,给出接下来可能出现的第二个数,
 25      * 处理完列表中的一个数就将该数从列表中移除。依次类推,直到待处理的列表中的元素为空。
 26      */
 27     private static void breadthFirstSearch() {
 28         totalCount = 0;
 29         results.clear();
 30         List<String> possibleList = new ArrayList<String>();
 31 
 32         // 初始化列表,开始时第一号盒子可以放入1-9
 33         for (int i = 1; i < 10; i++) {
 34             possibleList.add(i + "");
 35         }
 36 
 37         // 列表不为空的时候循环处理,因为又要增加又要删除,此时逆序遍历(此时即使用iterator,但是iterator没法删除元素,所以仍然会报错。)
 38         while (!possibleList.isEmpty()) {
 39             for (int i=possibleList.size() - 1; i>=0; i--) {
 40                 String element = possibleList.get(i);
 41                 // 长度为3说明3个数都放过了
 42                 if (element.length() == 3) {
 43                     totalCount++;
 44                     results.add(element);
 45                     possibleList.remove(i);
 46                     continue;
 47                 }
 48 
 49                 for (int j = 1; j < 10; j++) {
 50                     // 如果已经包含,则该数字不能再使用
 51                     if (element.contains(j + "")) {
 52                         continue;
 53                     } else {
 54                         // 如果没有包含对应的数字,则此时将数字加到元素后面,作为新的可能结果列表放入列表中
 55                         possibleList.add(element + j);
 56                     }
 57                 }
 58 
 59                 // 移除已经处理过的元素
 60                 possibleList.remove(i);
 61             }
 62             
 63         }
 64 
 65         System.out.println("Total count:" + totalCount);
 66         System.out.println(results);
 67     }
 68 
 69     /**
 70      * 采用深度优先算法实现:深度优先算法的核心思想是迭代。既然要迭代就应该先抽象出每一步需要重复处理的数据。 可以这样思考深度优先算法:
 71      * 假设有三个盒子,先往1号盒子放入1, 然后往2号盒子放入2,最后往3号盒子放入3.这样其实就组成了一个组合:123
 72      * 要想得到其他的组合,则必须先收回3号盒子中的3,然后放入剩下的任意一个。依次类推,当3号盒子可能的情况都放完了之后,就需要同时取回3号和2号盒子中的东西,
 73      * 然后在开始试。依次类推:
 74      * 
 75      */
 76     private static void deepFirstSearch() {
 77         totalCount = 0;
 78         results.clear();
 79         int[] book = new int[10]; // 定义已经使用过的数字,如果使用过某数字i,那么book[i] = 1
 80         int[] result = new int[3]; // 存储当前的三个数字组成的数组
 81         go(book, result, 0);
 82         System.out.println("Total count:" + totalCount);
 83         System.out.println(results);
 84     }
 85 
 86     /**
 87      * @param book
 88      *            存储已经放过的数字
 89      * @param step
 90      *            第几步,就相当于前面所说的放第几个盒子(第一个盒子对应第0步)
 91      */
 92     private static void go(int[] book, int[] result, int step) {
 93         if (step == 3) {
 94             totalCount++;
 95             results.add(new String(result[0] + "" + result[1] + "" + result[2]));
 96             return;
 97         }
 98         for (int i = 1; i < 10; i++) {
 99             if (book[i] == 1) {
100                 continue;
101             }
102             book[i] = 1; // 标记i已经被使用
103             result[step] = i;
104             // 因为是深度优先,所以需要继续往更深处遍历
105             go(book, result, step + 1);
106 
107             // 因为还要尝试其他组合所以这里沿路返回
108             book[i] = 0;
109             result[step] = 0;
110         }
111     }
112 }
SearchAlgorithm

相关文章: