Dijkastra算法:
设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组。
第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , 就将 加入到集合S中,直到全部顶点都加入到S中,算法就结束了)。
第二组为其余未确定最短路径的顶点集合(用U表示)。
按最短路径长度的递增次序依次把第二组的顶点加入S中。在加入的过程中,总保持从源点v到S中各顶点的最短路径长度不大于从源点v到U中任何顶点的最短路径长度。此外,每个顶点对应一个距离,S中的顶点的距离就是从v到此顶点的最短路径长度。U中的顶点的距离,是从v到此顶点只包括S中的顶点为中间顶点的当前最短路径长度。
代码实现:
#include<stdio.h>
#include<stdlib.h>
#define M 1000
char s[7]={'A','B','C','D','E','F','G'};
typedef struct Delete //存储原始权值链表
{char a;
int length;
struct Delete *next;
}Del;
typedef struct Increase //存储优化后链表
{char b;
int length;
struct Increase *next;
}Inc;
int min(int *buff,int n) //寻找最小值函数
{
int temp=M;
for(int i=0;i<n;i++)
if (temp>*(buff+i)&&*(buff+i)!=0)
temp=*(buff+i);
return temp;
}
void print_Del(Del *ph) //输出操作后原始链表
{if(NULL!=ph->next)
{Del *p=ph;
p=p->next;
printf("位置:%c ",p->a);
printf("距离:%d\n",p->length);
while(NULL!=p->next)
{
p=p->next;
printf("位置:%c ",p->a);
printf("距离:%d\n",p->length);
}
}
}
void print_Inc(Inc *ph) //输出最短路径顶点链表
{
if(NULL!=ph->next)
{Inc *p=ph;
printf("位置:%c ",p->b);
printf("距离:%d\n",p->length);
while(NULL!=p->next)
{
p=p->next;
printf("位置:%c ",p->b);
printf("距离:%d\n",p->length);
}
}
}
Del *create_Del(int *buff) //通过原始数据,建立原始链表
{
Del *p,*head,*tail;
p=(Del*)malloc(sizeof(Del));
tail =(Del*)malloc(sizeof(Del));
if(NULL==p||NULL==tail)
{printf("malloc error!\n");
return NULL;
}
head=p;
p->next=tail;
for(int i=0;i<7;i++)
{
p=tail;
p->a=s[i];
//printf("%c",s[i]);
p->length=*(buff+i);
//printf("%d\n",*(buff+i));
tail =(Del*)malloc(sizeof(Del));
p->next=tail;
}
p->next=NULL;
return head;
}
Del *delete_point(Del *ph,int num) //删除指定节点
{
Del *p=ph;
Del *rcy;
for(int i=1;i<num;i++)
p=p->next;
rcy=p->next;
p->next=p->next->next;
free(rcy);
return ph;
}
Del *find_Del(Del *ph,int num)
{Del *p=ph;
for(int i=1;i<=num;i++)
p=p->next;
return p;
}
Inc *increase_point(char D,int Length) //最短路径链表增加节点
{
Inc *q;
q=(Inc*)malloc(sizeof(Inc));
q->b=D;
q->length=Length;
q->next=NULL;
return q;}
void Dijkastra(int buff[][7],Del *Del_link,int z) //Dijkastra函数体
{Inc *p,*ph;Del *q,*get_min,*phD;int length_array[6];int n=0,u_num=5;
p=(Inc*)malloc(sizeof(Inc));
ph=p;
ph->b=s[z];
ph->length=0;
q=delete_point(Del_link,z+1);
phD=Del_link;
while(NULL!=Del_link->next)
{
int l=1;
get_min=Del_link;
while(NULL!=get_min->next)
{
get_min=get_min->next;
length_array[n]=get_min->length;
//printf("%d&%d\n",n,length_array[n]);
n++;
}
int m=min(length_array,n);
printf("*****************\n");
printf("更新的链表为:\n");
print_Del(phD);
printf("当前最小距离为%d\n",m);
while(NULL!=Del_link->next)
{if(Del_link->next->length==m)
{printf("当前最小距离的序数是%d\n",l);
break;
}
Del_link=Del_link->next;
l++;
}
printf("当前l值为%d\n",l);
Del *r=find_Del(phD,l);
char ra=r->a;
int rl=r->length;
if(NULL!=phD->next)
{
delete_point(phD,l);
printf("删除后的链表为:\n");
print_Del(phD);}
for(int k=1;k<=u_num;k++)
{Del *t=find_Del(phD,k);
for(int f=0;f<7;f++)
if(ra==s[f])
break;
for(int g=0;g<7;g++)
if(t->a==s[g])
break;
// printf("t->a=%c,f=%d,g=%d\n",t->a,f,g);
if(t->length>buff[f][g]+m)
t->length=buff[f][g]+m;
}
u_num--;
p->next=increase_point(ra,rl);
printf("最优链表为:\n");
print_Inc(ph);
p=p->next;
Del_link=phD;
if(NULL!=Del_link->next)
printf("当前链表第一个节点为%c\n",Del_link->next->a);
n=0;
}
if(NULL!=p->next)
p=p->next;
p->next=NULL;
}
/*
void cs(int *buff,Del *ph)
{
int m=min(buff);
printf("最小距离为%d\n",m);
for(int j=0;j<7;j++)
{if(*(buff+j)==m)
{printf("最小距离的序数是%d\n",j);
break;}
}
delete_point(ph,j);
printf("%d\n",ph->next->next->length);
}
*/
int main()
{int Temp,i;char start;
Del *p;
int Weight[][7]=
{
{0,12,M,M,M,16,14},
{12,0,10,M,M,7,M},
{M,10,0,3,5,6,M},
{M,M,3,0,4,M,M},
{M,M,5,4,0,2,8},
{16,7,6,M,2,0,9},
{14,M,M,M,8,9,0}
};
printf("请输入起始点:");
scanf("%c",&start);
for(int sta_num=0;sta_num<7;sta_num++)
if(start==s[sta_num])
break;
p=create_Del(Weight[sta_num]);
print_Del(p);
Dijkastra(Weight,p,sta_num);
return 0;
}
运行结果为: