十大常用算法的完整实现
一、二分查找算法:https://blog.csdn.net/weixin_46635575/article/details/121532149
二、分治算法:https://blog.csdn.net/weixin_46635575/article/details/121532941
三、动态规划算法:https://blog.csdn.net/weixin_46635575/article/details/121534074
四、KMP算法:https://blog.csdn.net/weixin_46635575/article/details/121590510
五、贪心算法:https://blog.csdn.net/weixin_46635575/article/details/121626626
六、普利姆算法:https://blog.csdn.net/weixin_46635575/article/details/121653256
七、克鲁斯卡尔算法:https://blog.csdn.net/weixin_46635575/article/details/121670374
八、地杰斯特拉算法:https://blog.csdn.net/weixin_46635575/article/details/121692675
九、佛洛依德算法:https://blog.csdn.net/weixin_46635575/article/details/121714678
十、马踏棋盘算法(周游骑士算法):https://blog.csdn.net/weixin_46635575/article/details/121716596
1、基本介绍
(1)应用场景
(2)介绍
回忆一下我们的图的广度优先和深度优先
- 广度优先是从一层一层的访问:所以是12345678
- 深度优先是先走到底,然后回到起点进行重新查找,如果还是不是很理解的话,建议你去看一下我主页的图的算法的文章。
- v就是我们例子中的G点,Dis里面记录的是v到图中各个节点的距离
(3)图解我们的题目
-
当以G开始走一遍后
当G访问后,接下来开始访问A开始访问。这时候三个数组也是要进行更新的,这时候的出发顶点任然是G点,只是以A点访问而已,不然我们无法记录G到各个顶点的距离。 -
需要创建的数组
2、代码编写
来看我们分析写代码的顺序
- 首先我要去编写初始化图的一个类,并且初始化图
- 第二步我是要完成目的1
- 第三步我们要完成目的2
(1)先初始化我们的图
- 这个到后面也是很重要的,所以请把这里看懂了,挺简单的
package cn.mldn.dijkstra;
import java.util.Arrays;
public class DijkstraAlgorithm {
public static void main(String[] args) {
//先初始化我们的图
char[] vertex = {'A','B','C','D','E','F','G'};
//领接矩阵
int[][] matrix = new int[vertex.length][vertex.length];
final int N = 65535;//表示不可连接
matrix[0] =new int[]{N,5,7,N,N,N,2};
matrix[1] =new int[]{5,N,N,9,N,N,3};
matrix[2] =new int[]{7,N,N,N,8,N,N};
matrix[3] =new int[]{N,9,N,N,N,4,2};
matrix[4] =new int[]{N,N,8,N,N,5,4};
matrix[5] =new int[]{N,N,N,4,5,N,6};
matrix[6] =new int[]{2,3,N,N,4,6,N};
//这是一部分的测试
Graph graph = new Graph(vertex, matrix);
graph.showGraph();
}
}
class Graph {
private char[] vertex;//存放顶点数组
private int[][] matrix;//领接矩阵
public Graph(char[] vertex,int[][] matrix) {
this.vertex = vertex;
this.matrix = matrix;
}
//显示图
public void showGraph() {
for (int[] link: matrix) {
System.out.println(Arrays.toString(link));
}
}
}
(2)完成目的1
- 首先要去看VisitedVertex 类的所有方法
- 然后再去看我们增加在Graph图里面的方法
import java.util.Arrays;
public class DijkstraAlgorithm {
public static void main(String[] args) {
//先初始化我们的图
char[] vertex = {'A','B','C','D','E','F','G'};
//领接矩阵
int[][] matrix = new int[vertex.length][vertex.length];
final int N = 65535;//表示不可连接
matrix[0] =new int[]{N,5,7,N,N,N,2};
matrix[1] =new int[]{5,N,N,9,N,N,3};
matrix[2] =new int[]{7,N,N,N,8,N,N};
matrix[3] =new int[]{N,9,N,N,N,4,2};
matrix[4] =new int[]{N,N,8,N,N,5,4};
matrix[5] =new int[]{N,N,N,4,5,N,6};
matrix[6] =new int[]{2,3,N,N,4,6,N};
//这是一部分的测试
Graph graph = new Graph(vertex, matrix);
graph.showGraph();
//第二部分的测试
graph.dsj(6);
}
}
//表示已经访问过的集合
class VisitedVertex {
//记录各个顶点是否访问过1表示已经访问过,0表没有访问
public int[] already_arr;
//每个下标对应的值为前一个顶点的下标,会动态更新
public int[] pre_visited;
//记录出发点到其他所有节点的距离,比如G为出发点,就会记录到其他顶点的距离,会动态更新,求的最短距离就会放到dis里面
public int[] dis;
//构造器
/**
*
* @param length 你要给我长度
* @param index 你是从那个顶点开始处理的:即出发顶点
*/
public VisitedVertex(int length,int index) {
this.already_arr = new int[length];
this.pre_visited = new int[length];
this.dis = new int[length];
//初始化dis数组,除了自己那个点为0
Arrays.fill(dis,65535);
this.already_arr[index] = 1;//设置出发顶点被访问过
this.dis[index] = 0;
}
/**
* 判断index顶点是否被访问过
* @param index
* @return 被访问过就是true
*/
public boolean in(int index) {
return already_arr[index] == 1;
}
/**
* 更新出发节点到index顶点的距离【对应dis数组】
* @param index
* @param len
*/
public void updateDis(int index,int len) {
dis[index] = len;
}
/**
* 更新pre顶点的前驱为index的节点【对应我们的pre_visited】
* @param pre
* @param index
*/
public void updatePre(int pre,int index) {
pre_visited[pre] = index;
}
/**
* 返回出发顶点到index的距离【对应我们的dis数组】
* @param index
*/
public int getDis(int index) {
return dis[index];
}
}
class Graph {
private char[] vertex;//存放顶点数组
private int[][] matrix;//领接矩阵
public Graph(char[] vertex,int[][] matrix) {
this.vertex = vertex;
this.matrix = matrix;
}
//显示图
public void showGraph() {
for (int[] link: matrix) {
System.out.println(Arrays.toString(link));
}
}
private VisitedVertex vv;//表示已经访问的顶点的集合
/**
* 地杰斯特拉算法
* @param index 表示出发顶点的下标
*/
public void dsj(int index) {
vv = new VisitedVertex(vertex.length,index);
update(index);//更新index顶点到周围顶点的距离和前驱顶点
}
//更新index下标顶点到周围顶点的距离和周围顶点的前驱顶点
private void update(int index) {
int len = 0;
//根据遍历我们的领接矩阵,即matrix[index]这一行
for (int i = 0; i < matrix[index].length; i++) {
//这时候的len表示,出发点到index顶点的距离 + 从index顶点到j顶点的距离
len = vv.getDis(index) + matrix[index][i];
//如果i这个节点没有被访问过,并且len小于出发节点到j顶点的距离,就需要更新
if (!vv.in(i) && len < vv.getDis(i)) {
vv.updatePre(i,index);//更新i这个节点的前驱节点为index顶点
vv.updateDis(i,len);//更新出发顶点到i顶点的距离
}
}
}
}
(3)完成目的2
完成上面,就相当于完成了过程图中的目的1,接下来完成目的2
- 首先在我们的VisitedVertex追加如下方法
/**
* 继续选择并返回新的访问顶点,比如这里的G完后,就要A作为新的访问顶点【不是以这个为出发点】
* @return
*/
public int updateArr() {
int min = 65535;
int index = 0;
for (int i = 0; i < already_arr.length; i++) {
if (already_arr[i] == 0 && dis[i] < min) {
min = dis[i];
index = i;
}
}
//同时更新index顶点被访问过
already_arr[index] = 1;
return index;
}
//用于后面的显示
public void show() {
System.out.println("============================");
for (int i: already_arr) {
System.out.print(i + " ");
}
System.out.println();
System.out.println("****************************");
for (int i: pre_visited) {
System.out.print(i + " ");
}
System.out.println();
System.out.println("----------------------------");
for (int i: dis) {
System.out.print(i + " ");
}
}
- 然后修改我们的的MGraph里面的djs方法和追加我们的show方法
/**
* 地杰斯特拉算法
* @param index 表示出发顶点的下标
*/
public void dsj(int index) {
vv = new VisitedVertex(vertex.length,index);
update(index);//更新index顶点到周围顶点的距离和前驱顶点
for (int i = 0; i < vertex.length; i++) {
index = vv.updateArr();//选择并返回新的访问顶点
update(index);//更新index顶点到周围顶点的距离和前驱顶点
}
}
//用于后续的显示
public void djsShow() {
vv.show();
}