Java--算法--常用的10种算法

  1. 非递归的二分查找算法:
    1.  

    2.  

       

    3. package com.model.algorithm;
      
      /**
       * @Description:测试类
       * @Author: 张紫韩
       * @Crete 2021/7/17 20:04
       * 常用的算法---非递归式的二分查找算法
       */
      public class AlgorithmDemo01 {
          public static void main(String[] args) {
              int[] array={1,2,3,4,5,6,7,8,9};
              System.out.println("index="+binarySearch(array, 5));
          }
          public static int binarySearch(int[] array,int targetNum){
              if (array.length !=0) {
                  int left = 0;
                  int right = array.length;
                  int mid;
                  while (left <= right) {
                      mid = (left + right) / 2;
                      if (targetNum > array[mid]) {
                          left = mid + 1;
                      } else if (targetNum < array[mid]) {
                          right = mid - 1;
                      } else {
                          return mid;
                      }
                  }
              }
              return -1;
          }
      }
  2.   分治算法:

    1. package com.model.algorithm;
      
      /**
       * @Description:测试类
       * @Author: 张紫韩
       * @Crete 2021/7/17 21:14
       * 常用算法---分治算法
       * 汉诺塔
       */
      public class AlgorithmDemo02 {
          public static void main(String[] args) {
              hanoiTower(4, 'A', 'B', 'C');
      
          }
          public static void hanoiTower(int num,char one,char two,char three){
              if (num==1){
                  System.out.println("移动第"+num+"盘"+one+"->"+three);
              }else {
                  hanoiTower(num-1, one, three, two);
                  System.out.println("移动第"+num+"盘"+one+"->"+three);
                  hanoiTower(num-1, two, one, three);
              }
          }
      }
  3. 动态规划算法:

    1.  

      package com.model.algorithm;
      
      /**
       * @Description:测试类
       * @Author: 张紫韩
       * @Crete 2021/7/18 10:51
       * 十种常用算法--动态规划算法
       */
      public class AlgorithmDemo03 {
          public static void main(String[] args) {
              int[] value = {0, 1500, 3000, 2000};
              int[] weight = {0, 1, 4, 3};
              int m = 4;//背包的重量
              int[][] res = new int[value.length][m + 1];
              int[][] path = new int[value.length][m + 1];
      //        初始化
              for (int i = 0; i < res.length; i++) {//第一列的,重量为0
                  res[i][0] = 0;
              }
              for (int i = 0; i < res[0].length; i++) {
                  res[0][i] = 0;
              }
              for (int i = 1; i < res.length; i++) {
                  for (int j = 1; j < res[0].length; j++) {
                      if (weight[i] > j) {
                          res[i][j] = res[i - 1][j];
                      } else {
                          if (value[i]+res[i-1][j-weight[i]]>res[i-1][j]){
                              res[i][j]=value[i] + res[i - 1][j - weight[i]];
                              path[i][j]=1;
                          }else {
                              res[i][j]=res[i-1][j];
                          }
                      }
                  }
              }
              for (int i = 0; i < res.length; i++) {
                  for (int j = 0; j < res[0].length; j++) {
                      System.out.print(res[i][j] + "\t");
                  }
                  System.out.println();
              }
              int i = path.length-1;
              int j=path[0].length-1;
              while(i>=0&&j>=0){
                  if (path[i][j]==1){
                      System.out.printf("第%d个物品放入了背包\n",i);
                      j-=weight[i];
                  }
                  i--;
              }
              
          }
      }
  4. KMP算法:

    1. package com.model.algorithm;
      
      /**
       * @Description:测试类
       * @Author: 张紫韩
       * @Crete 2021/7/18 16:38
       * 十种常用算法---KMP算法
       */
      public class AlgorithmDemo04 {
          public static void main(String[] args) {
              String str2="wxiz";
              String str1="aaawxiz";
              System.out.println(math01(str1, str2));
      
          }
      //    暴力匹配,str1中是否包含str2
          public static boolean math(String str1,String str2){
              for (int i = 0; i < str1.length()-str2.length()+1; i++) {
                  int length = str2.length();
                  if (str2.equals(str1.substring(i, i+length))){
                      return true;
                  }
              }
              return false;
          }
          public static int math01(String str1,String str2){
              int i=0;
              int j=0;
              char[] char1 = str1.toCharArray();
              char[] char2 = str2.toCharArray();
              int len1=char1.length;
              int len2=char2.length;
              while(i<len1&&j<len2){
                  if (char1[i]==char2[j]){
                      i++;
                      j++;
                  }else {
                      i=i-j+1;
                      j=0;
                  }
              }
              if (j==len2){
                  return i-j;
              }else {
                  return -1;
              }
      
          }
      }
    2. package com.model.algorithm;
      
      import java.util.Arrays;
      
      /**
       * @Description:测试类
       * @Author: 张紫韩
       * @Crete 2021/7/18 16:38
       * 十种常用算法---KMP算法(字符串匹配问题)
       */
      public class AlgorithmDemo04 {
          public static void main(String[] args) {
              System.out.println("暴力匹配算法");
              String str2 = "wxiz";
              String str1 = "aaawxiz";
              System.out.println(math01(str1, str2));
      
              System.out.println("KMP算法的使用");
              String string1 = "BBC ABCDAB ABCDABDABDE";
              String string2 = "ABCDABD";
              System.out.println(Arrays.toString(kmpNext(string2)));
              int[] kmpNext = kmpNext(string2);
              System.out.println(kmpSearch(string1, string2, kmpNext));
      
          }
      
          //    KMP搜索算法
          public static int kmpSearch(String str1, String str2, int[] next) {
              int j = 0;
              int len2 = str2.length();
              for (int i = 0; i < str1.length(); i++) {
                  if (str1.charAt(i) == str2.charAt(j)) {
                      j++;
                  }
      //          KMP算法的核心,调整j的位置
                  while (j > 0 && str1.charAt(i) != str2.charAt(j)) {
                      j = next[j - 1];
                  }
                  if (j == len2) {
                      return i - j + 1;
                  }
              }
              return -1;
          }
      
          //    kmp算法得到一个字符串的部分匹配表
          public static int[] kmpNext(String str) {
              int[] next = new int[str.length()];
              next[0] = 0;//如果字符串的长度是1返回的部分匹配之就是0
              for (int i = 1, j = 0; i < str.length(); i++) {
      //            当匹配到str.charAt(i)!=str.charAt(j)满足时,我们需要从 next[j-1]获取新的j的值,
      //            知道我们发现str.charAt(i)==str.charAt(j)成立才退出
      //            这时KMP的核心语法
                  while (j > 0 && str.charAt(i) != str.charAt(j)) {
                      j = next[j - 1];
                  }
      //            当匹配到str.charAt(i)==str.charAt(j)满足时,部分匹配表就+1
                  if (str.charAt(i) == str.charAt(j)) {
                      j++;
                  }
                  next[i] = j;
              }
              return next;
          }
      
          //    暴力匹配,str1中是否包含str2
          public static boolean math(String str1, String str2) {
              for (int i = 0; i < str1.length() - str2.length() + 1; i++) {
                  int length = str2.length();
                  if (str2.equals(str1.substring(i, i + length))) {
                      return true;
                  }
              }
              return false;
          }
      
          public static int math01(String str1, String str2) {
              int i = 0;
              int j = 0;
              char[] char1 = str1.toCharArray();
              char[] char2 = str2.toCharArray();
              int len1 = char1.length;
              int len2 = char2.length;
              while (i < len1 && j < len2) {
                  if (char1[i] == char2[j]) {
                      i++;
                      j++;
                  } else {
                      i = i - j + 1;
                      j = 0;
                  }
              }
              if (j == len2) {
                  return i - j;
              } else {
                  return -1;
              }
      
          }
      } 
  5.  贪心算法:

    1.  

    2. package com.model.algorithm;
      
      import org.w3c.dom.stylesheets.LinkStyle;
      
      import java.util.*;
      
      /**
       * @Description:测试类
       * @Author: 张紫韩
       * @Crete 2021/7/19 15:18
       * 十种常用算法--贪心算法
       * 集合覆盖问题
       */
      public class AlgorithmDemo05 {
          public static void main(String[] args) {
              HashMap<String, HashSet<String>> broadcasts = new HashMap<>();
              HashSet<String> set1 = new HashSet<>();
              set1.add("北京");
              set1.add("上海");
              set1.add("天津");
              HashSet<String> set2 = new HashSet<>();
              set2.add("广州");
              set2.add("北京");
              set2.add("深圳");
              HashSet<String> set3 = new HashSet<>();
              set3.add("成都");
              set3.add("上海");
              set3.add("杭州");
              HashSet<String> set4 = new HashSet<>();
              set4.add("上海");
              set4.add("天津");
              HashSet<String> set5 = new HashSet<>();
              set5.add("杭州");
              set5.add("大连");
              broadcasts.put("k1", set1);
              broadcasts.put("k2", set2);
              broadcasts.put("k3", set3);
              broadcasts.put("k4", set4);
              broadcasts.put("k5", set5);
      
              HashSet<String> allAreas=new HashSet<>();
              allAreas.add("北京");
              allAreas.add("上海");
              allAreas.add("广州");
              allAreas.add("天津");
              allAreas.add("深圳");
              allAreas.add("杭州");
              allAreas.add("大连");
              allAreas.add("成都");
      //        System.out.println("覆盖最多未选择城市广播的名称:"+getMaxBroadcast(allAreas, broadcasts));
              ArrayList<String> list = greedy(broadcasts, allAreas);
              for (String key:list){
                  System.out.print(key+"\t");
              }
      
          }
      
          public static ArrayList<String> greedy(HashMap<String,HashSet<String>> broadcasts,HashSet<String> allAreas){
              ArrayList<String> resList = new ArrayList<>();//存放结果,包含所有的城市的电台组合
      
              while(!(allAreas.isEmpty())){
                  String res = getMaxBroadcast(allAreas, broadcasts);
                  //            清除掉所有的已经覆盖的城市
      //            HashSet<String> citySet = broadcasts.get(res);
      //            for (String city:citySet){
      //                allAreas.remove(city);
      //            }
                  allAreas.removeAll(broadcasts.get(res));
                  resList.add(res);
              }
              return resList;
          }
      
      //    遍历获取到各个广播台的覆盖未选城市个数,返回第一个覆盖为选城市的电台
          public static String getMaxBroadcast(HashSet<String> allAreas,HashMap<String,HashSet<String>> broadcasts){
              int max=Integer.MIN_VALUE;
              String resName=null;
              for ( Map.Entry<String, HashSet<String>> entrySet:broadcasts.entrySet()){
                  String key = entrySet.getKey();
                  HashSet<String> value = entrySet.getValue();
                  int count=0;
                  value.retainAll(allAreas);
                  count=value.size();
      //            for (String city:value){
      //                if (allAreas.contains(city)){
      //                    count++;
      //                }
      //            }
                  if (count>max){
                      max=count;
                      resName=key;
                  }
              }
             return resName;
          }
      }
  6. 普利姆算法:

    1.  

       

    2. package com.model.algorithm;
      
      import java.util.Arrays;
      
      /**
       * @Description:测试类
       * @Author: 张紫韩
       * @Crete 2021/7/19 17:26
       * 十种常用算法--普利姆算法(Prim)
       */
      public class AlgorithmDemo06 {
          public static void main(String[] args) {
              char[] data={'A','B','C','D','E','F','G'};
              Graph graph = new Graph(data);
              graph.addSize('A', 'B', 5);
              graph.addSize('A', 'C', 7);
              graph.addSize('A', 'G', 2);
              graph.addSize('B', 'G', 3);
              graph.addSize('B', 'D', 9);
              graph.addSize('C', 'E', 8);
              graph.addSize('D', 'F', 4);
              graph.addSize('E', 'F', 5);
              graph.addSize('E', 'G', 4);
              graph.addSize('F', 'G', 6);
      //        graph.show();
      
              MinTree minTree = new MinTree(graph);
              minTree.show();
              minTree.createMinTree('A');
      
      
          }
      
      }
      class MinTree{
      
          private Graph graph;
      
          //   核心方法。使用图创建最小生成树
          public void createMinTree(char c){
              int start = graph.getNumber(c);
              int[] visited=new int[graph.nodeNum];
      //        将当前节点标记未已经访问
              visited[start]=1;
      //        找出 nodeNum-1条边
              for (int i = 1; i < graph.nodeNum; i++) {//一共有 nodeNum-1条的边
                  int minWeight=1000;
                  int x=-1;
                  int y=-1;
                  for (int j = 0; j < graph.nodeNum; j++) {//遍历已经访问的节点
                      for (int k = 0; k < graph.nodeNum; k++) {//遍历没有被访问过的节点
                          if (visited[j]==1&&visited[k]==0&&graph.weight[j][k]<minWeight){
                              minWeight=graph.weight[j][k];
                              x=j;
                              y=k;
                          }
                      }
                  }
                  visited[y]=1;
                  System.out.println("找到最小的一条边:<"+graph.data[x]+","+graph.data[y]+">\t权值是:"+minWeight);
              }
          }
      //   遍历图
          public void show(){
              if (graph!=null) {
                  graph.show();
              }else {
                  System.out.println("图为空,无法进行遍历");
              }
          }
      
      
          public MinTree(Graph graph) {
              this.graph = graph;
          }
      
      
      }
      
      class Graph{
          int nodeNum;//节点的数量
          char[] data;//存放节点的数据
          int[][] weight;//存放边
      
          public Graph(char[] data) {
              this.nodeNum = data.length;
              this.data=data;
              weight=new int[nodeNum][nodeNum];
              for (int[] arr:weight) {
                  Arrays.fill(arr, 1000);
              }
          }
          public void addSize(char nodeA,char nodeB,int weight){
              this.weight[getNumber(nodeA)][getNumber(nodeB)]=weight;
              this.weight[getNumber(nodeB)][getNumber(nodeA)]=weight;
          }
          public void show(){
              for (int[] link:this.weight){
                  System.out.println(Arrays.toString(link));
              }
          }
          public int getNumber(char c){
              switch (c){
                  case 'A':
                      return 0;
                  case 'B':
                      return 1;
                  case 'C':
                      return 2;
                  case 'D':
                      return 3;
                  case 'E':
                      return 4;
                  case 'F':
                      return 5;
                  case 'G':
                      return 6;
                  default:
                      return -1;
              }
          }
      }
  7. 克鲁斯卡尔算法(Kruskal)

    1. package com.model.algorithm;
      
      import java.util.Arrays;
      
      /**
       * @Description:测试类
       * @Author: 张紫韩
       * @Crete 2021/7/19 19:37
       * 十种常用算法--克鲁斯卡尔算法(Kruskal)
       * 公交站问题
       */
      public class AlgorithmDemo07 {
          public static void main(String[] args) {
              char[] data = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
              KruskalGraph graph = new KruskalGraph(data);
              graph.addSize('A', 'B', 12);
              graph.addSize('A', 'F', 16);
              graph.addSize('A', 'G', 14);
              graph.addSize('B', 'C', 10);
              graph.addSize('B', 'F', 7);
              graph.addSize('C', 'D', 3);
              graph.addSize('C', 'E', 5);
              graph.addSize('C', 'F', 6);
              graph.addSize('D', 'E', 4);
              graph.addSize('E', 'F', 2);
              graph.addSize('E', 'G', 8);
              graph.addSize('F', 'G', 9);
      //        graph.show();
              Kruskal kruskal = new Kruskal(graph);
              kruskal.show();
              System.out.println("边的数量:" + kruskal.getEdgeNum());
              KruskalEdge[] edges = kruskal.getEdge();
              for (KruskalEdge edge : edges) {
                  System.out.println(edge);
              }
              System.out.println("排序后的边:");
              kruskal.sortEdge(edges);
              for (KruskalEdge edge : edges) {
                  System.out.println(edge);
              }
              System.out.println("使用克鲁斯卡尔算法得到的最小生成树:");
              kruskal.createGraph();
      
          }
      }
      
      //克鲁斯卡尔生成最小生成树
      class Kruskal {
          private KruskalGraph graph;
      
          //核心方法,使用kruskal算法生成最小生成树
          public void createGraph() {
              int index=0;//表示结果数组的索引
              int[] ends=new int[graph.nodeNum];//保存每个顶点的终点
              KruskalEdge[] rets=new KruskalEdge[graph.nodeNum-1];//创建一个返回值
              KruskalEdge[] edges=getEdge();//的到所有的边
      //      System.out.println(Arrays.toString(edges));
      //      对边进行排序
              sortEdge(edges);
      //      遍历edges边的数组,将最小的边添加到最小生成树,判断是否构成回路,如果没有就加入到,否则不加入
              for (int i = 0; i < getEdgeNum(); i++) {
                  //edges[i].getStart():edges[i]边的起点
                  int p1=getPosition(edges[i].getStart());
                  int p2=getPosition(edges[i].getEnd());
                  //ends:保存已经生成的最小生树每个顶点的终点
                  int end1=getEnd(ends, p1);
                  int end2=getEnd(ends, p2);
                  if (end1!=end2){
                      ends[end1]=end2;
                      rets[index++]=edges[i];
                  }
              }
      //        输出所有的构成最小生成树的边
              for (KruskalEdge edge:rets){
                  System.out.println(edge);
              }
          }
          //    返回顶点的坐标
          public int getPosition(char c) {
              return graph.getPosition(c);
          }
      
          //   获取到所有的边
          public KruskalEdge[] getEdge() {
              if (graph != null) {
                  return graph.getEdge();
              } else {
                  return null;
              }
          }
      //    功能:获取小标未i的顶点的终点,用于后面判断两个顶点是否是相同的
      //    ends:数组记录了各个顶点对应的终点是那个,
      //    i:表示传入的顶点对应的下标
      //    返回的是 顶点i对应的终点的下标
          public int getEnd(int[] ends,int i){
              while (ends[i]!=0){
                  i=ends[i];
              }
              return i;
          }
      
          //    对边进行排序
          public void sortEdge(KruskalEdge[] Edges) {
              for (int i = 0; i < Edges.length; i++) {
                  for (int j = 0; j < Edges.length - 1 - i; j++) {
                      if (Edges[j].getWeight() > Edges[j + 1].getWeight()) {
                          KruskalEdge temp = Edges[j];
                          Edges[j] = Edges[j + 1];
                          Edges[j + 1] = temp;
                      }
                  }
              }
          }
      
          //    获取边的数量
          public int getEdgeNum() {
              if (graph != null) {
                  return graph.getEdgeNum();
              } else {
                  return -1;
              }
          }
      
          //   遍历图
          public void show() {
              if (graph != null) {
                  graph.show();
              } else {
                  System.out.println("图为空,无法进行遍历");
              }
          }
      
      //    初始化
          public Kruskal(KruskalGraph graph) {
              this.graph = graph;
          }
      }
      
      
      
      //边类
      class KruskalEdge {
          private char start;//边的起点
          private char end; //边的终点
          private int weight;//边的权重
      
          public KruskalEdge() {
          }
      
          public KruskalEdge(char start, char end, int weight) {
              this.start = start;
              this.end = end;
              this.weight = weight;
          }
      
          public char getStart() {
              return start;
          }
      
          public void setStart(char start) {
              this.start = start;
          }
      
          public char getEnd() {
              return end;
          }
      
          public void setEnd(char end) {
              this.end = end;
          }
      
          public int getWeight() {
              return weight;
          }
      
          public void setWeight(int weight) {
              this.weight = weight;
          }
      
          @Override
          public String toString() {
              return "KruskalEdge{" +
                      "start=" + start +
                      ", end=" + end +
                      ", weight=" + weight +
                      '}';
          }
      }
      
      
      
      
      //图类
      class KruskalGraph {
          int nodeNum;//节点的数量
          char[] data;//存放节点的数据
          int[][] weight;//存放边
          private static final int INF = Integer.MAX_VALUE;
      
          //    返回顶对应的下标
          public int getPosition(char c) {
              for (int i = 0; i < nodeNum; i++) {
                  if (data[i] == c) {
                      return i;
                  }
              }
              return -1;
          }
      
          public KruskalEdge[] getEdge() {
              KruskalEdge[] edges = new KruskalEdge[getEdgeNum()];
              int index = 0;
              for (int i = 0; i < nodeNum; i++) {
                  for (int j = i + 1; j < nodeNum; j++) {
                      if (weight[i][j] != INF) {
                          edges[index++] = new KruskalEdge(data[i], data[j], weight[i][j]);
                      }
      
                  }
              }
              return edges;
          }
      
          //    初始化
          public KruskalGraph(char[] data) {
              this.nodeNum = data.length;
              this.data = data;
              weight = new int[nodeNum][nodeNum];
              for (int i = 0; i < weight.length; i++) {
                  for (int j = 0; j < weight.length; j++) {
                      if (i == j) {
                          weight[i][j] = 0;
                      } else {
                          weight[i][j] = INF;
                      }
                  }
              }
          }
      
          public void addSize(char nodeA, char nodeB, int weight) {
              this.weight[getNumber(nodeA)][getNumber(nodeB)] = weight;
              this.weight[getNumber(nodeB)][getNumber(nodeA)] = weight;
          }
      
          public void show() {
              for (int[] link : this.weight) {
                  for (int i = 0; i < link.length; i++) {
                      System.out.printf("%10d\t", link[i]);
                  }
                  System.out.println();
              }
          }
      
          public int getEdgeNum() {
              int count = 0;
              for (int i = 0; i < data.length; i++) {
                  for (int j = i + 1; j < data.length; j++) {
                      if (weight[i][j] != INF) {
                          count++;
                      }
                  }
              }
              return count;
          }
      
          private int getNumber(char ch) {
              switch (ch) {
                  case 'A':
                      return 0;
                  case 'B':
                      return 1;
                  case 'C':
                      return 2;
                  case 'D':
                      return 3;
                  case 'E':
                      return 4;
                  case 'F':
                      return 5;
                  case 'G':
                      return 6;
                  default:
                      return -1;
              }
          }
      }
  8. 迪杰斯特拉算法(Dijkstra):

    1. package com.model.algorithm;
      
      import java.util.Arrays;
      
      /**
       * @Description:测试类
       * @Author: 张紫韩
       * @Crete 2021/7/20 10:06
       * 十种常用算法--迪杰斯特拉算法(Dijkstra)
       */
      public class AlgorithmDemo08 {
          public static void main(String[] args) {
              char[] data={'A','B','C','D','E','F','G'};
              DijkstraGraph graph = new DijkstraGraph(data);
              graph.addEdge('A', 'B', 5);
              graph.addEdge('A', 'C', 7);
              graph.addEdge('A', 'G', 2);
              graph.addEdge('B', 'G', 3);
              graph.addEdge('B', 'D', 9);
              graph.addEdge('C', 'E', 8);
              graph.addEdge('D', 'F', 4);
              graph.addEdge('E', 'F', 5);
              graph.addEdge('E', 'G', 4);
              graph.addEdge('F', 'G', 6);
      //        graph.show();
              Dijkstra dijkstra = new Dijkstra(graph);
              dijkstra.show();
              System.out.println(Arrays.toString(dijkstra.dis));
              System.out.println(Arrays.toString(dijkstra.visited));
              System.out.println(Arrays.toString(dijkstra.pre_visited));
              dijkstra.dijkstra('A');
              dijkstra.showResult();
      
          }
      }
      class Dijkstra{
          private final DijkstraGraph graph;
          public int[] visited; //记录每个顶点的访问情况
          public int[] pre_visited; //记录每个顶点的前驱节点
          public int[] dis;//记录起点到各个顶点的距离
      
      //    核心算法,生成顶点到各个顶点的最短距离
          public void dijkstra(char c){
              int index = getPosition(c);
              dis[index]=0;//设置起点到自己的距离为0
              for (int i = 0; i < visited.length; i++) {
                  visited[index]=1;//起点为1,已将访问过了
                  update(index);//跟新起点能到大的节点的信息
                  index=getNewIndex();
              }
          }
      //    获得一个新的访问顶点,以这个顶点继续访问其他的顶点
          public int getNewIndex(){
              int index=0;
              int min=Integer.MAX_VALUE;
              for (int i = 0; i < visited.length; i++) {
                  if (dis[i]<min&&!isVisited(i)){
                      index=i;
                      min=dis[i];
                  }
              }
              return index;
          }
      //   更新某个index节点到周围节点的距离以及周围顶点的前驱节点
          public void  update(int index){
              int len=0;
              for (int i = 0; i < graph.weight[index].length; i++) {
                  len=getDis(index)+graph.weight[index][i];
                  if (!isVisited(i)&&len<getDis(i)){
                      updateDis(i, len);//更新距离
                      updatePre(i, index);//更新前驱节点
                  }
              }
          }
          //    展示最后的结果
          public void showResult(){
              System.out.println("每个顶点的访问情况:"+Arrays.toString(visited));
              System.out.println("每个顶点的前驱节点情况:"+Arrays.toString(pre_visited));
              System.out.println("每个顶点到起点的最短距离情况:"+Arrays.toString(dis));
          }
      
      //    判断当前节点是否被访问了
          public boolean isVisited(int index){ return  visited[index]==1; }
      //    更新起点index到节点的距离
          public void updateDis(int end,int len){
              dis[end]=len;
          }
      //    更新顶点的前前驱节点
          public void updatePre(int index,int pre){
              pre_visited[index]=pre;
          }
      //    返回某个顶点到起点的距离
          public int getDis(int index){
              return dis[index];
          }
          //   初始化
          public Dijkstra(DijkstraGraph graph) {
              visited=new int[graph.nodeNum];
              pre_visited=new int[graph.nodeNum];
              dis=new int[graph.nodeNum];
              Arrays.fill(dis, Integer.MAX_VALUE);
              this.graph = graph;
          }
          //    返回某个顶点的下标
          public int getPosition(char c){
              if (graph!=null) {
                  return graph.getPosition(c);
              }else {
                  return -1;
              }
          }
      //    展示图
          public void show(){
              if (graph!=null) {
                  graph.show();
              }else {
                  System.out.println("图为空");
              }
          }
      
      }
      
      
      
      //图类
      class DijkstraGraph {
          int nodeNum;//节点的数量
          char[] data;//存放节点的数据
          int[][] weight;//存放边
          private static final int INF = 65535;
      
          //    返回顶对应的下标
          public int getPosition(char c) {
              for (int i = 0; i < nodeNum; i++) {
                  if (data[i] == c) {
                      return i;
                  }
              }
              return -1;
          }
      
          //    初始化
          public DijkstraGraph(char[] data) {
              this.nodeNum = data.length;
              this.data = data;
              weight = new int[nodeNum][nodeNum];
              for (int i = 0; i < weight.length; i++) {
                  for (int j = 0; j < weight.length; j++) {
                          weight[i][j] = INF;
      
                  }
              }
          }
          public void addEdge(char nodeA, char nodeB, int weight) {
              this.weight[getPosition(nodeA)][getPosition(nodeB)] = weight;
              this.weight[getPosition(nodeB)][getPosition(nodeA)] = weight;
          }
      
      //    展示图
          public void show() {
              for (int[] link : this.weight) {
                  for (int j : link) {
                      System.out.printf("%10d\t", j);
                  }
                  System.out.println();
              }
          }
      
      }
  9.  弗洛伊德算法(Floyd):

    1.  

       

    2. package com.model.algorithm;
      
      import java.util.Arrays;
      
      /**
       * @Description:测试类
       * @Author: 张紫韩
       * @Crete 2021/7/20 16:09
       * 十种常用算法--弗洛伊德算法(Floyd)
       * 求最短路径
       */
      public class AlgorithmDemo09 {
          public static void main(String[] args) {
              char[] data={'A','B','C','D','E','F','G'};
              FloydGraph graph = new FloydGraph(data);
              graph.addEdge('A', 'B', 5);
              graph.addEdge('A', 'C', 7);
              graph.addEdge('A', 'G', 2);
              graph.addEdge('B', 'G', 3);
              graph.addEdge('B', 'D', 9);
              graph.addEdge('C', 'E', 8);
              graph.addEdge('D', 'F', 4);
              graph.addEdge('E', 'F', 5);
              graph.addEdge('E', 'G', 4);
              graph.addEdge('F', 'G', 6);
      //        graph.show();
              Floyd floyd = new Floyd(graph);
              floyd.showGraph();
              System.out.println("返回节点对应的下标:"+floyd.getPosition('B'));
              floyd.floyd();
              floyd.showResult();
      
          }
      }
      class Floyd{
          private FloydGraph graph;
          private int[][] dis;//从各个顶点出发,到达其他的顶点的距离,最后的结果,也保留在这个数组中
          private int[][] pre;//保存到目标节点的前驱节点
      
      // 弗洛伊德的核心算法,
          public void floyd(){
              int len=0;
              for (int i = 0; i < dis.length;i++) {//中间节点,以某个中间节点循环,不断更新 两个节点的前驱节点和两个节点之间的距离
                  for (int j = 0; j < dis.length; j++) {//起点
                      for (int k = 0; k < dis.length; k++) {//终点
                          len=dis[j][i]+dis[i][k];
                          if (len<dis[j][k]){
                              dis[j][k]=len;//跟新最小数据
                              pre[j][k]=pre[k][j];//跟新前驱节点
                          }
                      }
                      
                  }
                  
              }
      
          }
      
          public Floyd(FloydGraph graph) {
              dis=graph.weight;
              this.graph = graph;
              pre=new int[graph.nodeNum][graph.nodeNum];
              for (int i = 0; i < pre.length; i++) {
                  Arrays.fill(pre[i],i);
              }
      
          }
      
          public void showResult(){
              for (int i=0;i< dis.length;i++){
                  for (int j = 0; j < dis[i].length; j++) {
                      System.out.printf("<"+graph.data[i]+","+graph.data[j]+">最短路径:%5d\t",dis[i][j]);
                  }
                  System.out.println();
                  for (int j = 0; j < dis[i].length; j++) {
                      System.out.printf("<"+graph.data[i]+","+graph.data[j]+">前驱节点:%5s\t", graph.data[pre[i][j]]);
                  }
                  System.out.println();
                  System.out.println();
              }
          }
          public int getPosition(char c){
              return graph.getPosition(c);
          }
          public void showGraph(){
              if (graph!=null){
                  graph.show();
              }else {
                  System.out.println("图为空");
              }
          }
      }
      
      
      //图类
      class FloydGraph {
          int nodeNum;//节点的数量
          char[] data;//存放节点的数据
          int[][] weight;//存放边
          private static final int INF = 65535;
      
          //    返回顶对应的下标
          public int getPosition(char c) {
              for (int i = 0; i < nodeNum; i++) {
                  if (data[i] == c) {
                      return i;
                  }
              }
              return -1;
          }
      
          //    初始化
          public FloydGraph(char[] data) {
              this.nodeNum = data.length;
              this.data = data;
              weight = new int[nodeNum][nodeNum];
              for (int i = 0; i < weight.length; i++) {
                  for (int j = 0; j < weight[i].length; j++) {
                      if (i==j){
                          weight[i][j]=0;
                      }else {
                          weight[i][j] = INF;
                      }
                  }
              }
          }
          public void addEdge(char nodeA, char nodeB, int weight) {
              this.weight[getPosition(nodeA)][getPosition(nodeB)] = weight;
              this.weight[getPosition(nodeB)][getPosition(nodeA)] = weight;
          }
      
          //    展示图
          public void show() {
              for (int[] link : this.weight) {
                  for (int j : link) {
                      System.out.printf("%10d\t", j);
                  }
                  System.out.println();
              }
          }
      
      }
  10.  马踏棋盘算法(骑士周游问题):

    1.  

    2.  

    3.  

      package com.model.algorithm;
      
      
      import com.sun.deploy.pings.Pings;
      
      import java.awt.*;
      import java.time.LocalDateTime;
      import java.util.ArrayList;
      import java.util.Arrays;
      import java.util.Comparator;
      
      /**
       * @Description:测试类
       * @Author: 张紫韩
       * @Crete 2021/7/20 20:22
       * 十种常用算法--马踏棋盘算法(骑士周游问题)
       */
      public class AlgorithmDemo10 {
          public static void main(String[] args) {
              System.out.println("开始了");
              HorseChessboard chessboard = new HorseChessboard(8, 8);
              int second = LocalDateTime.now().getSecond();
              chessboard.horseChessBoard(0, 0, 1);
              System.out.println("共耗时:"+(LocalDateTime.now().getSecond()-second));
      
              for (int[] temp:chessboard.getChessboard()){
                 System.out.println(Arrays.toString(temp));
               }
              for (boolean[] temp:chessboard.getVisited()){
                  System.out.println(Arrays.toString(temp));
              }
          }
      
      }
      class HorseChessboard{
          private  int x;//第几列
          private  int y;//第几行
          private  int[][] chessboard;//棋盘
          private  boolean[][] visited;//是否访问
          private boolean finished=false;//是否完成
      
          public void horseChessBoard(int row,int column,int step){
      //       1.假设当前节点是可以遍历整个棋盘的,将当前节点访问,
              Point curr = new Point(row, column);
              chessboard[row][column]=step;
              visited[row][column]=true;
      //        2.访问节点周围所有的节点
              ArrayList<Point> next = getNext(curr);
              sortPoint(next);//使用贪心算法,先遍历可行数量少的,可以减少回溯的次数,来提高速度
              while (!next.isEmpty()){
                  Point remove = next.remove(0);
                  if (!visited[remove.x][remove.y]) {
                      horseChessBoard(remove.x, remove.y, step+1);
                  }
              }
      //        3.实现回溯
      //          假设当前节点是可以访问的,如果遍历了这个周围的所有节点,但还是没有走完,就说明这个节点是走不通的我们需要进行回溯
              if (step<x*y&&!finished){
                  chessboard[row][column]=0;
                  visited[row][column]=false;
              }else {
                  finished=true;
              }
          }
          public ArrayList<Point> getNext(Point curPoint){
              ArrayList<Point> nextList = new ArrayList<>();
              int x = curPoint.x;
              int y = curPoint.y;
              if (x-2>=0&&y-1>=0){//5号位置
                  nextList.add(new Point(x-2,y-1));
              }
              if (x-1>=0&&y-2>=0){//6好位置
                  nextList.add(new Point(x-1,y-2));
              }
              if (x+1<this.x&&y-2>=0){//7号位置
                  nextList.add(new Point(x+1,y-2));
              }
              if (x+2<this.x&&y-1>=0){//0好位置
                  nextList.add(new Point(x+2,y-1));
              }
              if (x+2<this.x&&y+1<this.y){//1号位置
                  nextList.add(new Point(x+2,y+1));
              }
              if (x+1<this.x&&y+2<this.y){//2好位置
                  nextList.add(new Point(x+1,y+2));
              }
              if (x-1>=0&&y+2<this.y){//3好位置
                  nextList.add(new Point(x-1,y+2));
              }
      
              if (x-2>=0&&y+1<this.y){//4好位置
                  nextList.add(new Point(x-2,y+1));
              }
      
              return nextList;
          }
          public  void sortPoint(ArrayList<Point> pointList){
              pointList.sort(new Comparator<Point>() {
                  @Override
                  public int compare(Point o1, Point o2) {
                     return getNext(o1).size()-getNext(o2).size();
                  }
              });
      
          }
      
          public HorseChessboard(int x, int y) {
              visited=new boolean[x][y];
              chessboard=new int[x][y];
              this.x = x;
              this.y = y;
              for (boolean[] temp:visited){
                  Arrays.fill(temp, false);
              }
      
          }
      
          public int getX() {
              return x;
          }
      
          public void setX(int x) {
              this.x = x;
          }
      
          public int getY() {
              return y;
          }
      
          public void setY(int y) {
              this.y = y;
          }
      
          public int[][] getChessboard() {
              return chessboard;
          }
      
          public void setChessboard(int[][] chessboard) {
              this.chessboard = chessboard;
          }
      
          public boolean[][] getVisited() {
              return visited;
          }
      
          public void setVisited(boolean[][] visited) {
              this.visited = visited;
          }
      
          public boolean isFinished() {
              return finished;
          }
      
          public void setFinished(boolean finished) {
              this.finished = finished;
          }
      }

       

         

posted @ 2021-07-19 11:43  张紫韩  阅读(4149)  评论(0编辑  收藏  举报