Dijkstra完整代码实现

Dijkstra

该算法是最近备考研时,学到图中Dijkstra算法时,自己用

C实现的代码,代码可以直接运行。

说明:

  1. 图是由邻接表存储的

​
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<limits.h> 
​
#define MaxVertexNum 100
#define INFINITY INT_MAX //最大值 
​
//用邻接表定义图
//定义边或弧 
typedef struct ArcNode{
    int adjvex;//边或弧指向哪个结点 
    int info;//边或弧的权值 
    struct ArcNode *next;//执行下一条弧的指针 
}ArcNode; 
​
//定义顶点
typedef struct VNode{
    int data;//顶点信息
    ArcNode *first;//第一条边/弧 
}VNode,AdjList[MaxVertexNum];
​
//用邻接表存储图
typedef struct{
    AdjList vertices;//顶点数组 
    int vexnum,arcnum;//图的当前顶点数和弧数 
}ALGraph; 
​
​
//初始化图
void InitGraph(ALGraph &G,int n){
    G.vexnum = 0;
    G.arcnum = 0;
    //分配头结点 
    int i;
    for (i=1;i<=n;i++){
        G.vertices[i].first = (ArcNode *)malloc(sizeof(ArcNode));
        G.vertices[i].first->next = NULL;
    } 
} 
​
//存储图
void StoreGraph(ALGraph &G,int n,int m,int data2[][3]){//n是顶点个数,m是边的条数
    //初始化 
    InitGraph(G,n); 
    //存储每个结点的信息 
    int i;
    for (i=1;i<=n;i++){
        G.vertices[i].data = i;
        G.vexnum++; 
    }
    //各个结点的关系,遍历边 
    for (i=0;i<m;i++){
            ArcNode* arcNode = (ArcNode *)malloc(sizeof(ArcNode));
            arcNode->adjvex = data2[i][1];//边或弧指向的结点
            arcNode->info =  data2[i][2];//边或弧的权值 
            //第一次插入 
            if (G.vertices[data2[i][0]].first->next == NULL){
                G.vertices[data2[i][0]].first->next = arcNode;
                arcNode->next = NULL; 
            }else{//非第一次插入 
                //从头结点插入边或弧 
                ArcNode* arcNext = G.vertices[data2[i][0]].first->next; 
                G.vertices[data2[i][0]].first->next = arcNode;
                arcNode->next = arcNext;
            }
            G.arcnum++;//增加一条弧 
    } 
} 
​
//打印邻接表 
void print(ALGraph G){
    int i;
    int data = 0;
    int info;
    for (i=1;i<=G.vexnum;i++){
        ArcNode* p = G.vertices[i].first->next;
        printf("%d",i);
        while (p!=NULL){
            data = p->adjvex;
            info = p->info;
            printf("--%d-->%d",info,data);
            p = p->next;
        }
        printf("\n");
        
    }
    
}
​
/*
    初始化Dijkstra
        把顶点v到各顶点的路径长度记录到dist[]中,并记录前驱结点 
*/
void InitDijkstra(ALGraph G,int v,int dist[],int path[],bool final[]){
    
    int i;
    //将所有值赋为无穷 
    for (i=1;i<=G.vexnum;i++){
        final[i] = false;
        dist[i] = INT_MAX;
    } 
    dist[v] = 0;
    final[v] = true;
    ArcNode* p = G.vertices[v].first->next;
    while (p!=NULL){
        i = p->adjvex;//结点下标
        dist[i] = p->info;//从<v-i>的权值 
        path[i] = v; 
        p = p->next;
    }
    
} 
​
//从dist[]中找到最小值,不包括已经找到的值 
int MinDist(int dist[],bool final[],int n){
    int min = INT_MAX;
    int i;
    for(i=1;i<=n;i++){
        if(!final[i] && dist[i]<min){
            min = i;
        }
    }
    return min;
} 
​
/*
    Dijkstra算法:寻找一个结点到其他各结点的单元路径--时间复杂度O(V2),因为需要找到MinDist()需要一定时间 
        v:是目标顶点 
        final[]:是标记各顶点是否已找到最短路径,下标从1开始 
        dist[]: 是记录目标顶点到各顶点的最短路径 ,下标从1开始 
        path[]:是记录路径上的前驱结点 ,下标从1开始 
        n:结点数 
*/
void Dijkstra(ALGraph G,int v,bool final[],int dist[],int path[],int n){
    
    //初始化 
    InitDijkstra(G,v,dist,path,final);
    
    int count = 0;//记录找到几个最短路径了
    //遍历还未找到最短路径的结点 
    while (count<G.vexnum-2){//这里-2不容易理解 
    
        //从dist中找到最短路径,这里运用贪心的思想 
        int index = MinDist(dist,final,n);
        final[index] = true;
        count++;
        //更新dist中的值
        ArcNode *p = G.vertices[index].first->next;
        while (p!=NULL){
            int v2 = p->adjvex;
            int v2Info = p->info;
            int v2Dist = dist[index]+v2Info;
            if (v2Dist < dist[v2]){
                dist[v2] = v2Dist;
            }
            p = p->next; 
        } 
    }
}
​
void printDist(int dist[],int n){
    int i;
    for (i=1;i<=n;i++){
        printf("%d  ",dist[i]);
    }
}
​
//主函数 
int main(void){
    //这不是指针,是一个结构体变量,cpu会自动给它分配内存,
    //如果是结构体指针,则必须手动malloc给它分配内存 
    ALGraph G;
    int n = 5;
    int m = 7;
    int data[][3] = {
                    {1,2,2},{1,4,5},{2,3,10},{2,4,6},
                    {3,5,6},{4,3,3},{4,5,9}
                    };      
    StoreGraph(G,n,m,data);
    print(G);
    printf("\n");
    
    bool final[n+1];
    int dist[n+1];
    int path[n+1];
    int v = 2;
    Dijkstra(G,v,final,dist,path,n);
    printDist(dist,n);
    
    printf("\nending progarm");
    return 0;
}

运行结果:

说明:

1--5-->4表示顶点1到顶点4有边,且权值为5

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值