Dijkstra算法实现(java),从建立有向图开始!

迪杰斯特拉算法是典型最短路径算法,用于计算图或网中某个特定顶点到其他所有顶点的最短路径。主要特点是以起始点为中心向外,层层扩展,直到扩展覆盖所有顶点。

那么废话不多说,开始建立有向图,建立图节点,对象有三个,代码注释了

class Mapnode{
	public ArrayList<Mapnode> inlist=new ArrayList<>();//入弧
	public ArrayList<Mapnode> outlist=new ArrayList<>();//出弧
	public String name;//写节点名字
}

手动写入节点,注意要按顺序写,因为节点的姓名和权值关系很大,不能跳着写,这里我加了判断,有兴趣的小伙伴可以适当改进,邻接矩阵大小可以设的很大,就不怕溢出了,这里我只设了6

public class Dijkstra {
	public static int[][] Adjacency=new int[6][6];//邻接矩阵,我是用来计算权值的
	public static HashMap<String, Integer> map=new HashMap<>();//本来是用来判断是否有重复节点,不过用不到了
	public static ArrayList<Mapnode> list=new ArrayList<>();//存放所有节点
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=1;
		
		
		while(true){
			if(n==1){
				Mapnode node=new Mapnode();
				node.name="v0";
				list.add(node);
				n++;
			}
			System.out.println("请问你要继续创建图节点吗(1/0)");
			int shuru=sc.nextInt();
			if(shuru==0){
				break;
			}else if(shuru==1){
				Mapnode node=new Mapnode();
				System.out.println("请输入节点姓名:(v0/v1),按顺序来");
				String name=sc.next();
				if(((int)name.charAt(1))-48!=list.size()){
					System.out.println(((int)name.charAt(1))-48!=list.size());
					System.out.println(name.charAt(1));
					System.out.println(list.size());
					System.out.println("输入错误,请重新输节点名称");
				}else {
					list.add(node);
					node.name=name;
					System.out.println("创建成功");
				}
			}else{
				System.out.println("请重新输入");
			}
		}
	}

运行结果图,我用的eclipse(

之后是节点之间的相连并设置权值大小,这里我直接用的某视频的值写入了,这里可以写进方法里,博主比较懒,直接写主函数里了(

		while(true){
			System.out.println("还要继续相连吗");
			int judge=sc.nextInt();
			if(judge==1){
				System.out.println("请输入要连接的节点");
				String node1=sc.next();
				System.out.println("请输入指向的节点");
				String node2=sc.next();
				System.out.println("请输入权值");
				int num=sc.nextInt();
				Adjacency[(int)node1.charAt(1)-48][(int)node2.charAt(1)-48]=num;
				Mapnode node=list.get((int)node1.charAt(1)-48);
				node.outlist.add(list.get((int)node2.charAt(1)-48));
				list.get((int)node2.charAt(1)-48).inlist.add(node);
				System.out.println("连接成功");
			}else{
				break;
			}
		}

 运行结果图,写入的值我直接给你了,省的你在写(我这么好,不给个赞说不过去吧(doge))

//1 v1 v2 1 1 v0 v1 10 1 v0 v4 5 1 v4 v2 9 1 v4 v3 2 1 v1 v4 2 1 v4 v1 3 1 v2 v3 4 1 v3 v0 7 1 v3 v2 6 0

输出连接图像,相信大家能理解这段,可以简化一点,也留给大家了(

		for(int i=0;i<list.size();i++){
			System.out.println(list.get(i).name);
			for(int j=0;j<list.get(i).outlist.size();j++){
				System.out.print("----"+Adjacency[(int)list.get(i).name.charAt(1)-48][(int)list.get(i).outlist.get(j).name.charAt(1)-48]+"---->"+list.get(i).outlist.get(j).name);
				System.out.println();
			}
		}

 结果图,中间是权值

 之后就是我们的缔结斯特拉算法了,首先输入起始节点,从起始节点开始,首先初始化dist(最短节点距离)遍历起始节点的出度,将每个出度节点的权值写入dist数组,将fina起始节点设置为true,代表此节点已经被找到了最短距离,然后写入路径前驱,路径前驱设置为当前最小路径的节点,之后循环找到fina为false的最小dist节点,从最小的dist入手,找到该节点并遍历该节点的出度,重新计算dist,也就是,该节点的dist加上该节点到出度节点的权值,比较大小,要是小于原来的dist就替换成更小的距离,并将该出度节点的前驱节点改为此节点,循环遍历即可

boolean []fina=new boolean[list.size()];//标记是否已找到最短路径
		int dist[]=new int[list.size()];//最短路径长度
		int path[]=new int[list.size()];//路径前驱
		for(int i=0;i<dist.length;i++){
			dist[i]=99999;
			path[i]=-1;
		}
		System.out.println("请输入起始的节点:");
		String start=sc.next();
		fina[(int)start.charAt(1)-48]=true;
		dist[(int)start.charAt(1)-48]=0;
		path[(int)start.charAt(1)-48]=-1;
		//初始化距离
		for(Mapnode i:list.get((int)start.charAt(1)-48).outlist){
			dist[(int)i.name.charAt(1)-48]=Adjacency[(int)start.charAt(1)-48][(int)i.name.charAt(1)-48];
			path[(int)i.name.charAt(1)-48]=(int)start.charAt(1)-48;
			System.out.println(Adjacency[(int)start.charAt(1)-48][(int)i.name.charAt(1)-48]);
		}
		//找到最短路径
		for(int j=0;j<list.size()-1;j++){
			int min[][]={{99999999,-1}};
			for(int i=0;i<dist.length;i++){
				if(fina[i]==false){
					if(min[0][0]>dist[i]){
						min[0][0]=dist[i];
						min[0][1]=i;
					}					
				}
			}
			fina[min[0][1]]=true;
			//从最短路径出手,找到相连的节点,重新计算最小值
			for(Mapnode i:list.get(min[0][1]).outlist){
				if(min[0][0]+Adjacency[min[0][1]][(int)i.name.charAt(1)-48]<dist[(int)i.name.charAt(1)-48]){
					dist[(int)i.name.charAt(1)-48]=min[0][0]+Adjacency[min[0][1]][(int)i.name.charAt(1)-48];
					path[(int)i.name.charAt(1)-48]=min[0][1];
				}
			}
			
		}
		for(int i=0;i<path.length;i++){
			System.out.println(list.get(i).name+" "+fina[i]+" "+dist[i]+" "+path[i]);
		}
		//成功了,迪杰斯特拉nb,总结一下,本算法只适用于权值全为正数的找最短路径算法
	}

看最后输出结果对比,谁的视频不用说了吧(,完全一致

最后博主想说的是缔结斯特拉算法只适用于权值为正的找最短路径问题,要是为负的话,需要Bellman-Ford算法,浏览多的话之后博主也会出的

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Dijkstra算法是一种用于计算最短路径的贪心算法。它可以应用于有向图和无向图,但是在本文中我们只考虑有向图的情况。下面是Java实现Dijkstra算法有向图的最短路径的示例代码: ```java import java.util.*; public class DijkstraAlgorithm { private final int MAX_VALUE = Integer.MAX_VALUE; // 定义一个最大值 public int[] dijkstra(int[][] graph, int start) { int n = graph.length; int[] distance = new int[n]; // 存储起点到每个顶点的距离 boolean[] visited = new boolean[n]; // 记录顶点是否已经被访问 Arrays.fill(distance, MAX_VALUE); // 初始化距离为最大值 distance[start] = 0; // 起点到自己的距离为0 for (int i = 0; i < n; i++) { int u = findMinDistance(distance, visited); // 找到当前未访问的距离最小的顶点 visited[u] = true; // 标记该顶点已经被访问 for (int v = 0; v < n; v++) { if (!visited[v] && graph[u][v] != MAX_VALUE && distance[u] != MAX_VALUE && distance[u] + graph[u][v] < distance[v]) { distance[v] = distance[u] + graph[u][v]; // 更新起点到该顶点的距离 } } } return distance; } // 找到当前未访问的距离最小的顶点 private int findMinDistance(int[] distance, boolean[] visited) { int minDistance = MAX_VALUE; int minIndex = -1; for (int i = 0; i < distance.length; i++) { if (!visited[i] && distance[i] < minDistance) { minDistance = distance[i]; minIndex = i; } } return minIndex; } public static void main(String[] args) { int[][] graph = { {0, 2, 4, MAX_VALUE, MAX_VALUE}, {MAX_VALUE, 0, 1, 4, 2}, {MAX_VALUE, MAX_VALUE, 0, MAX_VALUE, MAX_VALUE}, {MAX_VALUE, MAX_VALUE, MAX_VALUE, 0, 3}, {MAX_VALUE, MAX_VALUE, MAX_VALUE, MAX_VALUE, 0} }; int start = 0; DijkstraAlgorithm dijkstraAlgorithm = new DijkstraAlgorithm(); int[] distance = dijkstraAlgorithm.dijkstra(graph, start); System.out.println(Arrays.toString(distance)); } } ``` 在上面的示例代码中,我们使用一个二维数组来表示有向图的邻接矩阵,其中MAX_VALUE表示两个顶点之间没有连接。在dijkstra方法中,我们首先初始化起点到每个顶点的距离为最大值,然后遍历每个顶点,找到当前未访问的距离最小的顶点,并将该顶点标记为已访问。然后,我们遍历与该顶点相邻的顶点,并更新起点到这些顶点的距离。最后返回起点到每个顶点的最短距离数组。 在上述示例中,我们使用了一个findMinDistance方法来找到当前未访问的距离最小的顶点,并使用Arrays.fill方法将distance数组初始化为最大值。这里需要注意的是,我们使用了Integer.MAX_VALUE来表示两个顶点之间没有连接,因为在Dijkstra算法中,我们需要比较两个顶点之间的距离,而使用一个较大的值可以避免出现负权边的情况。 在main方法中,我们定义了一个有向图的邻接矩阵,然后调用dijkstra方法计算起点到每个顶点的最短距离,并输出结果。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值