Dijkstra算法——超~~详细!!

Dijkstra算法

_ ** 时隔多月,我又回来了!**_
今天下午久违的又学了会儿算法,又重新学习了一遍Dijkstra,这是第三次重新学习Dijkstra(以前学的都忘完了>_<).
废话先不bb,上代码。

#include<bits/stdc++.h>
using namespace std;
#define INF 9999999
#define M 1000
int d[M];
int p[M]={0};
int con[M][M];
int n,line;           //n点数,边数line 

struct node{
	char name;
}w[M];
void Dijkstra(int v,int *d,int p[],int con[M][M]) //初始点v 
{
	int vis[M];
	for(int i=1;i<=n;i++)        //第一步,确定与初始点v连接的点的路径 
	{
		d[i]=con[v][i];
		vis[i]=0;               //vis初始化 
		if(d[i]!=INF)
		p[i]=v;
	}
	d[v]=0;                     //对第一个点初始化 
	vis[v]=1;
	for(int i=1;i<=n;i++)       //第二布,两重循环 ,每次循环又分两步 。判断所有点 
	{
		int a=INF,id=v;
		for(int j=1;j<=n;j++) //1、找出该次循环中距离最小的点, 该点可能是一条新的路径 
		{
			if(d[j]<a && !vis[j])
			{
				a=d[j];       //a确定值 
				id=j;         //id确定点的下标 
			}
		}        
		vis[id]=1;              //已判断过 ,已经走过 
		for(int j=1;j<=n;j++)   //2、 从此时距离最短的点出发,更新与id相连的点的值,有两种情况 
		{                                     
			if(!vis[j] && con[id][j]<INF)  
			{
				int newdis=d[id]+con[id][j];
				if(newdis<d[j])         //根据 newdis与d[j]判断 
				{                     
					d[j]=newdis;
					p[j]=id;
				}	
			}
		}
	}
}
int idex(char a)
{
	for(int i=1;i<M;i++)
		if(w[i].name==a)
			return i;
}
void fun(int *p,char fist,char last)
{
	char x[M];
	int f=idex(fist),l=idex(last);
	cout<<"从"<<fist<<"到"<<last<<"的最短路径为:\n";
	x[0]=last;
	int y=1;
	int t=p[l];
	while(t!=f)
	{
		x[y++]=w[t].name;
		t=p[t];
	}
	cout<<fist;
	for(int i=y-1;i>=0;i--)
	cout<<"->"<<x[i];
	cout<<"\n";
}
int main()
{
	char a,b;
	int dis;
	cout << "************算法6.10 迪杰斯特拉算法**************\n"; 
	cout<<"请输入总点数,总边数:";
	cin>>n>>line;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			con[i][j]=INF;
	for(int i=1;i<=n;i++)
	{
		cout<<"请输入第"<<i<<"个点:";
		cin>>w[i].name;
	}
	for(int i=1;i<=line;i++)
	{
		cout<<"请输入第"<<i<<"条边:";
		cin>>a>>b>>dis;
		int a1=idex(a),b1=idex(b);
		if(dis<INF)
		{
			con[a1][b1]=dis;
			con[b1][a1]=dis;
		}
	}	
	cout << "*****无向网G创建完成!*****\n" ;
	for(int i=1;i<=n;i++)
		d[i]=INF;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(con[i][j]==INF)
			cout<<"∞ ";
			else
			cout<<con[i][j]<<" ";
		}
		printf("\n");
	}
	cout<<"请输入起点和终点:";
	cin>>a>>b;
	Dijkstra(idex(a), d, p, con);
	cout << a<<"到最后"<<b<<"的最短路径长度为: " << d[idex(b)] <<"\n";	
	fun(p,a,b); 
	return 0;
} 
这次学习总结了Dijkstra算法模板函数的几个主要步骤,因为这个函数没有用到递归,只		  
用了两个循环,因此可以分为从上到下的两步。
Dijkstra算法模板函数主要有两步:
一、
	确定与初始点v连接的点的路径 ,检查所有与初始点连接的点并更新他们的d[i]值。
二、
	一个二重嵌套循环,每次for循环里又分两步:
	1、
		找出此次循环中(d[i]中)距离值最小的,并分别用id,a记录该点对应的下标与d[i].
	2、
		以这个点(id)为初始点,更新所有与该点相连通的点(d数组).
重复第二步。

以上。

Dijkstra算法是一种用于在加权图中找到最短路径的算法,它可以处理没有负权边的图。算法的基本思想是,从源点开始,逐步增加到其他顶点的距离,直到找到最短路径为止。Dijkstra算法采用贪心策略,每次找到距离源点最近的一个未被访问的顶点,并更新其他顶点到源点的距离。 在Java中实现Dijkstra算法通常需要使用优先队列来优化查找当前距离源点最近顶点的过程。以下是Dijkstra算法的Java实现的一个简单例子: ```java import java.util.*; class Dijkstra { // 图的顶点数量 private static final int N = 9; // Dijkstra算法的实现 public static void dijkstra(int[][] graph, int startVertex) { // 记录源点到每个顶点的最短路径 int[] dist = new int[N]; // 初始化距离数组,所有顶点距离设置为无穷大 Arrays.fill(dist, Integer.MAX_VALUE); // 用于标记顶点是否被访问过 boolean[] visited = new boolean[N]; // 起始点到自身的距离是0 dist[startVertex] = 0; // 用优先队列优化查找最小距离的顶点 PriorityQueue<Integer> pq = new PriorityQueue<>(Comparator.comparingInt(i -> dist[i])); // 将起始点加入优先队列 pq.add(startVertex); while (!pq.isEmpty()) { // 从优先队列中选出距离最小的顶点 int u = pq.poll(); // 如果这个顶点已经被访问过,跳过 if (visited[u]) continue; // 标记顶点为已访问 visited[u] = true; // 遍历所有邻接的顶点 for (int v = 0; v < N; v++) { // 如果顶点u到顶点v存在边,并且顶点v未被访问 if (graph[u][v] != 0 && !visited[v]) { // 计算源点通过顶点u到顶点v的路径长度 int newDist = dist[u] + graph[u][v]; // 如果新的路径长度小于当前记录的路径长度,则更新之 if (newDist < dist[v]) { dist[v] = newDist; // 将顶点v加入优先队列 pq.add(v); } } } } // 输出从源点到每个顶点的最短路径长度 for (int i = 0; i < N; i++) { System.out.println("Distance from vertex " + startVertex + " to vertex " + i + " is " + dist[i]); } } public static void main(String[] args) { // 示例图的邻接矩阵表示 int[][] graph = { {0, 4, 0, 0, 0, 0, 0, 8, 0}, {4, 0, 8, 0, 0, 0, 0, 11, 0}, {0, 8, 0, 7, 0, 4, 0, 0, 2}, {0, 0, 7, 0, 9, 14, 0, 0, 0}, {0, 0, 0, 9, 0, 10, 0, 0, 0}, {0, 0, 4, 14, 10, 0, 2, 0, 0}, {0, 0, 0, 0, 0, 2, 0, 1, 6}, {8, 11, 0, 0, 0, 0, 1, 0, 7}, {0, 0, 2, 0, 0, 0, 6, 7, 0} }; // 从顶点0开始计算最短路径 dijkstra(graph, 0); } } ``` 在这个例子中,`graph`是一个图的邻接矩阵表示,`dijkstra`方法实现了Dijkstra算法,`main`方法用于测试算法。请注意,这个例子假设图是用邻接矩阵表示的,并且顶点编号从0开始。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值