Dijkstra算法

Dijkstra算法
基本算法:
将图G中所有的顶点V分成两个顶点集合A,B.如果源点S到顶点u的最短路径已经知道,则点u属于集合A,否则属于集合B。在最开始的时候A中只包含源点S,其余的点属于B,算法结束时,所有源点S可以达到的点都在集合A中,而不可达的点仍然在集合B。

伪代码:
S为源点,Belong[ ]记录点属于哪个集合,true表示属于A,false表示属于B,map[ ][ ] 记录地图信息,map[u][v]代表点v到点u的长度,最短结果保存到dist[ ]中,pre[ ]记录最短路径终点的前驱,如:到达点j最短的路径上,终点j的前一节点即为k,即pre[j] = k。

  1. 初始化:源点的距离dist[s]设为0,其他的点的距离设为map[s][i],p[s] = true,其他各点的 p[i] = false;
  2. 循环N-1次:
    1. 在B中的点取一s到其距离最小的点k,p[k] = true; 如果所有的k都不可达,退出循环,算法结束。
    2. 对于每个与k相邻的在B中的点j,更新s到j的最短路径,如果dist[k] + map[k][j] < dist[j] ;
      那么dist[j] = dist[k] + map[k][j];

直接实现:
最简单的实现方法是,存储图的信息使用邻接矩阵,在每次循环中,在用一个循环找距离最短的点,然后用遍历的方法更新与其相邻的边,注意比较可以发现,除了路径记录和更新dist数组部分以外,Dijkstra和Prim算法实现完全相同。
样例代码:

const int maxn = 10001;      //点个数
void Dijkstra(int map[maxn][maxn],int s)
// n个点,dist[i]表示点i到源点s的最短距离,map记录图信息,pre记录前驱,源点,终点。
{
    int i, j, k;
    int min;
    bool belone[maxn];         //true 属于A,false属于B
    int dist[maxn];
    int pre[maxn];
    for (i = 1; i < maxn; ++i)   //初始化
    {
        belone[i] = false;
        if (i != s)
        {
            dist[i] = map[s][i];
            pre[i] = s;
        }
    }
    dist[s] = 0;
    belone[s] = true;
    for (i = 1; i < maxn - 1; ++i)//循环n-1次,求s到其他n-1个点的最短路径
    {
        min = INT_MAX;
        k = 0;
        for (j = 1; j < maxn; ++j)//在b中取一点,s到其距离最短
        {
            if (!belone[j] && dist[j] < min)
            {
                min = dist[j];
                k = j;
            }
        }
        if (k == 0) return;     //如果没有点可扩展,即剩余的点不可到达返回
        belone[k] = true;       //将k从B中除去,加入到A
        for (j = 1; j < maxn; ++j)
        {
            //对于每个与k相邻的在B中的点j,更新s到j的最短路径
            if (!belone[j] && map[k][j] != INT_MAX&&dist[j] > dist[k] + map[k][j])
            {
                dist[j] = dist[k] + map[k][j];
                pre[j] = k;
            }
        }
    }
}

效率:时间复杂度为O(n^2),空间复杂度:由于使用邻接矩阵,空间消耗为O(n^2)。

这里写图片描述

输出结果:

这里写图片描述

数据结构习题Dijkstra 1.3、将二叉树看作图,并对它作图的深度优先遍历,则与原二叉树的 结果是相同的。 A、前序遍历 B、中序遍历C、后序遍历D、层次序遍历 1.4、在关于树的以下4种叙述中,正确的是 。 A、用指针方式存储有n个结点的二叉树,至少要有n+1个指针。 B、m阶B-树中,具有k个子结点的结点,必有k-1个键值。 C、m阶B-树中,每个非叶子结点的子结点个数≥[m/2]。 D、平衡树一定是丰满树。 1.5、在最好和最坏情况下的时间复杂度均为O(nlog2n)且稳定的排序方法是 A、希尔排序 B、快速排序 C、堆排序 D、归并排序 二、解答题 2.1、对目标串 abaabcc和模式串aabc,描述根据KMP算法进行匹配的过程,包括失效函数计算。答:失效函数:-1, 0, -1, -1 目标串 abaabcc和模式串aabc的KMP算法进行匹配的过程 abaabcc aabc 首先,从目标位置0和模式位置0开始比较,至ab和aa,不等时目标位置为1, 模式位置为1。因0位置失效函数的值( f [posP-1] ) 为-1,从目标位 置1和模式位置0开始新一轮比较。因第一个字符( posP == 0 )就不等,目标 位置增1,目标位置2和模式位置0开始新一轮比较,直到模式位置比较至4, 匹配成功。 int fastFind ( char *s, char * pat ){ //带失效函数的KMP匹配算法 int posP = 0, posT = 0; int lengthP = strlen(pat), lengthT = strlen(s); while ( posP < lengthP && posT < lengthT ) if ( pat[posP] == s[posT] ) { posP++; posT++; //相等继续比较 } else if ( posP == 0 ) posT++; //不相等 else posP = f [posP-1]+1; if ( posP < lengthP ) return -1; else return posT - lengthP; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值