Dijkstra算法实现

(1)Dijkstra算法解决了有向图上带权的单元最短路径问题,但是算法要求所有的权值必须是非负。算法的思想及其实现均参考《算法导论》一书。

         Dijkstra算法的时间复杂度依赖于最小优先队列的具体实现,下述算法采用的是最小堆结构,时间复杂度为O((V+E)lgV)

(2)算法实现:(简单案例测试成功,若存在问题请指出,多谢。)

#include <iostream> 

using namespace std;  

#define MAX_NODE 1000  
#define INFINITY   9999999
#define NIL   -1

typedef struct ArcNode  
{  
    int adjvex;//弧指向的节点的值(点的标号)  
    int distance;//两点之间的距离
    int weight; //边的权重
    ArcNode* next;//指向下一条弧  
    ArcNode(int value)  
    {  
        adjvex = value;  
        next = NULL;  
    }  
};//邻接表节点  

typedef struct  
{  
    int vexdata; //头节点的标号  
    struct ArcNode* firstarc;//第一个邻接表节点的地址  
}VexNode, AdjList[MAX_NODE];//头结点  

typedef struct  
{  
    AdjList vexNodes;  
    int vexNum;  
    int arcNum;//当前节点数目和弧数  
}GraphWithAL;//邻接表表示的图  

//检测要输入的边是否已经存在,针对无向图  
bool CheckArcIsExist(GraphWithAL* G, int v1, int v2)  
{  
    ArcNode* temp = G->vexNodes[v1].firstarc;  
    while(temp!=NULL)  
    {  
        if(temp->adjvex == v2)  
            return true;  
        temp = temp->next;  
    }  
    return false;  
}  

//创建图,vexNum代表顶点的个数,arcNum代表边的个数,isUnDirected代表的是 是否是无向图  
void CreateGraph(GraphWithAL* G, int vexNum, int arcNum)  
{  
    memset(G, 0 ,sizeof(GraphWithAL));  
    //初始化头结点  
    int i = 0;  
    for(i=0; i<vexNum; ++i)  
    {  
        G->vexNum = vexNum;  
        G->vexNodes[i].firstarc = NULL;  
        G->vexNodes[i].vexdata = i;//从0开始计算顶点  
    }  
    //初始化边  
    for(i=0; i<arcNum; ++i)  
    {  
        //输入边的顶点和尾点  
        int v1, v2, weight;  
        cin>>v1>>v2>>weight;  
        if(CheckArcIsExist(G, v1, v2))  
            continue;  
        ArcNode* arcNode = new ArcNode(v2);  
        //还需要检验边是否已经存在,这里没有检验  
        arcNode->next = G->vexNodes[v1].firstarc;
        arcNode->weight= weight;
        G->vexNodes[v1].firstarc = arcNode;  
        G->arcNum++;   
    }  
}  

//初始化d[],保存从源点到各个顶点的最短路径距离,num代码节点数目
void InitialSingleSource(int s, int d[], int pi[], int num)
{
    int i=0;
    for(; i<num; ++i)
    {
        d[i] = INFINITY;
        pi[i] = NIL;
    }
    d[s] = 0;
}

//松弛技术
void Relax(int u, int v, int weight, int d[], int pi[])
{
    if(d[v] > d[u]+weight)
    {
        d[v] = d[u] +weight;
        pi[v] = u;
    }
}

//修整最小堆 ,使用最小堆结构存储d[]的下标值,目的是最快的方式取出d[]中的最小值下标
void fix_min_heap(int a[], int pos, int len, int d[]) {  
    int left = 2 * pos + 1;  
    int right = 2 * pos + 2;  
    int min = pos;  
    if (left < len && d[a[left]] < d[a[pos]])  
        min = left;  
    if (right < len && d[a[right]] < d[a[min]])  
        min = right;  
    if (pos != min) {  
        int tep = a[pos];  
        a[pos] = a[min];  
        a[min] = tep;  
        fix_min_heap(a, min, len, d);  
    }  
}  
//建立最小堆  
void build_min_heap(int a[], int len, int d[]) {  
    int parent = (len - 1) / 2;  
    int i = 0, j = 0;  
    for (i = parent; i >= 0; --i) {  
        int left = 2 * i + 1;  
        int right = 2 * i + 2;  
        int min = i;  
        if (left < len && d[a[left]] < d[a[i]])  
            min = left;  
        if (right < len && d[a[right]] < d[a[min]])  
            min = right;  
        if (i != min) {  
            int tep = a[i];  
            a[i] = a[min];  
            a[min] = tep;  
            fix_min_heap(a, min, len, d);  
        }  
    }  
}  

//去出最小堆的最小值
int ExtractMin(int a[], int n, int d[])
{
     int temp = a[0];
     a[0] = a[n-1];
     fix_min_heap(a, 0, n-1, d);
     return temp;
}

void Dijkstra(GraphWithAL* G, int s)
{

    int* d = new int[G->vexNum];//记录每个顶点距源点的最小距离
    int* pi = new int[G->vexNum];
    int* a = new int[G->vexNum];//记录最小距离d的下标值
    int i=0;
    for(i=0; i<G->vexNum; ++i)//初始化a
        a[i] = i;
    InitialSingleSource(s, d, pi, G->vexNum);
    int num = G->vexNum;//起初最小堆中的值为顶点的数量,
    
    while(num != 0)
    {
        int min = ExtractMin(a, num--, d);
        ArcNode* temp = G->vexNodes[min].firstarc;
        while(temp != NULL)
        {
            Relax(min, temp->adjvex, temp->weight, d, pi);
            temp = temp->next;
        }

    }
    for(i=0; i<G->vexNum; ++i)
        cout<<d[i]<<" ";
    cout<<endl;
}

int main()  
{  
    GraphWithAL G;  
    int n, m;  
    while(cin>>n>>m)  
    {  
        if(n==0)  
            break;
        CreateGraph(&G, n, m);  
        Dijkstra(&G,  1);
    }
    return 0;  
} 


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值