,,基于稀疏图上的Johnson算法的详解

,,基于稀疏图上的Johnson算法的详解

本篇文章介绍了,稀疏图上的约翰逊算法的详解。需要的朋友参考下

算法步骤简述:

1.计算图G加入新结点后的图g ',加入的新结点0到所有原结点之间距离为0,同时形成新的边集e’;

2.使用贝尔曼-福特公司算法处理g ',并形成0结点到各结点的最小距离d。

3.如果贝尔曼-福特公司算法检测出有负权回路则提示错误的并退出,否则继续。

4.对所有' g '中的顶点v,根据0结点到v的最小距离,将h(v)设置为这个值。

5.对所有的边w(u,v),权值更新为w(u,v) h(u)-h(v)

6.对图G中所有结点运行迪克斯特拉算法计算与其他顶点最短距离d'[u][v]

(此处假定G和w集合是分开存储的。直接使用' g '也可以,因为0结点对其他结点是不可达的,但这显然浪费了计算时间。如果权值信息存在' g '中,可以对' g '进行操作,只不过跳过了0结点的处理)

7.原图G中最短距离d[u][v]=d'[u][v] h(v)-h(u)

代码中有的地方没有优化,比如辅助结构vassist其实在贝尔曼-福特公司算法和迪克斯特拉算法两个函数中用法稍微有所不同,而且成员变量在前者中只用了2个;同时松弛算法放松也有类似的情况。前者是简单的复用,后者直接用名字区分。

代码包含三部分:贝尔曼-福特算法、迪杰斯特拉算法、用二项堆实现的优先级数组(迪杰斯特拉算法要用到)。以下是算法的C语言版本,测试实例同 《算法导论》 图25-1复制代码代码如下:#包含stdio。h #包含stdlib。h

# define U 65535 # define PARENT(I)((I-1)/2)# define LEFT(I)(2 *(I)1)# define RIGHT(I)(2 *(I)2)# define N 5

结构顶点{ int key struct vtable * adj };

结构虚拟表{ int key//这个键是在顶点数组的序号//struct vertext * v;int w;struct vtable * next };

struct vassist { int d;int p;(同Internationalorganizations)国际组织键;};

int insert(struct vertex *,int,int,int,int);int walk(struct vertex *,int,int);struct va sist * initialize _ ss(int,int);int relaxd(int *,int,int,int);int relax b(struct va sist *,int,int,int);int build _ min _ heap(struct va sist *,int);int min _ heap ify(struct va sist *,int,int);int heap _ extract _ min(struct va sist *,int);堆中的int(struct va sist *,int,int);int heap _ decrease(struct va sist *,int,int);int dijkstra(struct vertex *,int,int,int * *);int bellman_ford(struct vertex *,int*,int,int);

int insert(struct vertex *p,int len,int i,int j,int w) { struct vtable *q,* prevq=p[i].adjprintf('key:%d\n ',p[i].关键);prev=NULL而(q!=NULL) { if (q-key==j) { printf('错误:v %d到%d已经存在. \n ',I,j);返回0;} else { prev=q;q=q-next;} } q=(struct vtable *)malloc((struct vtable)的大小);q-key=j;q-w=w;q-next=NULL;if(prev!=NULL)prev-next=q;else p[i].adj=q;返回1;}

int walk(struct vertex *p,int len,int i) { struct vtable *q=p[i].形容词而(q!=NULL) { printf(' %d,w是%d\n ',q-key,q-w);q=q-next;} printf(' \ n ');}

struct va sist * initialize _ ss(int size,int s){ int I;struct va sist * vava=(struct va sist *)malloc(size * sizeof(struct va sist));for(I=0;isizei ) { va[i].key=I;//建堆后我!=密钥va[i].d=U;va[i].p=-1;} va[s].d=0;返回va;}

//relax for dijkstraint relax d(int * p,int u,int v,int w) {//w=w(u,v)if(p[v]p[u]w){ p[v]=p[u]w;//为了简单处理,p使用的是数组//没有父母标记//如果想用父母标记,请将p改为一个自定义的结构体}返回1;}

//relax for belt man _ fordint relax b(struct va sist * va,int u,int v,int w) {//w=w(u,v) if(va[v].dva[u].va[v].d=va[u].d w;va[v].p=u;}返回1;}

国际贝尔曼_福特(结构顶点*图形,int *h,int大小,int s) {//算法要求不含源点可达的负权回路int i,j;struct vtable * p;struct va sist * vava=initialize _ ss(size,s);for(I=1;isi zei)for(j=0;jsize-1;j ) { p=graph[j].形容词而(p!=NULL) { relaxb(va,j,p-key,p-w);p=p-next;} }

printf('from %d,\n ',s);for(j=0;jsizej ) printf('to %d: %d\n ',j,va[j].d);

for(j=0;jsizej ) {//对0结点不必要p=图形[j]的缩写.形容词而(p!=NULL) { if(va[p-key].dva[j].d p-w)返回0;p=p-next;} } for(j=1;j=尺寸;h[j]=va[j].d;免费(va);h[0]=0;返回1;}

int build _ min _ heap(struct va sist * va,int size) {//建堆int I;for(I=大小/2-1;I=0;i - ) min_heapify(va,I,size);

返回1;}

int min _ heap ify(struct va sist * va,int i,int heap_size) { int l,r,min;结构温度;int tmin=U;l=左;r=右;if ((l heap_size) (va[l]).dva[i].d)){ min=l;tmin=va[l].d;} else { min=I;tmin=va[i].d;} if ((r heap_size) (va[r]).dva[最小值]。d)){ min=r;tmin=va[r].d;}如果(!(min==i)) { temp.d=va[min].d;temp.p=va[min].p;temp.key=va[min].关键;

va[最小值]。d=va[i].d;va[最小值]。p=va[i].p;va[最小值]。key=va[i].关键;

va[i].d=温度;va[i].p=temp.pva[i].key=temp.key

min_heapify(va,min,heap _ size);}返回1;}

int heap _ extract _ min(struct va sist * va,int heap _ size){ int min;if ( heap_size1)返回-1;min=va[0].关键;va[0].p=va[堆大小-1]。p;va[0].d=va[堆大小-1]。d;va[0].key=va[heap_size -1].关键;堆大小=堆大小-1;min_heapify(va,0,heap _ size);返回最小值;}

int in heap(struct va sist * va,int heap_size,int j){ int I;for(I=0;iheap _ sizei ) if(va[i].key==j)返回我;return-1;}

int heap _ decrease(struct va sist * va,int i,int key _ new){ struct va sist temp;if(key_newva[i].d)返回0;va[i].d=key _ new while((i0)(va[PARENT(I)].d va[i].d)) { temp.d=va[i].d;temp.p=va[i].p;temp.key=va[i].关键;va[i].d=va[父代(一)].d;va[i].p=va[父代(一)].p;va[i].key=va[PARENT(i)].关键;父代d=。温度;父代p=临时温度父代. key=temp.keyi=父代;}返回1;}

int dijkstra(struct vertex *graph,int len,int s,int **delta) { int i,j,heap _ size struct vtable * q;struct v assist * vaint * p;p=(int *)malloc(len * sizeof(int));for(I=0;ilenI)p[I]=U;p[s]=0;堆大小=长度

va=initialize_ss(len,s);build_min_heap(va,heap _ size);//va被拿去建堆,后续输出距离时不能再用了

while(heap _ size 0){ I=heap _ extract _ min(va,heap _ size);printf('node:%d\n ',I);heap _ size-;for(j=0;jheap _ sizej ) printf('key:%d,d:%d,in数组:%d\n ',va[j].弗吉尼亚州基[j]的缩写.d,p[va]j .key]);q=图形[我].形容词而(q!=NULL) { j=inheap(va,heap_size,q-key);if(j=0) if(va[j].dp[i] q-w) heap_decrease(va,j,p[I]q-w);relaxd(p,I,q-key,q-w);//其实可以合并heap_decreas和放松,不过为了接口简单没有这样做printf('将%d放松到%d,w是%d\n ',I,q-key,q-w);q=q-next;} for(j=0;jheap _ sizej ) printf('key:%d,d:%d,in数组:%d\n ',va[j].弗吉尼亚州基[j]的缩写.d,p[va]j .key]);} for(I=0;ileni ) printf('从%d到%d,距离是%d\n ',s,I,p[I]);

免费(va);

for(I=0;ilenI){ delta[s][I]=p[I];}免费(p);

}

int **johnson(struct vertex *g,int n) { int i,j;int *h,**delta,* * d;结构顶点* gnstructvtable * p;gn=(结构顶点*)malloc(n*sizeof(结构顶点));h=(int *)malloc(n * sizeof(int));delta=(int * *)malloc(n * sizeof(int *));d=(int * *)malloc(n * sizeof(int *));for(I=0;在;I){ delta[I]=(int *)malloc(n * sizeof(int));d[I]=(int *)malloc(n * sizeof(int));} for(I=0;在;I)gn[I]=g[I];

for(I=1;在;我)插入(gn,n,0,I,0);如果(!bellman_ford(gn,h,n,0)) { printf('输入图包含负权循环. \ n ');返回NULL}

for(I=0;在;i ) { p=gn[i].形容词而(p!=NULL){ p-w=p-w h[I]-h[p-key];p=p-next;} } for(I=0;在;我)行走(gn,n,I);

printf(' before Dijkstra \ n ');for(I=1;在;i ) { dijkstra(gn,n,I,delta);for(j=1;jn;j)d[I][j]=delta[I][j]h[j]-h[I];

} for(I=1;在;I){ for(j=1;jn;j ) printf('%d\t ',d[I][j]);printf(' \ n ');} return d;}

int main(){ int i,j;int * * d;结构顶点N . 1 );//为0结点的加入预留位置for(I=0;iN 1;[医]例.adj=NULL例】. key=I;}

插入(vt,N 1,1,2,3);插入(vt,N 1,1,3,8);插入(vt,N 1,1,5,-4);插入(vt,N 1,2,4,1);插入(vt,N 1,2,5,7);插入(vt,N 1,3,2,4);插入(vt,N 1,4,3,-5);插入(vt,N 1,4,1,2);插入(vt,N 1,5,4,6);d=约翰逊(vt,N ^ 1);

返回1;}

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • word文档无法编辑是怎么回事-
  • 华为手机怎么设置返回键(华为手机下面的三个按键设置方法)
  • lumia950怎么样(Lumia950体验分享)
  • otg连接是什么意思(OTG连接手机方法)
  • 笔记本触摸板怎么右键(笔记本电脑触控板手势操作设置)
  • 真我x7怎么样(realme X7 系列体验)
  • 苹果的A16处理器有多强(苹果的A16处理器的介绍)
  • 小米互传怎么用(小米手机的连接与共享教程)
  • 怎么设置电脑桌面图标自动对齐 设置电脑桌面自动整理图标的方法
  • 宽带错误651最简单解决方法(处理宽带错误651的措施)
  • 大学生手机有什么推荐(大学生换手机攻略)
  • 天玑1100和骁龙778g哪个好(骁龙778G、天玑900、天玑1100购选建议)
  • yum update 升级报错的解决办法
  • Windows10禁用屏保教程
  • 连接wifi显示无互联网连接怎么办(无线连上了却不能上网处理绝招)
  • 留言与评论(共有 条评论)
       
    验证码: