【JavaScript算法实践】最短路径算法


前言

最短路问题是图问题中的经典问题,这类问题在生活中非常常见,我们(特别是生活在大城市的人)出门在外,无论是驾车还是乘坐公共交通工具,甚至步行,都会求助于高德地图、百度地图等定位和导航程序。我们可能会有其他的考虑:例如如何乘车、换乘?如何避开拥堵路段?但根本的问题仍然是:哪条路径最短?
在图问题中,这一问题对应的算法被称为最短路径算法。本文介绍其中两种非常著名算法的JavaScript实现:
Dijkstra算法和Floyd-Warshall算法
关于Dijkstra算法 和 Floyd-Warshall算法可以参考以下博文
Dijkstra算法

Floyd-Warshall算法


一、Dijkstra算法

Dijkstra算法是一种计算从单个源到所有其他源的最短路径的贪心算法,这意味着我们可以用它来计算从图的一个顶点到其余各顶点的最短路径

考虑下图:
在这里插入图片描述
我们来看看如何找到顶点A和其余顶点之间的最短路径。但首先,我们需要声明表示上图的邻接矩阵,如下所示:

var graph = [[0,2,4,0,0,0],
            [0,0,2,4,2,0],
            [0,0,0,0,3,0],
            [0,0,0,0,0,2],
            [0,0,0,3,0,2],
            [0,0,0,0,0,0]]

算法实现

下面给出Dijkstra算法的实现:

this.dijkstra = function(src){ //输入参数src为源节点索引,例如A点的索引是0,B点是1
	var dist = [], //最短路径距离
	visited = [], //已访问
	length = this.graph.length //最长路径距离
	
	for(var i = 0; i < length; i++){
		dist[i] = Infinity   //先初始化为无穷大
		visited[i] = false // 初始化标记均未访问
	}
	dist[src] = 0 //起点最短距离设置为0
	
	for(var i = 0; i < length-1; i++){
		var u = minDistance(dist, visited) //寻找最短路
		visited[u] = true; //标记为已访问
		for(var v = 0; v < length; v++){
			if(!visited[v] && this.graph[u][v] != 0 && dist[u] != Infinity  &&
			dist[u] + this.graph[u][v] < dist[v]) {
				dist[v] = dist[u] + this.graph[u][v] //若找到更短路,更新
			}
		}
	}
	return dist;//处理完所有节点,返回源点到其他顶点的最短路径距离向量
}

计算顶点间最短路径minDistance,需要搜索dist向量中的最小值,返回它在数组中的索引:

var minDistance = function(dist, visited){
	var min = Infinity, minIndex = -1
	for(var v = 0; v < dist.length; v++){
		if(visited[v] == false && dist[v] <= min){
			min = dist[v]
			minIndex = v
		}
	}
	return minIndex
}

若选A为源节点,对本节开始的图执行以上算法

this.dijkstra(0)

会得到如下输出:
在这里插入图片描述
说明:本算法实现只求得了源节点到其他节点的最短路长度,没有给出具体路径。

二、Floyd-Warshall 算法

Floyd-Warshall算法是一种计算图中所有最短路径的动态规划算法。通过该算法,我们可以找出从所有源到所有顶点的最短路径。

算法实现

this.floydWarshall = function(){
	var dist = [],
	length = this.graph.length,
	i,j,k
	for(i = 0; i < length; i++){
		dist[i] = []
		for(j = 0; j < length; j++){
			//录入一步直达路径
			if(this.graph[i][j] == 0 && i != j) {
				dist[i][j] = Infinity
			}else{
				dist[i][j] = this.graph[i][j]
			} 
			console.log(dist[i][j])
		}
	}
	for(k = 0; k < length; k++){ //k是中间节点
		for(i = 0; i < length; i++){ //i是起点
			for(j = 0; j < length; j++){ //j是终点
				if((dist[i][k] + dist[k][j]) < dist[i][j]) //如果i经过k,到达j的路径比已有的最短路径更短
					dist[i][j] = dist[i][k] + dist[k][j] //则更新
			}
		}
	}
	return dist
}

this.floydWarshall()

会得到如下输出:

在这里插入图片描述
其中,Infinity代表顶点 i 到 j 的最短路径不存在。

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
很抱歉,根据提供的引用内容,我没有找到关于最短路径算法和Vue3的相关信息。但是,最短路径算法是一种经典的算法,常用于计算网络中两点之间的最短路径。在Vue3中,可以使用JavaScript实现最短路径算法。以下是一个使用Dijkstra算法计算最短路径JavaScript代码示例: ```javascript function dijkstra(graph, start, end) { const distances = {}; const visited = {}; const previous = {}; let path = []; // 初始化距离和前置节点 for (let vertex in graph) { distances[vertex] = Infinity; previous[vertex] = null; } distances[start] = 0; // 找到最短路径 while (Object.keys(visited).length !== Object.keys(graph).length) { let currentVertex = null; let shortestDistance = Infinity; for (let vertex in graph) { if (!visited[vertex] && distances[vertex] < shortestDistance) { currentVertex = vertex; shortestDistance = distances[vertex]; } } for (let neighbor in graph[currentVertex]) { let tentativeDistance = shortestDistance + graph[currentVertex][neighbor]; if (tentativeDistance < distances[neighbor]) { distances[neighbor] = tentativeDistance; previous[neighbor] = currentVertex; } } visited[currentVertex] = true; } // 构建路径 let currentVertex = end; while (currentVertex !== start) { path.unshift(currentVertex); currentVertex = previous[currentVertex]; } path.unshift(start); return { distances, path }; } // 示例 const graph = { A: { B: 2, C: 1 }, B: { A: 2, D: 3, E: 2 }, C: { A: 1, F: 3 }, D: { B: 3 }, E: { B: 2, F: 1 }, F: { C: 3, E: 1 }, }; const { distances, path } = dijkstra(graph, 'A', 'F'); console.log(distances); // 输出:{ A: 0, B: 2, C: 1, D: 5, E: 4, F: 3 } console.log(path); // 输出:[ 'A', 'C', 'F' ] --相关问题--:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值