图数据结构。程序输出不像我想要

时间:2016-07-16 20:51:40

标签: javascript graph

Graph

如果选择F到C,我的程序输出应该如下所示。

  

F,D,C费用:2

     

F,D,E,C成本:4

     

F,D,B,A,C成本:5

     

F,D,G,B,A,C成本:7

但是,我一直得到像这样的输出

  

F,D,C费用:2

我试图获得其他输出,但程序永远不会有效,这就像我得到的那样接近。

我错过了什么?

function calculateNow() {
  var g = new Graph();
  calculate();

  function Graph() {
    this.edges = {};

    this.addNode = function(label) {
      this.edges[label] = {};
    };

    this.addEdge = function(from, to, cost) {
      this.edges[from][to] = cost;
      this.edges[to][from] = cost;
    };

    this.calculatePaths = function(from, to, cost, paths) {
      if (g.edges[from][to]) {
        cost = g.edges[from][to];
        paths = paths.concat("," + to);
        g.displayPath(paths, cost);
      } else {
        next = getNextEdge(from);
        cost = cost + g.edges[from][next];
        paths = paths.concat("," + next);
        g.displayPath(paths, cost);

        if (next !== to) {
          g.calculatePaths(next, to, cost, paths);
        }
      }
    };

    function getNextEdge(from) {
      var res, cost = 999;
      if (g.edges[from]['A']) {
        cost = g.edges[from]['A'];
        res = 'A';
      }
      if (g.edges[from]['B'] && g.edges[from]['B'] <= cost) {
        cost = g.edges[from]['B'];
        res = 'B';
      }
      if (g.edges[from]['C'] && g.edges[from]['C'] <= cost) {
        cost = g.edges[from]['C'];
        res = 'C';
      }
      if (g.edges[from]['D'] && g.edges[from]['D'] <= cost) {
        cost = g.edges[from]['D'];
        res = 'D';
      }
      if (g.edges[from]['E'] && g.edges[from]['E'] <= cost) {
        cost = g.edges[from]['E'];
        res = 'E';
      }
      if (g.edges[from]['F'] && g.edges[from]['F'] <= cost) {
        cost = g.edges[from]['F'];
        res = 'F';
      }
      if (g.edges[from]['G'] && g.edges[from]['G'] <= cost) {
        cost = g.edges[from]['G'];
        res = 'G';
      }
      return res;
    }

    this.displayPath = function(path, cost) {
      var res = document.getElementById('result');
      res.innerHTML = path + " Cost: " + (cost*2);
    };

  }

  function calculate() {
    var from = document.getElementById('from').value;
    var to = document.getElementById('to').value;

    g.addNode('A');
    g.addNode('B');
    g.addNode('C');
    g.addNode('D');
    g.addNode('E');
    g.addNode('F');
    g.addNode('G');

    g.addEdge('A', 'B', 2);
    g.addEdge('A', 'C', 1);
    g.addEdge('B', 'D', 1);
    g.addEdge('B', 'G', 1);
    g.addEdge('C', 'D', 1);
    g.addEdge('C', 'E', 1);
    g.addEdge('D', 'E', 2);
    g.addEdge('D', 'F', 1);
    g.addEdge('D', 'G', 2);

    g.calculatePaths(from, to, 0, "" + from);
  }
}
Select two nodes:
<br />From
<select id="from">
  <option value='A'>A</option>
  <option value='B'>B</option>
  <option value='C'>C</option>
  <option value='D'>D</option>
  <option value='E'>E</option>
  <option value='F' selected>F</option>
  <option value='G'>G</option>
</select>To
<select id="to">
  <option value='A'>A</option>
  <option value='B'>B</option>
  <option value='C' selected>C</option>
  <option value='D'>D</option>
  <option value='E'>E</option>
  <option value='F'>F</option>
  <option value='G'>G</option>
</select>
<input type="button" onclick="calculateNow();" value="Calculate" />
<br/>
<br/><span id="result" />

1 个答案:

答案 0 :(得分:1)

代码中的逻辑问题是使用getNextEdge。似乎在每个节点上,您只挑选一条边进行探索,但根据您的预期输出,您似乎真的想要探索每个边缘。

这是我对代码的看法,将getNextEdge的使用替换为离开该节点的所有边缘的循环:

&#13;
&#13;
function Graph() {
  this.edges = {};

  this.addNode = function(label) {
    this.edges[label] = {};
  };

  this.addEdge = function(from, to, cost) {
    this.edges[from][to] = cost;
    this.edges[to][from] = cost;
  };

  this.calculatePaths = function(from, to, cost, path) {
    // Recursion base case: we're already at the destination node
    if (from === to) {
      this.displayPath(path, cost);
    } else {
      // Capture this, since it will be reassigned in the loop
      var that = this;
      Object.keys(this.edges[from]).forEach(function (next) {
        // Don't visit this node again if we already have
        for (var i = 0; i < path.length; i++) {
          if (path[i] === next) {
            return;
          }
        }

        // Recurse
        that.calculatePaths(next, to, cost + that.edges[from][next], path.concat([next]));
      });
    }
  };

  this.displayPath = function(path, cost) {
    console.log(path.join(", ") + ' Cost: ' + cost);
  };
}

function calculate(from, to) {
  var g = new Graph();

  g.addNode('A');
  g.addNode('B');
  g.addNode('C');
  g.addNode('D');
  g.addNode('E');
  g.addNode('F');
  g.addNode('G');

  g.addEdge('A', 'B', 2);
  g.addEdge('A', 'C', 1);
  g.addEdge('B', 'D', 1);
  g.addEdge('B', 'G', 1);
  g.addEdge('C', 'D', 1);
  g.addEdge('C', 'E', 1);
  g.addEdge('D', 'E', 2);
  g.addEdge('D', 'F', 1);
  g.addEdge('D', 'G', 2);

  g.calculatePaths(from, to, 0, [from]);
}

calculate('F', 'C');
&#13;
&#13;
&#13;