【问题标题】:How to start topological sort after a certain element in JavaScript?如何在JavaScript中的某个元素之后开始拓扑排序?
【发布时间】:2022-11-16 06:42:56
【问题描述】:

我用 JavaScript 拼凑了这种拓扑排序,并有一个基于 this post 的图表:

const graph = {
  edges: {
    c: ['d', 'f'],
    d: ['e'],
    f: ['e'],
    a: ['b', 'c'],
    b: ['d', 'e'],
  }
}

// Calcuate the incoming degree of each vertex
const vertices = Object.keys(graph.edges)
const inDegree = {}
for (const v of vertices) {
  const neighbors = graph.edges[v]
  neighbors?.forEach(neighbor => {
    inDegree[neighbor] = inDegree[neighbor] + 1 || 1
  })
}

const queue = vertices.filter((v) => !inDegree[v])
const list = []

while (queue.length) {
  const v = queue.shift()
  const neighbors = graph.edges[v]

  list.push(v)

  // adjust the incoming degree of its neighbors
  neighbors?.forEach(neighbor => {
    inDegree[neighbor]--

    if (inDegree[neighbor] === 0) {
      queue.push(neighbor)
    }
  })
}

console.log(list)

99% 确定这是 JS 中拓扑排序的正确实现。

我有兴趣进行热模块重新加载,并且有兴趣模拟更新模块图中的相关节点。所以说d更新了。然后我们不关心abc,它们很好,我们只关心更新d和未来的节点然后是e,顺序是[ d, e ]。我们不关心 f,因为它不与 d 内联。

我如何更新此topsort函数以获取一个键(顶点/节点),并从那时起,包括元素,所以如果我通过d,我得到[ d, e ]

是像 list.slice(list.indexOf('d')) 一样简单,还是通用/稳健的解决方案更棘手?

我不认为这是正确的,因为如果我为模块 b 这样做,我们应该只需要更新 [ b, d, e ],但我的解决方案包括 c,这是不正确的。不知道如何解决这个问题。

【问题讨论】:

  • 如果 d 更改并且结果包括 [d,f,e],其中包括 f 因为它提供 e,那么看起来如果更新 b,则 [b,c,d,f,e]`应该是解决方案,因为 bc 都提供 d,不是吗?
  • @Trentium btilly 说的对,应该是[ 'b', 'd', 'e' ]
  • 然后 d 的变化导致 [d, e] 而不是 [d,f,e],对吗?
  • 是的,你是对的!哈,混乱。更新。

标签: javascript algorithm sorting graph topological-sort


【解决方案1】:

首先你需要一个优先队列。我只是借用Efficient way to implement Priority Queue in Javascript?来回答这个问题。

现在

const vertexPosition = {};
for (let [index, value] of list.entries()) {
  vertexPosition[value] = index;
}

function fromVertex (vertex) {
  let answer = [];
  seen = {vertex: 1};
  let heap = [];
  MinHeap.push(heap, [vertexPosition[vertex], vertex]);

  while (0 < heap.length) {
    let [position, nextVertex] = MinHeap.pop(heap);
    answer.push(nextVertex);
    graph.edges[nextVertex]?.forEach(futureVertex => {
      if (! seen[futureVertex]) {
        seen[futureVertex] = 1;
        MinHeap.push(heap, [vertexPosition[futureVertex], futureVertex]);
      }
    })
  }

  return answer;
}

现在fromVertex('b') 给了我们[ 'b', 'd', 'e' ]。 (与您的预期不同,因为没有 c 也意味着我们不需要 f。)

【讨论】:

  • 非常好,谢谢!有点让我头疼,将不得不阅读MinHeap和优先级队列。介意解释为什么需要优先级队列,和/或如何使用它?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-08
  • 2021-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多