吉林大学数据结构--图的单源无权最短路径和图的单源正权最短路径,Dijktra算法

#include <stdio.h>
#include <stdlib.h>
typedef struct edge{
int veradj;
int cost;
struct edge*link;
}edge;
typedef struct head{
int vername;
edge*adjacent;
}head;

edge*creatnode(edge*p,int c,int a){//创建顶点
p=(edge*)malloc(sizeof(edge));
p->veradj=c;
p->cost=a;
p->link=NULL;
return p;
}
head*build(int n,head*headt[]){//创建邻接图
int i=0;
for(i=0;i<n;i++)
{headt[i]=(head*)malloc(sizeof(head));
headt[i]->vername=i;
headt[i]->adjacent=NULL;}
int c;int cost;
edge*p,*q;
for(i=0;i<n;i++)
{
scanf("%d%d",&c,&cost);
while(c!=-1){
p=creatnode(p,c,cost);
if(headt[i]->adjacent==NULL)
      {headt[i]->adjacent=p;
      q=p;}
      else{
            q->link=p;
            q=p;
      }
      scanf("%d%d",&c,&cost);
}

}
return headt[0];
}
void print(head*a[],int n){
int i=0;
edge*p;
for(i=0;i<n;i++)
{p=a[i]->adjacent;
printf("%d:\t",i);
while(p!=NULL){
      printf("%d\t%d\t",p->veradj,p->cost);
      p=p->link;
}
printf("\n");
}
}

void ShortestPath(head*headt[],int v,int n,int dist[],int path[]){//单源无权图最短路径问题(类似图的广度优先遍历)
//headt[]头链表,v开始节点,n节点个数,dist[]保存路径长度,path[]保存前驱节点
int i=0;
for(i=0;i<n;i++)
{dist[i]=-1;
 path[i]=-1;
}
dist[v]=0;
int s[10];
int top=0,tail=0,count=0;
s[tail]=v;
tail=(tail+1)%10;
count++;
int u;
edge*p;
while(count!=0){
u=s[top];
top=(top+1)%10;
      count--;
p=headt[u]->adjacent;
while(p){
if(dist[p->veradj]==-1){
      s[tail]=p->veradj;
      tail=(tail+1)%10;
      count++;
      dist[p->veradj]=dist[u]+1;
      path[p->veradj]=u;
}
   p=p->link;
}
}
}
void DShortestPath(head*headt[],int v,int n,int dist[],int path[]){//单源正权最短路径问题(Dijkstra算法)
//headt[]头链表,v开始节点,n节点个数,dist[]保存路径长度,path[]保存前驱节点//贪心
//1_y初始化
int s[10];//标记是否被访问
edge*p;int u;int i=0;
for(i=0;i<n;i++)
{dist[i]=999;//应该设置成无穷大
      path[i]=-1;
      s[i]=0;
}
dist[v]=0;
s[v]=1;
p=headt[v]->adjacent;
u=v;//u代表即将访问的顶点

//2_y求从初始顶点v到其他各顶点的最短路径
int j=1;
for(j=1;j<=n-1;j++)
{
while(p){
if(s[p->veradj]!=1&&dist[u]+p->cost<dist[p->veradj])
{dist[p->veradj]=dist[u]+p->cost;
      path[p->veradj]=u;
}
p=p->link;
}

//3_y确定即将被访问的顶点
int imax=999;
for(i=0;i<n;i++){
if(s[i]!=1&&dist[i]<imax)
      {imax=dist[i];u=i;}
}
s[u]=1;
p=headt[u]->adjacent;
}
}
int main()
{  int n,i,v;
scanf("%d",&n);
    head*headt[10];
   headt[0]=build(n,headt);
    print(headt,n);
   printf("请输入你要开始的节点\n");
   scanf("%d",&v);
   int dist[10],path[10];
   //ShortestPath(headt,v,n,dist,path);
   DShortestPath(headt,v,n,dist,path);
   for(i=0;i<n;i++)
      printf("%d\t",dist[i]);
   printf("\n");
   for(i=0;i<n;i++)
      printf("%d\t",path[i]);
    return 0;
}

/*7
1 1
3 1
-1 0
3 1
4 1
-1 0
0 1
5 1
-1 0
2 1
4 1
5 1
6 1
-1 0
-1 0
-1 0
4 1
5 1
-1 0*///课本184页图6.17
/*6
1 12
2 5
3 8
-1 0
0 12
2 5
4 20
-1 0
0 5
1 5
3 6
4 10
5 8
-1 0
0 8
3 6
5 4
-1 0
1 20
2 10
5 9
-1 0
2 8
3 4
4 9
-1 0*///课本189页图(为保证算法一致性将1,2,3,4,5,6改为0,1,2,3,4,5)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值