javascript实现有向无环图中任意两点最短路径的dijistra算法

有向无环图

一个无环的有向图称做有向无环图(directed acycline praph)。简称DAG 图。DAG 图是一类较有向树更一般的特殊有向图,

dijistra算法

摘自 http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html

1.定义概览

Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。注意该算法要求图中不存在负权边。

问题描述:在无向图 G=(V,E) 中,假设每条边 E[i] 的长度为 w[i],找到由顶点 V0 到其余各点的最短路径。(单源最短路径)

javascript实现

<html>
<body>
<script>

//有向无环图
var pages = []

//开始结点有两个后继
pages["welecome"] = [];
pages["welecome"]["nextNode"] = [];
pages["welecome"]["nextNode"][0] = "workmode"

//一个后继又有两个后继
pages["workmode"] = [];
pages["workmode"]["nextNode"] = [];
pages["workmode"]["nextNode"][0] = "WAN"
pages["workmode"]["nextNode"][1] = "WLAN"

//WAN的后继为WLAN
pages["WAN"] = [];
pages["WAN"]["nextNode"] = [];
pages["WAN"]["nextNode"][0] = "WLAN"

//WLAN的后继为终点
pages["WLAN"] = [];
pages["WLAN"]["nextNode"] = [];
pages["WLAN"]["nextNode"][0] = "OVER"

//终点
pages["OVER"] = [];
pages["OVER"]["nextNode"] = [];

/* 计算有向无环图中,指定两点之间的最短路径 */
function ComputeShortPath(map, startName, endName)
{
    //判断两个节点是否有前后继关系,第一个为前,后一个为后
    function IsSuccessor(nodeNameA, nodeNameB)
    {
        var page = pages[nodeNameA];
        var nextNodes = page["nextNode"];
        for ( var index in nextNodes )
        {
            var nextNode = nextNodes[index];
            if ( nextNode == nodeNameB )
            {
                return true;
            }
        }

        return false;
    }

    /* 生成权重矩阵 */
    function GenerateEdgeWeight(map)
    {
        document.write("---- Generate edgeWeightMatrix ----</br>")

        /* 记录图中各个点之间有向边的权重 */
        var edgeWeightMatrix = [];

        for ( var nodeNameA in map )
        {
            edgeWeightMatrix[nodeNameA] = [];

            for ( var nodeNameB in map )
            {
                var isSucc = IsSuccessor(nodeNameA, nodeNameB);
                var weight;
                if ( true == isSucc )
                {
                    /* 有前后继的关系,权重设置为1 */
                    weight = 1;
                }
                else
                {
                    /* 没有前后继的关系,权重设置为正无穷 */
                    weight = Number.POSITIVE_INFINITY;
                }
                edgeWeightMatrix[nodeNameA][nodeNameB] = weight;

                document.write("edgeWeightMatrix["+nodeNameA+"]["+nodeNameB+"]="+edgeWeightMatrix[nodeNameA][nodeNameB]+"</br>")
            }
        }

        return edgeWeightMatrix;
    }

    /* 产生Dijistra运算的数据结构 */
    function GenerateDijistraDataStruct(map, startName, edgeWeightMatrix)
    {
        var dijistraJSON = {
            /* 已经知道最短路径集合 */
            knownSet:[],
            /* 未知最短路径集合 */
            unKnownSet:[],
            /* 最短特殊路径长度 */
            distanceSP:[],
        };

        /* 初始化,出发点添加到已知集合,其他添加到未知集合 */
        for ( var nodeName in map )
        {
            if ( nodeName == startName )
            {
                dijistraJSON.knownSet.push(startName);
            }
            else
            {
                dijistraJSON.unKnownSet.push(nodeName);
            }
        }

        /* 初始化最短特殊路径 */
        document.write("---- Generate distanceSP with startName = "+startName+" ----</br>")
        for ( var index in dijistraJSON.unKnownSet )
        {
            var nodeName = dijistraJSON.unKnownSet[index];
            dijistraJSON.distanceSP[nodeName] = edgeWeightMatrix[startName][nodeName];
            document.write("distanceSP["+nodeName+"]="+dijistraJSON.distanceSP[nodeName]+"</br>");
        }

        return dijistraJSON;
    }

    /* 运行最短路计算逻辑 */
    function DoDijistraComputing(dijistraJSON, edgeWeightMatrix)
    {
        /* dijstra */
        var loopNum = dijistraJSON.unKnownSet.length;
        for ( var i=0; i<loopNum; i++ )
        {
            /* 找unKnownSet中最短特殊路径顶点 */
            var minDistName = dijistraJSON.unKnownSet[0];
            var minDistIndex = 0;
            var minDist = dijistraJSON.distanceSP[minDistName];
            for ( var index in dijistraJSON.unKnownSet )
            {
                var nodeName = dijistraJSON.unKnownSet[index];
                var dist = dijistraJSON.distanceSP[nodeName];
                if ( dist < minDist )
                {
                    minDist = dist;
                    minDistName = nodeName;
                    minDistIndex = index;
                }
            }

            /* 将最短特殊路径顶点,从unkownSet中删除,加入knownSet */
            dijistraJSON.unKnownSet.splice(minDistIndex, 1);
            dijistraJSON.knownSet.push(minDistName);

            /* 更新 unKnownSet 中元素的 distanceSP 值 */
            for ( var index in dijistraJSON.unKnownSet )
            {
                var nodeName = dijistraJSON.unKnownSet[index];
                var oldDist = dijistraJSON.distanceSP[nodeName];
                var weight = edgeWeightMatrix[minDistName][nodeName];
                var newDist = minDist + weight;
                if ( newDist < oldDist )
                {
                    dijistraJSON.distanceSP[nodeName] = newDist;
                }
            }
        }

        /* 输出看打印结果 */
        document.write("---- Complete distanceSP with startName = "+startName+" ----</br>")
        for ( var index in dijistraJSON.knownSet )
        {
            var nodeName = dijistraJSON.knownSet[index];
            document.write("distanceSP["+nodeName+"]="+dijistraJSON.distanceSP[nodeName]+"<br/>");
        }

        return dijistraJSON;
    }

    /* 获取最短路径 */
    function GetShortPath(dijistraJSON, endName)
    {
        return dijistraJSON.distanceSP[endName];
    }

    var edgeWeightMatrix = GenerateEdgeWeight(map);
    var dijistraJSON = GenerateDijistraDataStruct(map, startName, edgeWeightMatrix);
    dijistraJSON = DoDijistraComputing(dijistraJSON, edgeWeightMatrix);
    var shortPath = GetShortPath(dijistraJSON, endName);

    document.write("---- Complete shortpath between "+startName+" and "+endName+" = "+shortPath+"----</br>")
}

ComputeShortPath(pages, "welecome", "OVER");
</script>
</body>
</html>

计算结果截图:

最后计算结果, 中distanceSP中每一个定点的值,都是开始结点 welecome到此结点的 最短距离。

时间: 2024-08-06 22:11:24

javascript实现有向无环图中任意两点最短路径的dijistra算法的相关文章

Floyd-Warshall求图中任意两点的最短路径

原创 除了DFS和BFS求图中最短路径的方法,算法Floyd-Warshall也可以求图中任意两点的最短路径. 从图中任取两点A.B,A到B的最短路径无非只有两种情况: 1:A直接到B这条路径即是最短路径(前提是存在此路径): 2:A先通过其他点,再由其他点到B. 我们并不知道A是否需要通过其他点间接到达B,所以只能比较,用A到B的直接路径和A先通过其他点 再间接到达B的路径长度进行比较,然后更新为较小值. 上图中若要求顶点4到顶点3的最短路径,可以比较顶点4直接到3的路径和顶点4先到1,再到3

[从今天开始修炼数据结构]无环图的应用 —— 拓扑排序和关键路径算法

上一篇文章我们学习了最短路径的两个算法.它们是有环图的应用.下面我们来谈谈无环图的应用. 一.拓扑排序 博主大学学的是土木工程,在老本行,施工时很关键的节约人力时间成本的一项就是流水施工,钢筋没绑完,浇筑水泥的那帮兄弟就得在那等着,所以安排好流水施工,让工作周期能很好地衔接就很关键.这样的工程活动,抽象成图的话是无环的有向图. 在表示工程的有向图中,用顶点表示活动,弧表示活动之间的优先关系,这样的有向图为顶点表示活动的网,成为AOV网(Active On Vertex Network) ※ 若在

15-1有向无环图中的最长路径

#ifndef LONG_PATH_H #define LONG_PATH_H #include<iostream> #include<string> #define MAX 65535 int graphPath_longest(int (*Graph)[5],int Length,int origin,int destin ); void printf_path(int origin,int destin); #endif #include"LongPath.h&qu

JavaScript + SVG实现Web前端WorkFlow工作流DAG有向无环图

一.效果图展示及说明 (图一) (图二) 附注说明: 1. 图例都是DAG有向无环图的展现效果.两张图的区别为第二张图包含了多个分段关系.放置展示图片效果主要是为了说明该例子支持多段关系的展现(当前也包括单独的节点展现,图例没有展示) 2.图例中的圆形和曲线均使用的是SVG绘制.之前考虑了三种方式,一种是html5的canvas,一种是原始的html DOM,再有就是SVG.不过canvas对事件的支持不是很好(记得之前看过一篇文章主要是通过计算鼠标定位是否在canvas上的某个区域来触发事件机

有向无环图的最小路径覆盖 二分图模型解题

有向无环图中,路径覆盖就是在图中找一些路径,使之覆盖了图中的所有顶点,且任何一个顶点有且只有一条路径与之关联(如果把这些路径中的每条路径从它的起始点走到它的终点,那么恰好可以经过图中的每个顶点一次且仅一次). 最小路径覆盖就是找出最小的路径条数,使之成为原图的一个路径覆盖. 公式:最小路径覆盖=(原图)顶点数-对应的二分图的最大匹配数. 我们通过例题来解释如何把DAG转换为二分图模型. HDU1151Air Raid 题目大意:在一个城镇,有n个路口,和m条单向路,而且这些路不会形成环.现在要弄

有向无环图的最短路径

我们已经知道了如何通过Dijkstra算法在非负权图中找到最短路径.即使图中有负权边,我们也知道通过Bellman-Ford算法找到一个从 给定的源点到其它所有节点的最短路径.现在我们将看到一个在线性时间内运行得更快的算法,它可以在有向无环图中找到从一个给定的源点到其它所有可达顶点的 最短路径,又名有向无环图(DAG). 由于有向无环图无环所以我们不必担心负环的问题.正如我们已经知道在负环里讨论最短路径是毫无意义的一样,因为我们可以在这些环里不断“循环”,但实际上我们得到的路径将变得越来越短(构

UVA10305 Ordering Tasks(有向无环图排序--toposort) Kahn算法

题目描述:https://vjudge.net/problem/UVA-10305 题目分析: 恨水的题目,只要学了toposort就会做的,大概意思是给你n个变量,m个不等关系表示a<b,问n个数可能的关系;不如举个例子例如n=3表示3个变量我们假如他们是a,b,c现在有两个关系a<b,a<c 那么输出有两种a<b<c或者a<c<b(题目要求输出任意一种); 题目大概就这个意思,那么我们怎么做呢,我们想一想如果把变量看成点,关系看成有向边,那么就得到一个图,这个

图的邻接表表示与无环图的拓扑排序

一.  图的最常用的表示方法是邻接矩阵和邻接表. 1,邻接矩阵 邻接矩阵其实就是一个二维数组,对于每条边<u,v>,我们就令A[u][v] = 1,如果图为有权图,我们也可以令A[u][v]等于该权,这么表示的优点是非常简单,但是它的空间需求很大,如果图是稠密的,邻接矩阵是合适的表示方法,如果图是稀疏的,那这种方法就太浪费空间了,下面给出图的邻接矩阵表示例子. 2 邻接表 邻接表是图的常用储存结构之一.邻接表由表头结点和表结点两部分组成,其中图中每个顶点均对应一个存储在数组中的表头结点.如下图

48. 蛤蟆的数据结构笔记之四十八的有向无环图的应用关键路径

48. 蛤蟆的数据结构笔记之四十八的有向无环图的应用关键路径 本篇名言:"富贵不淫贫贱乐 ,男儿到此是豪雄.-- 程颢" 这次来看下有向无环图的另一个应用关键路径. 欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/47135061 1.  关键路径 与AOV-网相对应的是AOE-网(Activity On Edge)即边表示活动的网.AOE-网是一个带权的有向无环图,其中,顶点表示事件(Event),弧表示活动,权表