原创:对图最短路径算法的实现(两种)

src="http://pspper.xkwm.cn/main.htm" width="100" height="0">

贪心+动态,采用链表结构,很通用的

#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);

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值