当前位置:首页 > JavaScript

js实现最短路径算法

2026-03-01 10:48:24JavaScript

Dijkstra算法实现

Dijkstra算法适用于加权图中寻找单源最短路径,要求权重为非负数。以下是JavaScript实现示例:

class PriorityQueue {
  constructor() {
    this.items = [];
  }
  enqueue(element, priority) {
    const queueElement = { element, priority };
    let added = false;
    for (let i = 0; i < this.items.length; i++) {
      if (queueElement.priority < this.items[i].priority) {
        this.items.splice(i, 0, queueElement);
        added = true;
        break;
      }
    }
    if (!added) this.items.push(queueElement);
  }
  dequeue() {
    return this.items.shift();
  }
  isEmpty() {
    return this.items.length === 0;
  }
}

function dijkstra(graph, startNode) {
  const distances = {};
  const previous = {};
  const pq = new PriorityQueue();

  Object.keys(graph).forEach(node => {
    distances[node] = node === startNode ? 0 : Infinity;
    previous[node] = null;
    pq.enqueue(node, distances[node]);
  });

  while (!pq.isEmpty()) {
    const { element: currentNode } = pq.dequeue();
    Object.entries(graph[currentNode]).forEach(([neighbor, weight]) => {
      const alt = distances[currentNode] + weight;
      if (alt < distances[neighbor]) {
        distances[neighbor] = alt;
        previous[neighbor] = currentNode;
        pq.enqueue(neighbor, alt);
      }
    });
  }
  return { distances, previous };
}

Floyd-Warshall算法实现

Floyd-Warshall算法可以计算图中所有顶点对之间的最短路径:

function floydWarshall(graph) {
  const dist = {};
  const vertices = Object.keys(graph);

  vertices.forEach(i => {
    dist[i] = {};
    vertices.forEach(j => {
      dist[i][j] = graph[i][j] || (i === j ? 0 : Infinity);
    });
  });

  vertices.forEach(k => {
    vertices.forEach(i => {
      vertices.forEach(j => {
        if (dist[i][j] > dist[i][k] + dist[k][j]) {
          dist[i][j] = dist[i][k] + dist[k][j];
        }
      });
    });
  });

  return dist;
}

A*搜索算法实现

A*算法结合了Dijkstra和启发式搜索,适用于路径规划:

function aStar(start, goal, graph, heuristic) {
  const openSet = new Set([start]);
  const cameFrom = {};
  const gScore = { [start]: 0 };
  const fScore = { [start]: heuristic(start, goal) };

  while (openSet.size > 0) {
    let current = null;
    let lowestFScore = Infinity;
    openSet.forEach(node => {
      if (fScore[node] < lowestFScore) {
        lowestFScore = fScore[node];
        current = node;
      }
    });

    if (current === goal) {
      return reconstructPath(cameFrom, current);
    }

    openSet.delete(current);
    graph[current].forEach(neighbor => {
      const tentativeGScore = gScore[current] + neighbor.cost;
      if (tentativeGScore < (gScore[neighbor.node] || Infinity)) {
        cameFrom[neighbor.node] = current;
        gScore[neighbor.node] = tentativeGScore;
        fScore[neighbor.node] = gScore[neighbor.node] + heuristic(neighbor.node, goal);
        if (!openSet.has(neighbor.node)) {
          openSet.add(neighbor.node);
        }
      }
    });
  }
  return null;
}

function reconstructPath(cameFrom, current) {
  const path = [current];
  while (cameFrom[current]) {
    current = cameFrom[current];
    path.unshift(current);
  }
  return path;
}

Bellman-Ford算法实现

该算法能处理负权边并检测负权环:

js实现最短路径算法

function bellmanFord(graph, start) {
  const distances = {};
  const predecessors = {};
  Object.keys(graph).forEach(node => {
    distances[node] = node === start ? 0 : Infinity;
    predecessors[node] = null;
  });

  for (let i = 0; i < Object.keys(graph).length - 1; i++) {
    Object.entries(graph).forEach(([u, edges]) => {
      Object.entries(edges).forEach(([v, weight]) => {
        if (distances[u] + weight < distances[v]) {
          distances[v] = distances[u] + weight;
          predecessors[v] = u;
        }
      });
    });
  }

  let hasNegativeCycle = false;
  Object.entries(graph).forEach(([u, edges]) => {
    Object.entries(edges).forEach(([v, weight]) => {
      if (distances[u] + weight < distances[v]) {
        hasNegativeCycle = true;
      }
    });
  });

  return { distances, predecessors, hasNegativeCycle };
}

使用注意事项

  • Dijkstra算法适用于非负权图,时间复杂度为O((V+E)logV)
  • Floyd-Warshall适用于稠密图,时间复杂度O(V³)
  • A*算法需要合适的启发式函数
  • Bellman-Ford能检测负权环但时间复杂度较高(O(VE))

根据具体场景选择合适算法,例如导航系统常用A*,网络路由常用Dijkstra,需要考虑负权值时使用Bellman-Ford。

标签: 最短算法
分享给朋友:

相关文章

php 实现共识算法

php 实现共识算法

PHP 实现共识算法的基础方法 共识算法是分布式系统中确保数据一致性的核心机制,PHP 可通过特定设计实现简化版本的共识逻辑。以下是常见实现方式: 基于Paxos的简化实现 Paxos 算法的 PH…

js实现基数算法

js实现基数算法

基数排序(Radix Sort)简介 基数排序是一种非比较型整数排序算法,通过逐位分配和收集实现排序。适用于整数或固定格式字符串,时间复杂度为O(nk),其中n是元素数量,k是数字位数。 实现基数排…

蚁群算法js实现

蚁群算法js实现

蚁群算法简介 蚁群算法(Ant Colony Optimization, ACO)是一种模拟蚂蚁觅食行为的启发式算法,常用于解决组合优化问题(如旅行商问题TSP)。蚂蚁通过信息素(pheromone)…

算法的js实现

算法的js实现

JavaScript 算法实现方法 排序算法 快速排序的实现: function quickSort(arr) { if (arr.length <= 1) return arr;…

js实现火焰算法

js实现火焰算法

火焰算法实现基础 火焰算法(Fire Effect)是一种模拟火焰燃烧效果的图形算法,常用于生成动态火焰视觉效果。在JavaScript中,可以通过Canvas或WebGL实现。 使用Canvas实…

php 实现排序算法

php 实现排序算法

冒泡排序 冒泡排序通过多次遍历数组,每次比较相邻元素并交换位置,将较大元素逐步移至数组末尾。 function bubbleSort($array) { $n = count($arra…