码迷,mamicode.com
首页 > 其他好文 > 详细

最短路径--Dijkstra算法原理分析

时间:2014-07-20 22:31:43      阅读:406      评论:0      收藏:0      [点我收藏+]

标签:最短路径      dijkstra   

1. What is problem we faced ?

/**
*    Q: What is problem we faced ?
*
*    A: In our life, there are many problems about pathfinding. Those problems can be simplified as a shorest
*        path problem. In a words,we need to find a suitable path to arrive our destination in a map. For examples
*        : In Internet, there are many routers work for us to transmit data. They are consist of a huge network.
*        It is necessary to find a suitable path between arbitrary two nodes.In addition, this path must be dynamic
*        since the huge network is always change.
*/

2. How can we solve it ? Any advices ?

/**
*    Q: How can we solve it ? Any advices ?
*
*    A: To solve this problem, I was try to find a method to do it. when I did, I found it is difficult to ensure
*        my path is optimal, Although looks like. There are still possible exist a path that is more shorter than
*        I‘s. Now, the problem is how can we ensure a path is optimal. That is not easy. But Dijkstra has been
*        introduced a amazing method. Usually, we explore a new thing by analyze it basic principles first. But
*        that is not always suitable.For this algorithm, we will try to explore it from the outside to the inside.
*        First at all, we simple explain how we can get a shorest path. Then we will demonstrate it.
*/

3. How does Dijkstrate Algorithm work ?

/**
*    Q: How does Dijkstrate Algorithm work ?
*
*    workflow:
*        1). label the start point as visited and others as unvisit.
*        2). obviously, the distance from the start point to the start point is 0.
*        3). compute the distance between the start point and it‘s neighbor nodes.
*        4). choice the nearest node, label it as visited. and we can ensure it‘s path is shorest path.
*        5). compute the distance between start point and all of nodes which have at least one visited node as
*            neighbor.
*        6). choice the nearest node, label it as visited.
*        7). return step(5) untill the new nearest node is destination.
*    When we find destination, all of nodes,which has been labeled as visited , has been get the shorest path.
*    Here has a Animation about this:
*        http://optlab-server.sce.carleton.ca/POAnimations2007/DijkstrasAlgo.html
*/

4. Why does it work ?

/**
*    Q: Why does it work ?
*
*    A: recall the steps above, there are two steps is suspicious. One,when we want to find the nearest node, we
*        always check the neighbor node of visited node.But why the nearest node is reside in the neighbor nodes ?
*        Two, when we found a "nearest node", why we can ensure a path is optimal by find nearest node ?
*/

5. why the nearest node is reside in the neighbor nodes ?

/**
*    Q: why the nearest node is reside in the neighbor nodes ?
*
*    A: First at all, we declare a words: nearest node, that is a node which have a nearest distance except for visited node.
*
*        build three set: SV( set of visited nodes), SU( set of unvisited nodes), and NN(set of neighbor nodes). SV
*        is used to contain all of nodes which has been visited. SU is used to contatin nodes which is unvisited.
*        NN is set of nodes which is neighbor with at least one visited node. Assume that:
*                s -- start point
*                x -- a element of NN
*                y -- a element of SV
*                z -- a element of SU
*        if we want to find a path to z.( s->...->z). The path must contain a node of NN. That means
*                s->...->z.
*        must belong to
*                s->...->x ->...->z
*        we can always know
*                L(s->...->x) < L(s->...->x ->...->z) = L(s->...->z)
*        So whatever we choice unvisited node and path, we can still find a more shorter path value in the
*        neighbor node.
*/

6. why we can ensure a path is optimal by find nearest node ?

/**
*    Q: why we can ensure a path is optimal by find nearest node ?
*
*    A: As we analysis above, the nearest node must be the neighbor of a visited node.
*        Now, at the example above ,Image we has been found a nearest node x, we can get this conclusion:
*                L(s->...->x) = Min{ s->...->x}           ---expr1
*        That‘s means there is no path have a more shorter distance than L(s->...->x).
*
*        If that is wrong, there are another path is more shorter. That must be
*                L(s->...->x0->...->z->...->x) < L(s->...->x)
*                (x0 is belong to NN, but not same with x)
*        That‘s means
*                L(s->...->x0) < L(s->...->x0->...->z->...->x) < L(s->...->x)
*        !!!!!!
*        L(s->...->x0) < L(s->...->x)
*        that is impossible.
*        So if we can find a nearest node ,then we can ensure the path is optimal.
*/

7. source code

/**
*    Here is an example
*/
#include <stdio.h>
/*
*    the distance of  unneighborly nodes
*/
#define UNRN        99
/*
*    used to index to a array,based on 0
*/
typedef int        INDEX;
/*
*    there are two status for a node.
*/
enum VISITSTAT{
        L_UNVISIT,
        L_VISIT,
        L_INVALID,
};

class Dijkstra {
        public:
                Dijkstra( int map[], int e_num, int unre);
                ~Dijkstra( );
                bool set( int start, int target);
                bool work( );
                /*
            * show the value of distance of nodes. when a node has been labeled as visited.
            * this value represent the minimum distance.
            */
                bool show();
                /*
            * show the path from start point to destination.
            */
                bool showPath( );

        private:
                /*
            * when we label a new node as visited, we need to update the distance of 
            * neighbor node.
            */
                bool	_UpdateRelDistanceTable();
                /*
            * used to find the nearest node when we had update the distance value of
            * neighbor node.
            */
                bool _GetNextNearest( INDEX &ind);
                int _mapNode( INDEX x, INDEX y);
                bool _mapLabel( INDEX x);
                bool _travel( INDEX cur);
/**
*    To a node, three types of information is necessary: 
*        1). the relationship between this node with other nodes. Whether their are neighbor.
*            what is the distance between two nodes. 
*        2). the status of a node. Whether a node has been visited.
*        3). the distance between the start node with the other nodes.
*/
                //relationship between nodes
                int                *map;
                //status of those nodes
                VISITSTAT    *ele_stat;
                //the distance
                int                *ele_relds;
                //the number of the elements
                int                ele_num;
                //start point
                INDEX        start;
                //end point
                INDEX        target;
                //the value of unrelated node.
                int                unre;
};

Dijkstra::Dijkstra( int map[], int e_num, int unre)
{
        this->map = map;
        this->ele_relds = new int[ e_num];
        this->ele_stat = new VISITSTAT[e_num];
        this->ele_num = e_num;
        this->start = 0;
        this->target = 0;
        this->unre = unre;
        /*
       * label all of nodes as unvisited
       */
        for( int i=0; i<e_num; i++)
                this->ele_stat[i] = L_UNVISIT;
        /*
       * initialize the distance as unreachable
       */
        for( int i=0; i <e_num; i++)
                this->ele_relds[i] = unre;
}

Dijkstra::~Dijkstra( )
{ }

/**
*    Logically, a map should be a two-dimensional array. But we can only build a 
*    one-dimensional array because of some reasons. So, for convenience,we define 
*    a function used to help us access the map.
*/
int Dijkstra::_mapNode( INDEX x, INDEX y)
{

        return this->map[ this->ele_num* x + y];
}

bool Dijkstra::_mapLabel( INDEX x)
{
        if( (x<0) 
            || (x>=this->ele_num) )
                    return false;

        this->ele_stat[x] = L_VISIT;
        return true;
}

bool Dijkstra::set( INDEX start, INDEX target)
{
        this->start = start;
        this->target = target;
        return true;
}

/**
*    the core function, used to realize the algorithm.
*/
bool Dijkstra::work( )
{
        /*
       * first at all, we label the start node as visited and initialize the distance between this node
       * with the start point. Obviously, it is 0.
       */
        INDEX        cur = this->start;
        this->ele_relds[cur] = 0;
        this->_mapLabel( cur);
        /*
       * we compute the distance of neighbor nodes and find the nearest node periodically.
       * Untill find the nearest node is destination, we get the shortest path to the destination.
       */
        do
        {
                //update the related distance of visited node
                this->_UpdateRelDistanceTable( );
                //get the nearest node and label it as visited
                if( !this->_GetNextNearest( cur))
                {
                        return false;
                }
                this->_mapLabel( cur);

        } while( cur!=this->target);

        return true;
}

bool Dijkstra::show()
{
        INDEX        i;
        printf(" %d-->%d\n", this->start, this->target);
        for( i=0; i<this->ele_num; i++)
        {
                printf("[%d] %4d\n", this->ele_stat, this->ele_relds[i]);
        }

        return true;
}
/**
*    Actually, we didn't save information about the shorest path. But ,with the help of the
*    information of shorest distance, we can still deduce the right path reversely.
*/
bool Dijkstra::showPath( )
{
        INDEX        cur = this->target;
        this->_travel( cur);

        return true;
}
/**
*    As we all know, all of the shorest distance of visited nodes is resolved. So
*    if we want to find the right path of a node, we just need to ensure :
*    the shorest distance of current node is equal to the sum of the shorest distance
*    of neighbor node and its' path.
*	
*/
bool Dijkstra::_travel( INDEX cur)
{
        if( cur==this->start)
        {
                printf("%d\n", cur);
                return false;
        }

        printf(" %d->", cur);

        INDEX        i;
        for( i=0; i<this->ele_num; i++)
        {
                //find neighbor
                if( this->_mapNode( cur, i)!=this->unre )
                {
                        //find right path
                        if((i!=cur)
                            &&(this->ele_relds[cur]==this->ele_relds[i] + this->_mapNode( cur, i)) )
                        {
                                this->_travel( i);
                        }
                }
        }

        return true;
}


bool Dijkstra::_UpdateRelDistanceTable( )
{
        INDEX        i;
        for( i=0; i<this->ele_num; i++)
        {
                //find those nodes visited
                if( this->ele_stat[i] == L_VISIT)
                {
                        INDEX        j;
                        for( j=0; j<this->ele_num; j++)
                        {
                                //find those nodes which is neighboor to the visited node and unvisited
                                if( (this->_mapNode( i, j)!=this->unre)
                                    &&(this->ele_stat[j])==L_UNVISIT )
                                    {
                                            //compute related distance
                                            int    rel_ds = this->ele_relds[i]+ this->_mapNode( i, j);
                                            //update related distance
                                            if( rel_ds<this->ele_relds[j] )
                                                    this->ele_relds[j] = rel_ds;
                                    }
                        }
                }
        }

        return true;
}

bool Dijkstra::_GetNextNearest( INDEX &ind)
{
        INDEX        min = -1;
        INDEX        i;
        for( i=0; i<this->ele_num; i++)
        {
                //find those nodes visited
                if( this->ele_stat[i]==L_VISIT)
                {
                        INDEX        j;
                        for( j=0; j<this->ele_num; j++)
                        {
                                //find nodes which is neighboor and unvisited
                                if( (this->_mapNode( i, j)!=this->unre)
                                    &&(this->ele_stat[ j]==L_UNVISIT) )
                                    {
                                            if( ( min == -1)
                                                ||(this->ele_relds[j]<this->ele_relds[min]))
                                            {
                                                    min = j;
                                            }
                                    }
                        }
                }
        }

        ind = min;
        return ind==-1?false:true;

}



#define E_NUM	8
//        O       A      B       C      D      E        F       T
static  int Map[ E_NUM*E_NUM] = {
/* O*/    0,         2,         5,         4,         UNRN, UNRN,  UNRN, UNRN,  
/* A*/    2,         0,         2,         UNRN, UNRN, UNRN, 12,        UNRN,
/* B*/    5,         2,         0,         1,         4,          UNRN, UNRN,  UNRN,
/* C*/    4,         UNRN, 1,         0,         UNRN, 4,          UNRN,  UNRN,
/* D*/    UNRN, UNRN, 4,        UNRN, 0,          1,         UNRN,  5,
/* E*/    UNRN, UNRN, UNRN, 4,        1,          0,         UNRN,  7,
/* F*/    UNRN, 12,       UNRN, UNRN,UNRN, UNRN, 0,          3,
/* T*/    UNRN, UNRN, UNRN, UNRN,5,          7,         3,          0,

};

static int UnreNode = UNRN;



int main()
{
        Dijkstra        map( Map, E_NUM, UnreNode);
        map.set( 0, 7);
        map.work( );
        map.show();
        map.showPath();

        return 0;
}


 

最短路径--Dijkstra算法原理分析

标签:最短路径      dijkstra   

原文地址:http://blog.csdn.net/u012301943/article/details/37991929

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!