如何获取指向javascript对象属性的链接数

时间:2019-03-18 12:25:34

标签: javascript arrays json graph-algorithm

我有此数据:

const main = 'test1';
const data = [
  {
    from: 'test1',
    to: 'test2'
  },
  {
    from: 'test2',
    to: 'test3'
  },
  {
    from: 'test3',
    to: 'test4'
  },
  {
    from: 'test4',
    to: 'test2'
  },
  {
    from: 'test1',
    to: 'test4'
  }
];

我想获取到主节点的链接数(在本例中为 test1 )。例如,如果我们查看节点 test3 ,则需要2个链接才能到达 test1

test3→test2→test1

与节点 test2 相同,需要1个链接才能到达 test1

什么是最好的计算方法?最后,我希望最长个链接到 test1 。在示例情况下为3:

test3→test2→test4→test1

2 个答案:

答案 0 :(得分:2)

您需要访问每个可能的路径。但是,如果遇到一个循环并且目标节点可达,则最长距离变为无穷远,因为一个循环可能会经历任意次。

要访问所有路径,可以使用递归函数。

这里是一个:

function find(data, sourceName, targetName) {
    // Create hash data structure keying nodes by their name
    const map = new Map(data.map(({from}) => [from, []]));
    data.forEach(({from,to}) => map.get(from).push(map.get(to)));
    // If links are supposed to be undirected, allowing traversal in both directions
    //   then uncomment this:
    // data.forEach(({from,to}) => map.get(to).push(map.get(from)));
    const target = map.get(targetName);
    // Recursive function
    function recur(node) {
        if (node === target) return 0; // Found target
        if (node.visited) { // Cycle; mark node for detection during backtracking 
            node.onCycle = true;
            return -Infinity;
        }
        node.visited = true;
        let dist = 1 + Math.max(...node.map(recur)); // Maximise path length
        node.visited = false;
        // Leave out next line if longest path should not include cycles
        if (node.onCycle && dist > 0) return Infinity; // Solution path can have cycles
        return dist;
    }
    const dist = recur(map.get(sourceName)); // Start!
    return dist < 0 ? null : dist; // Return null when target cannot be reached
}

const data = [{from: 'test1', to: 'test2'},{from: 'test2', to: 'test3'},{from: 'test3',to: 'test4'},{from: 'test4',to: 'test2'},{from: 'test1',to:'test4'}];
const longestDist = find(data, 'test1', 'test3');
console.log(longestDist);

请注意,此解决方案将不会继续搜索通过目标节点的搜索,然后尝试再次从那里找到它(通过一个循环)。换句话说,它假设路径只能包含目标作为其最后一个节点,而不是多次。

如果要排除具有循环的路径,请删除返回Infinity作为距离的行。

代码假定链接为定向。如果将链接理解为双向链接(又称​​ undirected ),则意味着如果指定了一个方向,则也可以在不明确将其包含为镜像链接的情况下提供相反的方向,然后取消注释上面的代码中的第二forEach行。

答案 1 :(得分:1)

您的问题可以用图论术语重新定义:“ test1”,“ test2”,...是顶点,数据数组包含边(对“ from-to”对)-因此我们有了图-找到最长的路径图中的是NP难题-wiki。因此,您需要检查所有可能的路径以找到最长的