迪杰斯特拉(Dijkstra)算法

本文深入解析了迪杰斯特拉算法,一种经典的最短路径算法,详细介绍了其原理及应用,通过广度优先搜索思想,计算从起点到图中其他各点的最短路径。并提供了算法的实现代码,帮助读者理解算法的具体操作流程。

迪杰斯特拉(Dijkstra)算法介绍
迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个结 点到其他结点的最短路径。它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止。

算法过程
设置出发顶点为v,顶点集合V{v,v2,v…}, v到V中各顶点的距离构成距离集合Dis,Dis{d1,d2,d…}, Dis集合记录着v到图中各顶点的距离(到自身可以看作0,v到vi距离对应为di)

  1. 从Dis中选择值最小的di并移出Dis集合, 同时移出V集合中对应的顶点vi,此时的v到vi即为最短路径
  2. 更新Dis集合,更新规则为:比较v到V集合中顶点的距离值,与v通过vi到V集合中项点的距离值,保留值较小的一个(同时也应该更新顶点的前驱节点为vi,表明是通过vi到达的)
  3. 重复执行两步骤,直到最短路径项点为目标顶点即可结束

图解
在这里插入图片描述


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,N};
		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(2);
		graph.show();
	}

}

class Graph{
	private char[] vertex;//顶点数组
	private int[][] matrix;//邻接矩阵
	private VisitedVertex vv;
	//构造器
	public Graph(char[] vertex,int[][] matrix) {
		this.matrix = matrix;
		this.vertex = vertex;
	}
	//显示图
	public void showGraph() {
		for(int[] link : matrix) {
			System.out.println(Arrays.toString(link));
		}
	}
	
	//更新index下标顶点到周围顶点的距离和周围顶点的前驱顶点
	private void update(int index) {
		int len = 0;
		//根据邻接矩阵遍历matrix[index]行
		for(int j = 0;j < matrix[index].length;j++) {
			len = vv.getDis(index) + matrix[index][j];
			//len 出发顶点到index顶点的距离 + 从index顶点到 j 顶点距离 的和
			if(!vv.in(j) && len<vv.getDis(j)) {
				//如果该点未被访问过 并且len小于出发顶点到J顶点的距离则需要更新
				vv.updatePre(j, index);
				vv.updateDis(j, len);
			}
		}
		  
	}                  
	//迪杰斯特拉算法
	//index 出发点下标
	public void dsj(int index) {
		vv = new VisitedVertex(vertex.length,index);
		update(index);//更新index顶点到周围顶点的距离 和前驱顶点
		for(int j = 1;j < vertex.length; j++) {
			index = vv.updateArr();//选择并返回新的访问顶点
			update(index);//更新index顶点到周围顶点的距离和前驱顶点
		}
	}
	
	public void show() {
		vv.show();
	} 
	
}

//已访问顶点集合
class VisitedVertex{
	//记录各个顶点是否访问过1表示访问过, 0未访问,会动态更新
	public int[] already_arr; 
	//每个下标对应的值为前一 个顶点下标,会动态更新
	public int[] pre_visited;
	//记录出发顶点到其他所有顶点的距离,比如G为出发顶点,就会记录G到其它顶点的距离,会动态更新,求的最短距离会存放到dis
	public int[] dis;
	//构造器
	public VisitedVertex(int length,int index) {
		this.already_arr = new int[length];//length顶点个数 index出发顶点		
		this.pre_visited = new int[length];
		this.already_arr[index] = 1;
		this.dis = new int[length];
		//初始化dis
		Arrays.fill(dis, 65535);//全部填充为65535
		this.dis[index] = 0;//设置出发点到该点距离为0
		
	}
	
	//判断index顶点是否被访问过
	public boolean in(int index) {
		return already_arr[index] == 1;//访问过为1
	}
	
	//更新出发顶点到该点距离
	public void updateDis(int index,int len) {
		dis[index] = len;
	}
	
	//更新顶点的前驱节点
	public void updatePre(int index,int pre) {
		pre_visited[index] = pre;
	}
	
	//返回出发顶点到index顶点个距离
	public int getDis(int index) {
		return dis[index];
	}
	
	//继续选择并返回新的访问节点 比如G(出发顶点) 完后 以A作为新的访问节点
	public int updateArr() {
		int min = 65535, index = 0;
		for(int i = 0; i < already_arr.length;i++) {
			if(already_arr[i] == 0 && dis[i] < min) {
				//该值未访问且距离更小
				//找到新的最短路径 并且不构成回路的顶点
				min = dis[i];
				index = i;
			}
		}
		//更新
		already_arr[index] = 1;
		return index;
	}
	
	//显示最后的结果
	public void show() {
		System.out.println("====");
		System.out.println(Arrays.toString(already_arr)+"already_arr");
		System.out.println("====");
		System.out.println(Arrays.toString(pre_visited)+"pre_visited");
		System.out.println("====");
		System.out.println(Arrays.toString(dis)+"dis");

	}
}
迪杰斯特拉(Dijkstra)算法是一种寻找图中两点间最短路径的经典算法,适用于无向图和有向图,特别是当边权表示距离、费用或其他成本时。算法的基本思想是从起点开始逐步探索邻接节点,并始终选择当前已访问节点到未访问节点中代价最小的一条边作为下一步的前进方向。 在MATLAB中实现迪杰斯特拉算法通常涉及以下几个步骤: 1. **初始化**:创建一个二维数组或矩阵来存储各顶点之间的距离,将所有初始值设置为无穷大,除了起点到自身的距离设置为0;创建一个布尔型数组记录哪些节点已经被处理过。 2. **选取最小距离节点**:从未被处理过的节点中选出距离起点最近的一个节点作为当前节点。 3. **更新距离**:对于当前节点的所有相邻节点,如果从起点通过当前节点到相邻节点的距离比之前记录的距离更小,则更新这个距离。 4. **标记已处理节点**:将当前节点标记为已经处理过。 5. **重复步骤2至4**,直到所有节点都被处理或找到目标节点。 MATLAB代码示例: ```matlab function [shortestPaths, processedNodes] = dijkstra(graphMatrix, startNode) % graphMatrix 是一个邻接矩阵,其中非零元素表示两个节点间的距离。 % startNode 是起始节点的位置。 % shortestPaths 和 processedNodes 分别返回最短路径矩阵和处理节点状态。 n = size(graphMatrix, 1); visited = false(n, 1); % 初始化未访问节点标志位 distances = inf(1, n); % 初始距离设为无穷大 distances(startNode) = 0; % 起始节点距离设为0 for i = 1:n-1 current = find(~visited & (distances == min(distances(~visited))), 1); visited(current) = true; for j = 1:n if ~visited(j) && graphMatrix(current, j) ~= 0 newDist = distances(current) + graphMatrix(current, j); if newDist < distances(j) distances(j) = newDist; end end end end shortestPaths = distances; processedNodes = visited; ``` **相关问题**: 1. **如何优化迪杰斯特拉算法**?在大数据集上运行时,可以考虑使用优先队列来加速查找下一个最短路径候选节点的过程。 2. **迪杰斯特拉算法与贝尔曼-福特算法的区别是什么**?贝尔曼-福特算法可以在存在负权重边的情况下求解最短路径,而迪杰斯特拉算法不支持负权重边。 3. **如何将迪杰斯特拉算法应用到实际问题中**?比如网络路由优化、地图导航系统中的路径规划等场景,都可以利用此算法来找到从源点到所有其他点的最短路径。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值