text: /**
   * Prim's algorithm is a greedy algorithm that finds a minimum
   * spanning tree for a connected weighted undirected graph.
   *
   * @example
   *
   * var Prim = require('path-to-algorithms/src/graphs/spanning-trees/prim');
   * var Graph = Prim.Graph;
   * var Edge = Prim.Edge;
   * var Vertex = Prim.Vertex;
   *
   * var graph, edges = [];
   * edges.push(new Edge(new Vertex(0), new Vertex(1), 4));
   * edges.push(new Edge(new Vertex(0), new Vertex(7), 8));
   * edges.push(new Edge(new Vertex(1), new Vertex(7), 11));
   * edges.push(new Edge(new Vertex(1), new Vertex(2), 8));
   * edges.push(new Edge(new Vertex(2), new Vertex(8), 2));
   * edges.push(new Edge(new Vertex(2), new Vertex(3), 7));
   * edges.push(new Edge(new Vertex(2), new Vertex(5), 4));
   * edges.push(new Edge(new Vertex(2), new Vertex(3), 7));
   * edges.push(new Edge(new Vertex(3), new Vertex(4), 9));
   * edges.push(new Edge(new Vertex(3), new Vertex(5), 14));
   * edges.push(new Edge(new Vertex(4), new Vertex(5), 10));
   * edges.push(new Edge(new Vertex(5), new Vertex(6), 2));
   * edges.push(new Edge(new Vertex(6), new Vertex(8), 6));
   * edges.push(new Edge(new Vertex(8), new Vertex(7), 7));
   * graph = new Graph(edges, edges.length);
   *
   * // { edges:
   * //    [ { e: '1', v: 0, distance: 4 },
   * //      { e: '2', v: 8, distance: 2 },
   * //      { e: '3', v: 2, distance: 7 },
   * //      { e: '4', v: 3, distance: 9 },
   * //      { e: '5', v: 2, distance: 4 },
   * //      { e: '6', v: 5, distance: 2 },
   * //      { e: '7', v: 0, distance: 8 },
   * //      { e: '8', v: 7, distance: 7 } ],
   * //   nodesCount: 0 }
   * var spanningTree = graph.prim();
   *
   * @module graphs/spanning-trees/prim
   */
  (function (exports) {
  
    'use strict';
  
    var Heap = require('../../data-structures/heap').Heap;
  
    /**
     * Graph vertex.
     *
     * @constructor
     * @public
     * @param {Number} id Id of the vertex.
     */
    exports.Vertex = function (id) {
      this.id = id;
    };
  
    /**
     * Graph edge.
     *
     * @constructor
     * @public
     * @param {Vertex} e Vertex which this edge connects.
     * @param {Vertex} v Vertex which this edge connects.
     * @param {Number} distance Weight of the edge.
     */
    exports.Edge = function (e, v, distance) {
      this.e = e;
      this.v = v;
      this.distance = distance;
    };
  
    /**
     * Graph.
     *
     * @constructor
     * @public
     * @param {Array} edges Array with graph edges.
     * @param {Number} nodesCount Number of nodes in graph.
     */
    exports.Graph = function (edges, nodesCount) {
      this.edges = edges || [];
      this.nodesCount = nodesCount || 0;
    };
  
    /**
     * Executes Prim's algorithm and returns minimum spanning tree.
     *
     * @public
     * @method
     * @return {Graph} Graph which is the minimum spanning tree.
     */
    exports.Graph.prototype.prim = (function () {
      var queue;
  
      /**
       * Initialize the algorithm.
       *
       * @private
       */
      function init() {
        queue = new Heap(compareEdges);
      }
  
      /**
       * Used for comparitions in the heap
       *
       * @private
       * @param {Vertex} a First operand of the comparition.
       * @param {Vertex} b Second operand of the comparition.
       * @return {number} Number which which is equal, greater or
       *  less then zero and indicates whether the first vertex is
       *  "greater" than the second.
       */
      function compareEdges(a, b) {
        return b.distance - a.distance;
      }
  
      return function () {
        init.call(this);
        var inTheTree = {};
        var startVertex = this.edges[0].e.id;
        var spannigTree = [];
        var parents = {};
        var distances = {};
        var current;
        inTheTree[startVertex] = true;
        queue.add({
          node: startVertex,
          distance: 0
        });
        for (var i = 0; i < this.nodesCount - 1; i += 1) {
          current = queue.extract().node;
          inTheTree[current] = true;
          this.edges.forEach(function (e) {
            if (inTheTree[e.v.id] && inTheTree[e.e.id]) {
              return;
            }
            var collection = queue.getCollection();
            var node;
            if (e.e.id === current) {
              node = e.v.id;
            } else if (e.v.id === current) {
              node = e.e.id;
            } else {
              return;
            }
            for (var i = 0; i < collection.length; i += 1) {
              if (collection[i].node === node) {
                if (collection[i].distance > e.distance) {
                  queue.changeKey(i, {
                    node: node,
                    distance: e.distance
                  });
                  parents[node] = current;
                  distances[node] = e.distance;
                }
                return;
              }
            }
            queue.add({
              node: node,
              distance: e.distance
            });
            parents[node] = current;
            distances[node] = e.distance;
          });
        }
        for (var node in parents) {
          spannigTree.push(
            new exports.Edge(node, parents[node], distances[node]));
        }
        return new exports.Graph(spannigTree);
      };
  
    }());
  
  })(typeof window === 'undefined' ? module.exports : window);
  