"use strict";
//var tab = window.open();
shortestPathDijkstra( );
function shortestPathDijkstra( ) {
var G = mazeB();
//G.print(); return;
var sNode; // source node number
while (sNode<0 || sNode>G.nnum | sNode%1!==0) {
sNode = Number(prompt("source node? (int 0 to "+G.nnum+")?"));
}
var edge, n, ob; // temps
var pq = makePriorityQueue(); // priority queue for best performance
var pLen = 0;
G.nodes[sNode].dist = pLen; // shortest path source to source is 0
pq.insert(pLen,sNode); // put source node num on queue to get ball rolling
while (pq.size() > 0) {
// process the min node on the heap
ob = pq.getMin(); pq.delMin();
n = ob.val;
if (G.nodes[n].handled) { continue; } // might be in pq from earlier pathlength
G.nodes[n].handled = true;
edge = G.nodes[n].adj; // deal with out edge nodes if any
while (edge!==null) {
if (!G.nodes[edge.tn].handled) { // dont process if we have already done it
pLen = G.nodes[n].dist + edge.weight;
if (pLen < G.nodes[edge.tn].dist) {
// update distance for dest node
G.nodes[edge.tn].dist = pLen;
G.nodes[edge.tn].path = n;
pq.insert(pLen,edge.tn);
}
}
edge = edge.next; // on to next edge
}
}
//alert("end: ");
// now report the results
var str = "shortest path lengths from node " + sNode + " (" + G.nodes[sNode].name + ") to:\n";
for (var n=0; n');
lst = this.nodes[i].adj;
while (lst!==null) {
tab.document.write("       --'"
+ lst.weight + "'---> "+lst.tn + "
");
lst = lst.next;
}
}
},
print: function(exStr) {
var lst;
var str = (exStr || "") + "\n";
for (var i=0; i " + lst.tn + "\n" ;
lst = lst.next;
}
}
alert(str);
},
}
return gobj;
//==================================================================
// end of main graph constructor code body
//==================================================================
// node and edge factory constructors
//==================================================================
function makeNodeFactory() {
var factory = {
idNum:0,
gen: function (s) {
var node = {
idn:this.idNum++,
name:(s || "..."),
next:null, // list of nodes
adj:null, // list of edges
indeg:0,
outdeg:0,
dist:Infinity, // use for shortest path info, etc
path:-1,
handled:false,
}
return node;
},
}
return factory;
}
function makeEdgeFactory() {
var factory = {
idNum:0,
gen: function (n,wt) {
var node = {
tn:n,
weight:(wt || 1),
next:null, // list of edges
idn:this.idNum++,
}
return node;
},
}
return factory;
}
} // end of graph constructor
//==================================================================
// binary heap constructor
//==================================================================
function makePriorityQueue() {
// constructor for a min heap
var heap = {
elts: [-Infinity], // load bignum into elt 0, slot 0 not used
root:1, // slot 1 is always root
last:0, // slot last always holds last val used in array elts
LC: function (n) { return 2*n; }, // slot num
RC: function (n) { return (2*n)+1; }, // slot num
PN: function (n) { return Math.floor(n/2); }, // slot num
LCV: function (n) { return this.elts[this.LC(n)]; }, // element value
RCV: function (n) { return this.elts[this.RC(n)]; }, // element value
PNV: function (n) { return this.elts[this.PN(n)]; }, // element value
size: function ( ) { return this.last; }, // num vals stored
getMin: function ( ) { return this.elts[this.root]; },
insert: function (p,v) {
var ob = {pri:p, val:v};
this.last++;
this.elts[this.last] = ob;
var n=this.last;
var p=this.PN(n);
var temp;
while ( (p!==0) && (ob.pri < this.elts[p].pri) ) {
// swap elt in n with elt in p
temp=this.elts[n]; this.elts[n]=this.elts[p]; this.elts[p]=temp;
n = p;
p = this.PN(n);
}
},
delMin: function () {
if (this.size()===0) { return; }
if (this.size()===1) { this.elts[1]=Infinity; this.last--; return;}
// havbe at least two elts
// move last val to root
this.elts[this.root]= this.elts[this.last];
this.elts[this.last] = Infinity; this.last--;
// bubble down from root
var temp, done=false;
var n=this.root, c=0;
while (!done) {
if (this.isLeaf(n)) { done=true; }
else {
if (this.hasOnlyLC(n)) { c=this.LC(n); }
else {
c = (this.LCV(n).pri < this.RCV(n).pri) ? this.LC(n) : this.RC(n);
}
if (this.elts[n].pri > this.elts[c].pri) {
temp=this.elts[c]; this.elts[c]=this.elts[n]; this.elts[n]=temp;
n = c;
}
else { done=true; }
}
}
},
isLeaf: function (n) { return ( this.LC(n)>this.last && this.RC(n)>this.last ); },
hasOnlyLC: function (n) { return ( this.RC(n)>this.last && this.LC(n)<=this.last ); },
print: function ( ) {
var str="heap elts: \n";
for (var i=1; i<=this.size(); i++) {
str += "p: "+this.elts[i].pri + ", v: "+ this.elts[i].val + "\n";
}
alert(str);
},
}
return heap;
}