算法分析---------------------Dijkstra(迪杰斯特拉)算法

数据结构学过好多时了,都快忘记了,现在复习一下吧


 

 

摘自http://www.wutianqi.com

 

Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低。

 

其基本思想是,设置顶点集合S并不断地作贪心选择来扩充这个集合。一个顶点属于集合S当且仅当从源到该顶点的最短路径长度已知。

初始时,S中仅含有源。设u是G的某一个顶点,把从源到u且中间只经过S中顶点的路称为从源到u的特殊路径,并用数组dist记录当前每个顶点所对应的最短特殊路径长度。Dijkstra算法每次从V-S中取出具有最短特殊路长度的顶点u,将u添加到S中,同时对数组dist作必要的修改。一旦S包含了所有V中顶点,dist就记录了从源到所有其它顶点之间的最短路径长度。

例如,对下图中的有向图,应用Dijkstra算法计算从源顶点1到其它顶点间最短路径的过程列在下表中。

 

 

 

Dijkstra算法的迭代过程:

 

 

我把他原来的程序又补充了注释

 

/*
 * main.cpp
 *
 *  Created on: 2013-8-17
 */
#include <stdio.h>
#include <iostream>
using namespace std;

const int maxnum = 100;
const int maxint = 999999;

void Dijkstra(int n, int v, int *dist, int *prev, int c[maxnum][maxnum]) {
    bool s[maxnum];    // 判断是否已存入该点到S集合中
    for (int i = 1; i <= n; ++i) {
        dist[i] = c[v][i];  //直接到原点的路径长度
        cout << dist[i] << endl;
        s[i] = 0;     // 初始都未用过该点
        if (dist[i] == maxint)
            prev[i] = 0;    //例如点3
        else
            prev[i] = v;    //标识2,4,5到原点有直接路径
    }
    //标识到原点的最少长度为0,而且1点已经使用过
    dist[v] = 0;
    s[v] = 1;

    cout << "核心算法" << endl;

    // 依次将未放入S集合的结点中,取dist[]最小值的结点,放入结合S中
    // 一旦S包含了所有V中顶点,dist就记录了从源点到所有其他顶点之间的最短路径长度
    for (int i = 2; i <= n; ++i) {
        int tmp = maxint;
        int u = v;
        // 找出当前未使用的点j的dist[j]最小值
        for (int j = 1; j <= n; ++j)
            if ((!s[j]) && dist[j] < tmp)  //未使用的点以及他到原点的为通路
                    {
                u = j;              // u保存当前邻接点中距离最小的点的号码
                tmp = dist[j];
            }
        s[u] = 1;    // 表示u点已存入S集合中

        // 更新dist
        for (int j = 1; j <= n; ++j)

            if ((!s[j]) && c[u][j] < maxint)   //未使用过的点而且其他点到标志点u是通路
                    {
                //前驱点到新的点的路径+新点到前驱点的路径是否小于这个新点直接到原点的距离或是已经保存的最短路径
                int newdist = dist[u] + c[u][j];
                if (newdist < dist[j]) {    //更新这个点的最短路径
                    dist[j] = newdist;
                    prev[j] = u;
                }
            }
    }
}

void searchPath(int *prev, int v, int u) {
    int que[maxnum];
    int tot = 1;
    que[tot] = u;
    tot++;
    //参数点的前驱
    int tmp = prev[u];
    //如果不是原点的话
    while (tmp != v) {
        //根据prev依次赋值前驱
        que[tot] = tmp;
        tot++;
        tmp = prev[tmp];
    }
    que[tot] = v;
    //遍历输出
    for (int i = tot; i >= 1; --i)
        if (i != 1)
            cout << que[i] << " -> ";
        else
            cout << que[i] << endl;
}

int main() {
    freopen("input.txt", "r", stdin);
    // 各数组都从下标1开始
            int dist[maxnum];// 表示当前点到源点的最短路径长度
            int prev[maxnum];// 记录当前点的前一个结点
            int c[maxnum][maxnum];// 记录图的两点间路径长度
            int n, line;// 图的结点数和路径数

            // 输入结点数
            cin >> n;
            // 输入路径数
            cin >> line;
            int p, q, len;// 输入p, q两点及其路径长度

            // 初始化c[][]为maxint
            for(int i=1; i<=n; ++i)
            for(int j=1; j<=n; ++j)
            c[i][j] = maxint;

            for(int i=1; i<=line; ++i)
            {
                cin >> p >> q >> len;
                if(len < c[p][q])       // 有重边
                {
                    c[p][q] = len;      // p指向q
                    c[q][p] = len;// q指向p,这样表示无向图
                }
            }

            for(int i=1; i<=n; ++i) {
                dist[i] = maxint;
            }
            for(int i=1; i<=n; ++i)
            {
                for(int j=1; j<=n; ++j)
                printf("%8d", c[i][j]);
                printf("\n");
            }

            Dijkstra(n, 1, dist, prev, c);

            // 最短路径长度
            cout << "源点到最后一个顶点的最短路径长度: " << dist[n] << endl;

            // 路径
            cout << "源点到最后一个顶点的路径为: ";
            searchPath(prev, 1, n);
        }

附上输入文件 input.txt

5
7
1 2 10
1 4 30
1 5 100
2 3 50
3 5 10
4 3 20
4 5 60

 


 

打印结果:

999999 10 999999 30 100
10 999999 50 999999 999999
999999 50 999999 20 10
30 999999 20 999999 60
100 999999 10 60 999999
999999
10
999999
30
100
核心算法
源点到最后一个顶点的最短路径长度: 60
源点到最后一个顶点的路径为: 1 -> 4 -> 3 -> 5

posted @ 2013-08-18 11:15  强子~Developer  阅读(539)  评论(0编辑  收藏  举报