贪心+动态,采用链表结构,很通用的
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#define close -1
#define true 1
typedef struct gpaths//构造求取路径的数据结构
{
int dimension;//图的大小
int *values;//指向邻接矩阵
int *nodes;//指向路径节点表
}gpaths;
typedef struct road
{
int node;//节点号
struct road *next;//下一个节点
}road;
typedef struct pathbucket
{
int node;
int head;
}pathbucket;
typedef struct greedyresult
{
pathbucket *p;
int *dest;
}greedyresult;
/*一维数组化为二维*/
int getelement(int *M,int dimension,int x,int y)//得到二维数组中的元素
{
return *(M+dimension*x+y);
}
int pushelement(int *M,int dimension,int x,int y,int element)//把元素压入二维数组
{
return (*(M+dimension*x+y)=element);
}
/*初始化*/
gpaths *initgpaths(int *source,int dimension)//source是原来的图邻接矩阵,dimension是大小
{
gpaths *g;
int i,j,element;
g=(gpaths *)malloc(sizeof(gpaths));
g->dimension=dimension;
g->values=(int *)malloc(sizeof(int)*dimension*dimension);
g->nodes=(int *)malloc(sizeof(int)*dimension*dimension);
memset(g->nodes,-1,dimension*dimension*4);//节点表清空
//将source复制到我们的数据结构,同时添加节点的初始连接信息
for(i=0;i<dimension;i++)
for(j=0;j<dimension;j++)
{
element=getelement(source,dimension,i,j);
if(element!=-1)
{
pushelement(g->values,dimension,i,j,element);
pushelement(g->nodes,dimension,i,j,j);
}
else
pushelement(g->values,dimension,i,j,-1);
}
return g;
}
/*推出所需要的所有信息*/
void createvalues(gpaths *g)
{
int i,j,k;
int v1,v2;
for(k=0;k<g->dimension;k++)//将N个节点逐一考虑,加入路径
for(i=0;i<g->dimension;i++)
for(j=0;j<g->dimension;j++)
{
v1=getelement(g->values,g->dimension,i,k);
v2=getelement(g->values,g->dimension,k,j);
//如果经过K节点得到更短路径,那么把K纳入,更新节点矩阵表
//使它总是标志两个元素之间最短路径中最后纳入的那个节点
if(v1!=-1&&v2!=-1)
{
if(((v1+v2)<getelement(g->values,g->dimension,i,j))||getelement(g->values,g->dimension,i,j)==-1)
{
v1=v1+v2;
pushelement(g->values,g->dimension,i,j,v1);
pushelement(g->nodes,g->dimension,i,j,k);
}
}
}
}
road *makepath(gpaths *g,int i,int j)//根据g中的信息,生成i-j的路径
{
road *r,*head,*p;
int flag=0;//指示本次扫描是否有新点被加入
if(getelement(g->values,g->dimension,i-1,j-1)==-1)
return NULL;
head=r=(road *)malloc(sizeof(road));
r->next=(road *)malloc(sizeof(road));
r->node=i-1;
r->next->node=j-1;
r->next->next=NULL;
do
{
r=head;
flag=0;
while(r->next!=NULL)
{
//发现有要被纳入路径的节点
if(getelement(g->nodes,g->dimension,r->node,r->next->node)!=r->next->node)
{
flag=1;//设置纳入标志
//纳入新点
p=r->next;
r->next=(road *)malloc(sizeof(road));
r->next->node=getelement(g->nodes,g->dimension,r->node,p->node);
r->next->next=p;
}
r=r->next;
}
}while(flag==1);//只要某次扫描没有一个新点被纳入则说明路径构造完毕
return head;//返回路径链表
}
int gleast(greedyresult *r,int dimension)
{
int i,gmin,least;
gmin=-1;
for(i=0;i<dimension;i++)
{
if((r->p+i)->node!=-1)continue;
if(gmin>*(r->dest+i)&&gmin!=-1&&*(r->dest+i)!=-1)
{
gmin=*(r->dest+i);
least=i;
}
if(gmin==-1&&*(r->dest+i)!=-1)
{
gmin=*(r->dest+i);
least=i;
}
}
if(gmin!=-1)
{
(r->p+least)->node=1;
return least;
}
else
{
return -1;
}
}
void modify(greedyresult *r,gpaths *g,int start,int least)
{
int i;
for(i=0;i<g->dimension;i++)
{
if(getelement(g->values,g->dimension,least,i)==-1)continue;
if(getelement(g->values,g->dimension,least,i)!=-1&&*(r->dest+i)!=-1)
{
if((*(r->dest+least)+getelement(g->values,g->dimension,least,i))<*(r->dest+i))
{
*(r->dest+i)=*(r->dest+least)+getelement(g->values,g->dimension,least,i);
(r->p+i)->head=least;
}
}
if(getelement(g->values,g->dimension,least,i)!=-1&&*(r->dest+i)==-1)
{
*(r->dest+i)=*(r->dest+least)+getelement(g->values,g->dimension,least,i);
(r->p+i)->head=least;
}
}
}
greedyresult *greedymethod(gpaths *g,int start)
{
int i,least;
greedyresult *r=NULL;
start--;//化为内部节点表达
r=(greedyresult *)malloc(sizeof(greedyresult));
r->p=(pathbucket *)malloc(sizeof(pathbucket)*g->dimension);
r->dest=(int *)malloc(sizeof(int)*g->dimension);
for(i=0;i<g->dimension;i++)//初始化桶
{
(r->p+i)->node=-1;
(r->p+i)->head=-1;
}
(r->p+start)->node=start;
(r->p+start)->head=start;
memcpy(r->dest,g->values+start*g->dimension,g->dimension*4);
for(i=0;i<g->dimension-1;i++)
{
least=gleast(r,g->dimension);
if(least==-1)continue;
modify(r,g,start,least);
}
return r;
}
road *greedypath(greedyresult *r,int start,int end)
{
road *rr,*temp;
start--;
end--;
if((r->p+end)->node==-1)return NULL;
rr=(road *)malloc(sizeof(road));
rr->node=start;
rr->next=(road *)malloc(sizeof(road));
rr->next->node=end;
rr->next->next=NULL;
while((r->p+rr->next->node)->head!=-1)
{
temp=rr->next;
rr->next=(road *)malloc(sizeof(road));
rr->next->node=(r->p+temp->node)->head;
rr->next->next=temp;
}
return rr;
}
//演示
void main()
{
gpaths *g;
road *r,*h,*d;
greedyresult *rr;
int i,j;
//测试数据
int a[7*7]={0,20,50,30,close,close,close,
close,0,25,close,close,70,close,
close,close,0,40,25,50,close,
close,close,close,0,55,close,close,
close,close,close,close,0,10,70,
close,close,close,close,close,0,50,
close,close,close,close,close,close,0};
int dest[7]={0};
//初始化数据结构
g=initgpaths(a,7);
//推算路径数据
/* createvalues(g);
printf("输入起始点: ");
scanf("%d",&j);
for(i=1;i<=g->dimension;i++)
{
if(i==j)continue;
printf("%d到%d的最短路径是: ",j,i);
r=h=makepath(g,j,i);//计算路径各点
if(r==NULL)
{
printf("%d到%d无路径/n",j,i);
continue;
}
//输出路径
while(r!=NULL)
{
printf("%d",r->node+1);
r=r->next;
if(r!=NULL)printf("----");
}
r=h;
//释放内存
while(r->next!=NULL)
{
d=r;
r=r->next;
free(d);
}
printf("/n");
printf("路径长度为%d",getelement(g->values,g->dimension,j-1,i-1));
printf("/n");
}*/
rr=greedymethod(g,3);
r=greedypath(rr,3,7);
}