迪杰斯特拉

 最近在Ubuntu下使用wine,那字体一直搞不定,也就没有更新日志。下面的迪杰斯特拉算法是这次数据结构课的作业,顺便把它放上来。这次的结构体定义相当不好,由于思路比较简单,流程图都没整理就开始写。后来发现结构体定义不要又不想改。下次写题目之前一定要整理下流程图。我们的教材是严蔚敏、吴伟民编著的清华大学出版社出版《数据结构(C语言版)》。思路基本上是按照课本里头的。

#include<stdio.h>

#include<malloc.h>

#include<string.h>

#include <stdlib.h>

 

#define MAX 3000//设无穷为3000

 

typedef struct {

    int flag;//判断节点是否在最短路劲集合中

    int *weight;

    int *road;

}Node;

 

void DIJ (Node *ve,int sourse,int n);

 

int main() {

 

    int i,j,n,sourse;

    Node *ve;

 

    printf ("Input the number of the NODE:");

    scanf ("%d",&n);//读节点数

    ve = (Node *) malloc (n*sizeof(Node));//分配空间

    if (!ve) exit (0);

    printf ("Input the number of the ROAD(The road to itself must not small than 3000,/n/

and if there is none plesae put a number larger than or equal to 3000):/n");

    for (i = 0; i<n; i++) {

        ve[i].flag = 0;//0

        ve[i].weight = (int *) malloc ( n*sizeof(int) );

        ve[i].road = (int *) malloc ( (n+1)*sizeof(int) );//n+1确保不会溢出

        if (!ve[i].weight || !ve[i].road) exit (0);

        memset (ve[i].road, 0, (n+1)*sizeof(int));//0作为路径结束标记

        for (j = 0; j < n; j++)

        scanf ("%d",&ve[i].weight[j]);//读路径值

    }

    printf ("Input the Sourse:");

    scanf ("%d",&sourse);//读起点值

    sourse--;

    ve[sourse].flag = 1;//起点在最短路径集合中

 

    DIJ(ve,sourse,n);//调用函数

 

    for (i = 0; i<n; i++) {

        if (i == sourse ) continue;//自己不用输出

        printf ("V%d to V%d/t",sourse+1,i+1);

        j = 0;

        if (ve[sourse].weight[i] < MAX) {   //判断是否有路径

            printf ("%d/t",ve[sourse].weight[i]);

        do {

            printf("V%d ",ve[i].road[j++]);

            } while (ve[i].road[j] !=0);

        printf ("/n");

        } else printf ("NONE/n");

    }//输出路径

 

    for (i = 0; i<n; i++) {

        free(ve[i].weight);

        free(ve[i].road);

    }

    free(ve);//释放空间

    return 0;

}

 

void DIJ (Node *ve,int sourse,int n) {

    int i,j,small;

 

    for (i = 0; i<n; i++) if (ve[sourse].weight[i] < MAX) {

        ve[i].road[0] = sourse+1;

        ve[i].road[1] = i+1;

    }//确定路径

    while (1){

        for (j=0; j < n && !(!ve[j].flag && (ve[sourse].weight[j] < MAX)); j++);

        if (j==n) break;//结束

        small = j;

        for (i = j+1; i < n; i++)

            if ( !ve[i].flag && ve[sourse].weight[i]<MAX) {

                if (ve[sourse].weight[i] < ve[sourse].weight[small])

                    small = i;

                }//ve[sourse].weight里头最小的且不在集合中

        ve[small].flag = 1;//把其纳入集合中

        for (i = 0; i<n; i++)

            if ( !ve[i].flag && ve[small].weight[i] < MAX &&/

            ve[small].weight[i]+ve[sourse].weight[small]<ve[sourse].weight[i]) {

                ve[sourse].weight[i] = ve[small].weight[i]+ve[sourse].weight[small];

//查看是否有更短路径

                for (j = 0; (ve[i].road[j] = ve[small].road[j]) != 0; j++);//重新确定路径

                ve[i].road[j] = i+1;

                ve[i].road[j+1] = 0;//置结尾表示

            }

    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值