用链表还原实现Dijkastra算法

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;
}

运行结果为:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值