节点js中的图形数据结构

时间:2019-06-10 19:45:59

标签: javascript node.js data-structures graph

更新1:

我在https://medium.com/basecs/breaking-down-breadth-first-search-cebe696709d9处找到了BFS的示例,但遇到错误TypeError: Cannot read property 'left' of undefined。你能告诉我如何解决吗

function roadsAndLibraries(n, c_lib, c_road, cities) {
    console.log("roadsAndLibraries n--->", n);
    console.log("roadsAndLibraries c_lib--->", c_lib);
    console.log("roadsAndLibraries c_road--->", c_road);
    console.log("roadsAndLibraries cities--->", cities);
    var m = new Map();
    m.set('a', 2);
    m.set('b', 3);
    m.set('b', 3);
    m.set('b', 2);
    m.set('b', 1);

    console.log("map value--->", m);
        // Check that a root node exists.

    // if (rootNode === null) {
    //     return;
    // }

    // Check that a root node exists.
    if (n === null) {
        console.log("n root node--->", n);
        return;
    }

    // Create our queue and push our root node into it.
    // var queue = [];
    // queue.push(rootNode);

    // Create our queue and push our root node into it.
    var queue = [];
    queue.push(n);

    console.log(" queue.push--->", queue);


    while (queue.length > 0) {
        // Create a reference to currentNode, at the top of the queue.
        var currentNode = queue[0];

        // If currentNode has a left child node, add it to the queue.
        if (currentNode.left !== null) {
            queue.push(currentNode.left)
        }
        // If currentNode has a right child node, add it to the queue.
        if (currentNode.right !== null) {
            queue.push(currentNode.right)
        }
        // Remove the currentNode from the queue.
        queue.shift()
    }




}

图形代码

'use strict';

const fs = require('fs');

process.stdin.resume();
process.stdin.setEncoding('utf-8');

let inputString = '';
let currentLine = 0;

process.stdin.on('data', inputStdin => {
    inputString += inputStdin;
});

process.stdin.on('end', function() {
    inputString = inputString.replace(/\s*$/, '')
        .split('\n')
        .map(str => str.replace(/\s*$/, ''));

    main();
});

function readLine() {
    return inputString[currentLine++];
}

// Complete the roadsAndLibraries function below.
function roadsAndLibraries(n, c_lib, c_road, cities) {
    console.log("roadsAndLibraries n--->", n);
    console.log("roadsAndLibraries c_lib--->", c_lib);
    console.log("roadsAndLibraries c_road--->", c_road);
    console.log("roadsAndLibraries cities--->", cities);

var m = new Map();
    m.set('a', 2);
    m.set('b', 3);
    m.set('b', 3);
    m.set('b', 2);
    m.set('b', 1);

    console.log("map value--->", m);





}

function main() {
    const ws = fs.createWriteStream(process.env.OUTPUT_PATH);
    console.log("ws--->", ws);


    const q = parseInt(readLine(), 10);
    console.log("q--->", q);

    for (let qItr = 0; qItr < q; qItr++) {
        const nmC_libC_road = readLine().split(' ');
        console.log("nmC_libC_road--->", nmC_libC_road);

        const n = parseInt(nmC_libC_road[0], 10);
        console.log("n--->", n);


        const m = parseInt(nmC_libC_road[1], 10);
        console.log("m--->", m);

        const c_lib = parseInt(nmC_libC_road[2], 10);
        console.log("c_lib--->", c_lib);

        const c_road = parseInt(nmC_libC_road[3], 10);
        console.log("c_road--->", c_road);

        let cities = Array(m);
        console.log("cities--->", cities);

        for (let i = 0; i < m; i++) {
            cities[i] = readLine().split(' ').map(citiesTemp => parseInt(citiesTemp, 10));
        }

        const result = roadsAndLibraries(n, c_lib, c_road, cities);
        console.log("result--->", result);

        ws.write(result + '\n');
    }

    ws.end();
}

样本输出

ws---> WriteStream {
  _writableState:
   WritableState {
     objectMode: false,
     highWaterMark: 16384,
     finalCalled: false,
     needDrain: false,
     ending: false,
     ended: false,
     finished: false,
     destroyed: false,
     decodeStrings: true,
     defaultEncoding: 'utf8',
     length: 0,
     writing: false,
     corked: 0,
     sync: true,
     bufferProcessing: false,
     onwrite: [Function: bound onwrite],
     writecb: null,
     writelen: 0,
     bufferedRequest: null,
     lastBufferedRequest: null,
     pendingcb: 0,
     prefinished: false,
     errorEmitted: false,
     emitClose: false,
     bufferedRequestCount: 0,
     corkedRequestsFree:
      { next: null,
        entry: null,
        finish: [Function: bound onCorkedFinish] } },
  writable: true,
  _events: [Object: null prototype] {},
  _eventsCount: 0,
  _maxListeners: undefined,
  path:
   '/tmp/submission/20190610/18/32/hackerrank-e7eb8e7be2993c28875aad2bbb8d6292/0.userout',
  fd: null,
  flags: 'w',
  mode: 438,
  start: undefined,
  autoClose: true,
  pos: undefined,
  bytesWritten: 0,
  closed: false }
q---> 2
nmC_libC_road---> [ '3', '3', '2', '1' ]
n---> 3
m---> 3
c_lib---> 2
c_road---> 1
cities---> [ <3 empty items> ]
roadsAndLibraries n---> 3
roadsAndLibraries c_lib---> 2
roadsAndLibraries c_road---> 1
roadsAndLibraries cities---> [ [ 1, 2 ], [ 3, 1 ], [ 2, 3 ] ]
result---> undefined
nmC_libC_road---> [ '6', '6', '2', '5' ]
n---> 6
m---> 6
c_lib---> 2
c_road---> 5
cities---> [ <6 empty items> ]
roadsAndLibraries n---> 6
roadsAndLibraries c_lib---> 2
roadsAndLibraries c_road---> 5
roadsAndLibraries cities---> [ [ 1, 3 ], [ 3, 4 ], [ 2, 4 ], [ 1, 2 ], [ 2, 3 ], [ 5, 6 ] ]
result---> undefined

1 个答案:

答案 0 :(得分:0)

在我看来,您似乎无法理解问题的根源。我将尝试对其进行总结,并指出一些您需要考虑的事项。

城市图

为您提供了一个图形,其中每个节点是一个城市,一条边是两个城市之间的双向道路。这意味着您正在处理一个无向图,这意味着如果城市A和B之间存在一条边(=道路),则可以从A到B以及从B到A行驶。当然,您可以通过为每条道路创建两条边来用有向图表示这一点:一条从A到B,一条从B到A。但是我认为这不是必需的。

现在,您希望每个城市都拥有一个图书馆或通往拥有图书馆的城市的道路。您意识到,如果有两组没有通过任何道路链接的城市,则每个组至少需要一个图书馆。这样的城市集称为connected components of a graph。您将需要识别这些组件。它们将成为必须独立解决的问题的一部分。

访问图书馆的费用

第二个信息是在城市中重建图书馆的成本和修路的价格。当您试图最小化总成本时,这意味着您正在尝试重建尽可能少的道路和尽可能少的库。

您意识到,如果重建图书馆的成本小于或等于修建道路的成本,那么更便宜的选择是在每个城市建造图书馆。

在其他情况下,解决方案非常简单,但不那么容易看到。让我们考虑一个连接的组件。对于商品,我们假设城市A,B,C和D是此连接组件的节点。

A----B
|    |
C----D

您已经知道您将需要在其中一个城市上至少放置一个图书馆。让我们在城市A上放置一个图书馆。然后,由于我们处于连接的组件中,所以A有一些通往其他城市的道路(最少一条,最多3条)。对于具有将其连接到城市A的道路的城市而言,重建道路比建立新图书馆要便宜。因此,我们选择重建道路。现在,城市A和城市A的邻居(城市B和D)可以访问图书馆。然后,在A的邻居(城市B和C)中,将有通往尚未访问图书馆的城市的道路。在这种情况下,C和B都有通向D的道路。我们只需要一条道路就可以将D连接到A的图书馆。同样,修建一条通往可以访问图书馆的城市的道路要比修建道路便宜一个新的图书馆。

算法

通过传播到第一个节点的所有邻居逐渐连接城市的先前方法,则第一个节点的邻居(递归)的邻居是BFS。另外,BFS算法适用于查找图的连接部分。

如果您理解前面的解释,我认为您能够解决问题。您可以在图形上运行BFS算法。启动算法时,先计算1个图书馆,然后在每次连接到新城市时计算1条道路。当您完成BFS算法后,图中仍然有您尚未访问的城市时,请计算一个额外的图书馆,并从一个尚未探索的城市开始再次使用BFS。