JavaScript 中的最短路径

2024-05-14

几周来我一直在寻找一种在 JavaScript 中计算最短路径的方法。我一直在玩书数据结构和算法作者:格罗纳(Groner)(名字恰如其分)https://github.com/loiane/javascript-datastructs-algorithms/tree/master/chapter09 https://github.com/loiane/javascript-datastructures-algorithms/tree/master/chapter09.

我不断发现的问题是代码是如此定制,以至于几乎不可能重写以产生所需的结果。我希望能够获得从任何给定顶点到任何其他顶点的最短路径,而不是像格罗纳编码的那样,只是从 A 开始的所有内容的列表。例如,我希望能够获得从F 到 B,或从 C 到 A。

完整代码在这里:http://jsfiddle.net/8cn7e2x8/ http://jsfiddle.net/8cn7e2x8/

有人可以帮忙吗?

var graph = new Graph();
var myVertices = ['A','B','C','D','E','F'];
for (var i=0; i<myVertices.length; i++) {
    graph.addVertex(myVertices[i]);
}
graph.addEdge('A', 'B');
graph.addEdge('B', 'C');
graph.addEdge('B', 'E');
graph.addEdge('C', 'D');
graph.addEdge('C', 'E');
graph.addEdge('C', 'G');
graph.addEdge('D', 'E');
graph.addEdge('E', 'F');

graph.dfs();

console.log('********* sortest path - BFS ***********');
var shortestPathA = graph.BFS(myVertices[0]);

//from A to all other vertices
var fromVertex = myVertices[0];

for (i = 1; i < myVertices.length; i++) {
    var toVertex = myVertices[i],
    path = new Stack();
    for (var v = toVertex; v !== fromVertex; v = shortestPathA.predecessors[v]) {
        path.push(v);
    }
    path.push(fromVertex);
    var s = path.pop();
    while (!path.isEmpty()) {
        s += ' - ' + path.pop();
    }
    console.log(s);
}

首先让我们指出,如果图未加权,广度优先搜索 (BFS) 会计算来自给定源顶点的最短路径。换句话说,我们将路径的长度视为路径中边的数量。

这是构建未加权图的简单方法:

function Graph() {
  var neighbors = this.neighbors = {}; // Key = vertex, value = array of neighbors.

  this.addEdge = function (u, v) {
    if (neighbors[u] === undefined) {  // Add the edge u -> v.
      neighbors[u] = [];
    }
    neighbors[u].push(v);
    if (neighbors[v] === undefined) {  // Also add the edge v -> u so as
      neighbors[v] = [];               // to implement an undirected graph.
    }                                  // For a directed graph, delete
    neighbors[v].push(u);              // these four lines.
  };

  return this;
}

请注意,我们已经实现了无向图。正如内联注释中提到的,您可以修改代码以通过删除四行来构造有向图addEdge功能。

BFS 的这种实现在有向图上同样可以很好地工作:

function bfs(graph, source) {
  var queue = [ { vertex: source, count: 0 } ],
      visited = { [source]: true },
      tail = 0;
  while (tail < queue.length) {
    var u = queue[tail].vertex,
        count = queue[tail++].count;  // Pop a vertex off the queue.
    print('distance from ' + source + ' to ' + u + ': ' + count);
    graph.neighbors[u].forEach(function (v) {
      if (!visited[v]) {
        visited[v] = true;
        queue.push({ vertex: v, count: count + 1 });
      }
    });
  }
}

为了找到两个给定顶点之间的最短路径并沿路径显示顶点,我们在探索图形时必须记住每个顶点的前趋:

function shortestPath(graph, source, target) {
  if (source == target) {   // Delete these four lines if
    print(source);          // you want to look for a cycle
    return;                 // when the source is equal to
  }                         // the target.
  var queue = [ source ],
      visited = { [source]: true },
      predecessor = {},
      tail = 0;
  while (tail < queue.length) {
    var u = queue[tail++],  // Pop a vertex off the queue.
        neighbors = graph.neighbors[u];
    for (var i = 0; i < neighbors.length; ++i) {
      var v = neighbors[i];
      if (visited[v]) {
        continue;
      }
      visited[v] = true;
      if (v === target) {   // Check if the path is complete.
        var path = [ v ];   // If so, backtrack through the path.
        while (u !== source) {
          path.push(u);
          u = predecessor[u];          
        }
        path.push(u);
        path.reverse();
        print(path.join(' &rarr; '));
        return;
      }
      predecessor[v] = u;
      queue.push(v);
    }
  }
  print('there is no path from ' + source + ' to ' + target);
}

以下代码片段在您在问题中给出的图表上演示了这些操作。首先,我们找到从 到所有可到达的顶点的最短路径A。然后我们找到最短路径B to G和来自G to A.

function Graph() {
  var neighbors = this.neighbors = {}; // Key = vertex, value = array of neighbors.

  this.addEdge = function (u, v) {
    if (neighbors[u] === undefined) {  // Add the edge u -> v.
      neighbors[u] = [];
    }
    neighbors[u].push(v);
    if (neighbors[v] === undefined) {  // Also add the edge v -> u in order
      neighbors[v] = [];               // to implement an undirected graph.
    }                                  // For a directed graph, delete
    neighbors[v].push(u);              // these four lines.
  };

  return this;
}

function bfs(graph, source) {
  var queue = [ { vertex: source, count: 0 } ],
      visited = { [source]: true },
      tail = 0;
  while (tail < queue.length) {
    var u = queue[tail].vertex,
        count = queue[tail++].count;  // Pop a vertex off the queue.
    print('distance from ' + source + ' to ' + u + ': ' + count);
    graph.neighbors[u].forEach(function (v) {
      if (!visited[v]) {
        visited[v] = true;
        queue.push({ vertex: v, count: count + 1 });
      }
    });
  }
}

function shortestPath(graph, source, target) {
  if (source == target) {   // Delete these four lines if
    print(source);          // you want to look for a cycle
    return;                 // when the source is equal to
  }                         // the target.
  var queue = [ source ],
      visited = { [source]: true },
      predecessor = {},
      tail = 0;
  while (tail < queue.length) {
    var u = queue[tail++],  // Pop a vertex off the queue.
        neighbors = graph.neighbors[u];
    for (var i = 0; i < neighbors.length; ++i) {
      var v = neighbors[i];
      if (visited[v]) {
        continue;
      }
      visited[v] = true;
      if (v === target) {   // Check if the path is complete.
        var path = [ v ];   // If so, backtrack through the path.
        while (u !== source) {
          path.push(u);
          u = predecessor[u];
        }
        path.push(u);
        path.reverse();
        print(path.join(' &rarr; '));
        return;
      }
      predecessor[v] = u;
      queue.push(v);
    }
  }
  print('there is no path from ' + source + ' to ' + target);
}

function print(s) {  // A quick and dirty way to display output.
  s = s || '';
  document.getElementById('display').innerHTML += s + '<br>';
}

window.onload = function () {
  var graph = new Graph();
  graph.addEdge('A', 'B');
  graph.addEdge('B', 'C');
  graph.addEdge('B', 'E');
  graph.addEdge('C', 'D');
  graph.addEdge('C', 'E');
  graph.addEdge('C', 'G');
  graph.addEdge('D', 'E');
  graph.addEdge('E', 'F');

  bfs(graph, 'A');
  print();
  shortestPath(graph, 'B', 'G');
  print();
  shortestPath(graph, 'G', 'A');
};
body { 
  font-family: 'Source Code Pro', monospace;
  font-size: 12px;
}
<link rel="stylesheet" type="text/css"
 href="https://fonts.googleapis.com/css?family=Source+Code+Pro">

<div id="display"></id>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JavaScript 中的最短路径 的相关文章

  • 如何检测浏览器是否支持自定义元素

    我正在查看 Modernizr 它应该有助于功能检测 这应该可以帮助确定您的网站是否与给定的 Web 浏览器兼容 但我没有看到任何表明我可以使用它来检测自定义 HTML 的内容我们在内容中创建和定义的元素 如果不是 Modernizr 我如
  • 在 javascript/jquery 中将光标更改为等待

    当调用函数时 如何让光标更改为此加载图标以及如何将其更改回 javascript jquery 中的普通光标 在你的 jQuery 中使用 body css cursor progress 然后又恢复正常 body css cursor d
  • Android 设备上的 PhoneGap 蓝牙插件

    我一直在尝试让 PhoneGap 工作的蓝牙插件 但我似乎不知道哪里出了问题 首先 我的测试设备是 Galaxy S3 GT 19305T 应用程序是使用PhoneGap CLI http docs phonegap com en 3 0
  • 在 Vue.js 中从父组件执行子方法

    目前 我有一个 Vue js 组件 其中包含其他组件的列表 我知道使用 vue 的常见方式是将数据传递给孩子 并从孩子向父母发出事件 但是 在这种情况下 我想在子组件中的按钮出现时执行子组件中的方法 parent被点击 哪种方法最好 一种建
  • 如何重置使用 JavaScript 更改的 CSS 属性?

    我的导航按钮的宽度从 100px 增加到 150px 当鼠标悬停在 nav li hover width 150px 但是使用 javascript 我已经做到了 无论选择哪个选项 宽度都将继续为 150px 当选择每个选项时 它会使其他选
  • 使用 useReducers 调度函数发送多个操作?

    使用时是否可以通过调度函数发送多个动作useReducer挂钩反应 我尝试向它传递一组操作 但这会引发未处理的运行时异常 明确地说 通常会有一个初始状态对象和一个减速器 如下所示 const initialState message1 nu
  • 使用模数按字母顺序对列表进行排序

    我在获取元素列表并按字母顺序对它们进行排序方面没有任何问题 但我很难理解如何使用模数来做到这一点 更新 这是按我的方式工作的代码 但是 我更喜欢下面提供的答案的可重用性 因此接受了该答案
  • 在 Wordpress 站点中进行 AJAX 调用时出现问题

    我在使用 Wordpress 站点功能的 AJAX 部分时遇到了一些问题 该功能接受在表单上输入的邮政编码 使用 PHP 函数来查找邮政编码是否引用特定位置并返回到该位置的永久链接 我的第一个问题是关于我构建的表单 现在我的表单操作是空白的
  • 除了更改标题之外,如何在 Firefox 中强制另存为对话框?

    有没有办法在 ff 中强制打开 www example com example pdf 的另存为对话框 我无法更改标题 如果您可以将文件以 Base64 格式输出到客户端 则可以使用 data uri 进行下载 location href
  • 为什么是 javascript:history.go(-1);无法在移动设备上工作?

    首先 一些背景 我有一个向用户呈现搜索页面 html 表单 的应用程序 填写标准并单击 搜索 按钮后 结果将显示在标准部分下方 在结果列表中 您可以通过单击将您带到新页面的链接来查看单个结果的详细信息 在详细信息页面中 我添加了一个 返回结
  • 如何将 Google Charts 与 Vue.js 库一起使用?

    我正在尝试使用 Vue js 库使用 Google Charts 制作图表 但我不知道如何添加到 div 这是我尝试做的 这是如何使用普通 javascript 添加图表 这是文档的代码示例 https developers google
  • Meteor - 从客户端取消服务器方法

    我正在通过服务器方法执行数据库计数 用户可以选择他们希望如何执行计数 然后调用该方法 我的问题是 计数可能需要一些时间 并且用户可能会在方法运行时改变主意并请求不同的计数 有什么方法可以取消调用的方法并运行新的计数吗 我认为 this un
  • 如何使输入字段和提交按钮变灰

    我想变灰这两件事 http doorsplit heroku com 歌曲输入字段和提交按钮 直到用户输入艺术家 有没有一种简单的方法可以通过 JQuery 来做到这一点 艺术家输入字段的id是 request artist 你可以这样做
  • 提交表单并重定向页面

    我在 SO 上看到了很多与此相关的其他问题 但没有一个对我有用 我正在尝试提交POST表单 然后将用户重定向到另一个页面 但我无法同时实现这两种情况 我可以获取重定向或帖子 但不能同时获取两者 这是我现在所拥有的
  • Angular 2+ 安全性;保护服务器上的延迟加载模块

    我有一个 Angular 2 应用程序 用户可以在其中输入个人数据 该数据在应用程序的另一部分进行分析 该部分仅适用于具有特定权限的人员 问题是我们不想让未经授权的人知道how我们正在分析这些数据 因此 如果他们能够在应用程序中查看模板 那
  • 为什么在 Internet Explorer 中访问 localStorage 对象会引发错误?

    我正在解决一个客户端问题 Modernizr 意外地没有检测到对localStorageInternet Explorer 9 中的对象 我的页面正确使用 HTML 5 文档类型 并且开发人员工具报告该页面具有 IE9 的浏览器模式和 IE
  • 如何在类似控制台的环境中运行 JavaScript?

    我正在尝试遵循这里的示例 http eloquentjavascript net chapter2 html http eloquentjavascript net chapter2 html and print blah 在浏览器中运行时
  • 模块构建失败(来自 ./node_modules/babel-loader/lib/index.js)Vue Js

    我从 GitHub 下载了一个我和我的朋友正在开发的项目 但是当我尝试运行时 npm run serve 我收到这个错误 src main js 中的错误 Module build failed from node modules babe
  • 如何更改此 jquery 插件的时区/时间戳?

    我正在使用这个名为 timeago 的插件 在这里找到 timeago yarp com 它工作得很好 只是它在似乎不同的时区运行 我住在美国东部 费城时区 当我将准确的 EST 时间放入 timeago 插件时 比如 2011 05 28
  • JQuery 图像上传不适用于未来的活动

    我希望我的用户可以通过帖子上传图像 因此 每个回复表单都有一个上传表单 用户可以通过单击上传按钮上传图像 然后单击提交来提交帖子 现在我的上传表单可以上传第一个回复的图像 但第二个回复的上传不起作用 我的提交过程 Ajax 在 php 提交

随机推荐

  • iPhone 点击时使 div 变暗

    当您的 div 附加了点击处理程序时 当点击该 div 时 iPhone 会使该 div 变暗 作为点击指示器 示例 在移动 Safari 上查看http jsbin com awejo3 4 http jsbin com awejo3 4
  • titledBorder 标题中的图标

    您好 是否可以在 titledBorder 的标题中放置一个图标 例如以下代码 import java awt GridLayout import javax swing JFrame import javax swing JLabel i
  • 有没有办法拉伸整个显示图像以适应给定的分辨率?

    我最近一直在使用pygame制作游戏 遇到了一个小问题 基本上 我希望能够将屏幕上的整个图像 我已经传输到它的所有内容 拉伸到用户将窗口大小调整到的分辨率 我在 pygame 和堆栈溢出的文档中搜索了很多 但我似乎找不到答案 这可能吗 我的
  • 在 Chapel 中计算矩阵的 rowSums

    继续我的教堂冒险 我有一个矩阵A var idx 1 n var adom idx idx var A adom int populate A var rowsums idx int 填充行和的最有效方法是什么 The 最有效率的解决方案很
  • Android计算两个日期之间的天数

    我编写了以下代码来查找两个日期之间的天数 startDateValue new Date startDate endDateValue new Date endDate long diff endDateValue getTime star
  • 如何在 Rails 3.2.1 版本中注释 Rails 模型

    我正在尝试遵循一些在线教程来在 Rails 中注释我的模型 然而 似乎所有教程都在谈论过时的注释版本或不正确的安装 这真是一团糟 到目前为止我已经尝试过以下方法 1 在 Gemfile 中添加此内容 gem annotate 2 4 0 2
  • 元素不适应 Firefox 上的

    使用 ES6 ish D3js 模块运行 Angular 6 应用程序会导致 Firefox 出现问题 Chromium Chrome Safari 和 IE Edge 工作正常 伪代码看起来类似于 生产代码可以在下面找到
  • 更改 WizardStep 按钮文本

    如何重命名每个按钮的文本 默认 步骤 1 到 步骤 n WizardStep 对于整个Wizard完成按钮的文本可以通过设置属性来设置finishButtonText 但没有类似的属性WizardStep 没有标准的方法 这是我实现它的方法
  • Angular - 为每个请求设置标头

    我需要在用户登录后为每个后续请求设置一些授权标头 要为特定请求设置标头 import Headers from angular2 http var headers new Headers headers append headerName
  • BigQuery 中使用 GROUPBY 的百分位函数

    在我的人口普查表中 我想按州分组 并为每个州获取县人口中位数和县数量 在 psql redshift 和 Snowflake 中 我可以这样做 psql gt SELECT state count county PERCENTILE CON
  • jquery ajax加载后丢失CSS

    大家知道如何解决 load Ajax 请求后的 css 问题吗 例如 如果我想从网页加载 DIV 在我的 Ajax 请求之后 container load path to div div id 我丢失了与该 div 关联的所有 css 和脚
  • 2D morton 码编码/解码 64 位

    如何将给定 x y 的莫顿代码 z 顺序 编码 解码为 32 位无符号整数 生成 64 位莫顿代码 反之亦然 我确实有 xy2d 和 d2xy 但仅适用于 16 位宽的坐标 产生 32 位莫顿数 在网上查了很多 但没有找到 请帮忙 如果您可
  • 为什么 clang 使用 -O0 生成低效的 asm(对于这个简单的浮点和)?

    我正在 llvm clang Apple LLVM 版本 8 0 0 clang 800 0 42 1 上反汇编此代码 int main float a 0 151234 float b 0 2 float c a b printf f c
  • 使 Recyclerview 固定高度并可滚动

    已解决以下检查答案 所以我试图为我的 Android 应用程序创建评论功能 我想在 recyclerview 中显示评论 然后在 recyclerview 下方有一个按钮和文本视图来添加评论 我想让 recyclerview 具有一定的高度
  • 如何使用 PowerShell 查找 CPU 和 RAM 使用情况?

    我试图让 PowerShell 提供 RAM 和 CPU 使用情况 但我无法弄清楚要使用哪个 WMI 类 我的计算机有两个处理器 因此拥有这两个处理器的信息会很有用 您还可以使用 Get Counter cmdlet PowerShell
  • libxml2 xmlChar * 到 std::wstring

    libxml2似乎将所有字符串存储在 UTF 8 中 如xmlChar xmlChar This is a basic byte in an UTF 8 encoded string It s unsigned allowing to pi
  • Windows 10 中的 npm 安装错误( npm install -g angular-cli )

    node v v4 5 0 npm v 5 0 1 有人在 Windows 10 中安装 angular cli 时遇到过这种问题吗 请尝试以下操作 step 0 运行这个命令 npm uninstall g angular cli npm
  • C++ 插件的“最适合”动态类型匹配

    我有一个几乎所有东西都是插件的架构 该架构以图形用户界面为基础 其中每个插件都由一个 表面 即用户可以通过其与插件交互的 UI 控件 表示 这些表面也是插件 每当添加新插件时 瘦主机都会自动确定哪个可用表面与其最匹配的 UI 如何在 C 中
  • 预处理后解析 C++ 源文件

    我正在尝试分析c 使用我定制的解析器的文件 写在c 在开始解析之前 我想摆脱所有 define 我希望源文件在预处理后可以编译 所以最好的方法是运行C Preprocessor在文件上 cpp myfile cpp temp cpp or
  • JavaScript 中的最短路径

    几周来我一直在寻找一种在 JavaScript 中计算最短路径的方法 我一直在玩书数据结构和算法作者 格罗纳 Groner 名字恰如其分 https github com loiane javascript datastructs algo