/*最小生成树的prim算法的延时实现
标记start并从start开始,把未标记的邻接点之间的边加入优先队列pq,从pq取最短的边,边的两个端点哪个没有被标记,如果这条边上有没被标记的点,就把此边加入mst,标记该点并把该点未标记的邻接点之间的边加入优先队列pq,重复操作直到pq为空。mst即最小生成树。此方法可以不考虑start不能达到的点之间的边。
*/
//(从边有权重开始)pq和mst保存的是边,以前都是保存点
//pq应该用优先队列实现,这里取巧用js自带的api了
function deleteMin(pq){
pq.sort(randomsort)
return pq.shift()
}
//function lengthSort(a,b){return a[2]<b[2]?-1:1} //可以简化成这样
function lengthSort(a,b){return a[2]-b[2]}
function lazyPrimMST(G,start){
visit(start,G)
while(pq.length>0){
var e=deleteMin(pq)
//console.log(e,"pq->",pq)
let v=e[0]
let w=e[1]
if(marked[v]&&marked[w]){continue}
mst.push(e)
if(!marked[v]){visit(v,G)}
if(!marked[w]){visit(w,G)}
}
}
function visit(v,G){
marked[v]=true
for(let j in G[v]){
let e=G[v][j]
if(!marked[e[0]]){pq.push([v,e[0],e[1]])}
}
}
//G:[[[1,1.1],[3,2.6]],[[4,0.6],[0,1.1]],[[5,8.1]],****]
let generateGraph=require('./wgraph').generateGraph
let generateEdges=require('./wgraph').generateEdges
var V=99
console.log(es=generateEdges(V,V*3))
console.log("G-->",G=generateGraph(V,es,false))
var marked=[]
var mst=[]
var pq=[]
var start=0
lazyPrimMST(G,start)
console.log(marked,"\n",mst)
//wgraph.js
function generateEdges(V,E,maxValue=9,jd=7){
var es=[]
//本来精度默认10,取一位小数,测试大量数据时出现相同长度的边在验证结果时很不方便
//比如最后一条边取[1,2,1.1]或[2,3,1.1]都可以,但验证(测试里的test方法)时会报错。所以尽量不使用等长的边
var jingdu=Math.pow(10,jd)
for(let i=0;i<E;i++){
let a=Math.floor(Math.random()*V)
let b=Math.floor(Math.random()*V)
let v=Math.floor(Math.random()*maxValue*jingdu)/jingdu
es.push([a,b,v])
//es.push([a,b,v-maxValue/2]) //随机生成正/负权重的边
}
return es
}
function addEdge(v,w,value,graph,allowCycle=true){
if(v==w&&!allowCycle)return
if(graph[v].indexOf(w)==-1){graph[v].push([w,value])}
if(graph[w].indexOf(v)==-1){graph[w].push([v,value])}
}
//edges:[[0,2,1.1],[7,1,3.6],***]
function generateGraph(V,edges,allowCycle=true){
var g=[]
for(let i=0;i<V;i++){g[i]=[]}
for(let i in edges){
addEdge(edges[i][0],edges[i][1],edges[i][2],g,allowCycle)
}
return g
}
function addDirectedEdge(v,w,value,graph,allowCycle=true){
if(v==w&&!allowCycle)return
if(graph[v].indexOf(w)==-1){graph[v].push([w,value])}
}
function generateDirectedGraph(V,edges,allowCycle){
var g=[]
for(let i=0;i<V;i++){g[i]=[]}
for(let i in edges){
addDirectedEdge(edges[i][0],edges[i][1],edges[i][2],g,allowCycle)
}
return g
}
function getReverseGraph(G){
let v=G.length
var es=[]
for(let i=0;i<v;i++){
let list=G[i]
for(let j in list){
es.push([list[j],i])
}
}
return generateDirectedGraph(v,es)
}
exports.addEdge=addEdge
exports.generateGraph=generateGraph
exports.addDirectedEdge=addDirectedEdge
exports.generateDirectedGraph=generateDirectedGraph
exports.getReverseGraph=getReverseGraph
exports.generateEdges=generateEdges
空间上mst和pq都与E成正比,时间上每条边只加一次,插入取出的都lgE