dijkstra算法(附带正确性证明)

/**
算法及其证明请访问http://www.math.ucsd.edu/~fan/teach/202/notes/04greed.pdf
*/
let max = Infinity;
function newGraph(){
    return {
        vertexs:['s','2','3','4','5','6','7','t'],
        edges:[
            [0,9,max,max,max,14,15,max],
            [9,0,24,max,max,max,max,max],
            [max,24,0,6,2,18,max,19],
            [max,max,6,0,11,max,max,6],
            [max,max,2,11,0,30,20,16],
            [14,max,18,max,30,0,5,max],
            [15,max,max,max,20,5,0,44],
            [max,max,19,6,16,max,44,0]
        ]
    };
    return {
        vertexs:['a','b','c','d','e','f','g'],
        edges:[
            [0,12,max,max,max,16,14],
            [12,0,10,max,max,7,max],
            [max,10,0,3,5,6,max],
            [max,max,3,0,4,max,max],
            [max,max,5,4,0,2,8],
            [16,7,6,max,2,0,9],
            [14,max,max,max,8,9,0]
        ]
    };
    return {
        vertexs:['A','B','C','D','E'],
        edges:[
            [0,5,8,max,max],
            [5,0,1,3,2],
            [8,1,0,max,max],
            [max,3,max,0,7],
            [max,2,max,7,0]
        ]
    };
}
function dijkstra(g,sv){
    let edges = g.edges;
    //let sv = 0;//
    let u = edges[sv].map((item,index)=>index);//未遍历顶点
    //console.info(u);
    let s = [];//源顶点到各顶点的最短路径值以及路径
    for(let i=0;i<u.length;i++){
        s.push({
            w:edges[sv][u[i]],
            path:[sv],
            visited:false
        });
    }
    let pre = u.map(i=>sv);//各顶点上次更新最短路径时的源顶点
    u.splice(sv,1);//未遍历的顶点中移除源顶点
    s[0].visited = true;
    while(u.length>0){
        //寻找离当源顶点最近的顶点
        let minI = 0;//离s最近的顶点在u中的下标
        let min = u[minI];//最近顶点
        let minW = s[min].w;//最近顶点权值
        for(let i=1;i<u.length;i++){
            if(!s[u[i]].visited && s[u[i]].w < minW){
                minI = i;
                min = u[i];
                minW = s[min].w;
            }
        }
        //console.info(`min=${min}`);
        //更新最短路径,上次更新最短路径时的源顶点,用于记录路径信息
        for(let i=0;i<u.length;i++){
            if(s[min].w + edges[min][u[i]] < s[u[i]].w){
                s[u[i]].w = s[min].w + edges[min][u[i]];
                pre[u[i]] = min;
            }
        }
        u.splice(minI,1);//
        s[min].visited = true;
        s[min].path = s[pre[min]].path.map(i=>i);//记录当前源顶点的最短路径信息到s。以上次更新最短路径时的源顶点的路径为基础。
        s[min].path.push(min);//再加上当前顶点
        //console.info(`pre=`);
        //console.info(pre);
    }
    //console.info(s);
    return s;
}
function test(){
    let g = newGraph();
    let res = dijkstra(g,0);
    console.info(res);
}
test();

猜你喜欢

转载自blog.csdn.net/zhoujiaping123/article/details/80910712