弗洛伊德算法c语言

求计算机求解关系R的传递闭包 C语言算法

传递闭包,最简单的技术是采用 【弗洛伊德算法】

Floyd-Warshall算法(Floyd-Warshall algorithm)是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径问题,同时也被用于计算有向图的传递闭包。

Floyd-Warshall算法的时间复杂度为O(N3),空间复杂度为O(N2)。

Floyd-Warshall算法的原理是动态规划。

设Di,j,k为从i到j的只以(1..k)集合中的节点为中间节点的最短路径的长度。

1.若最短路径经过点k,则Di,j,k = Di,k,k − 1 + Dk,j,k − 1;

2.若最短路径不经过点k,则Di,j,k = Di,j,k − 1。

因此,Di,j,k = min(Di,k,k − 1 + Dk,j,k − 1,Di,j,k − 1)。

在实际算法中,为了节约空间,可以直接在原来空间上进行迭代,这样空间可降至二维。

代码请见:

C++ 弗洛伊德算法

#includecstdio

#includecstdlib

using namespace std;

int map[105][105];

int main()

{

int m,n,i,j,k,x,y,a,b,t;

scanf(“%d”,n,m);

for(i=1;i=n;i++)

for(j=1;j=n;j++)

map[i][j]=999999999;

for(i=1;i=m;i++)

{

scanf(“%d%d%d”,x,y,t);

map[x][y]=t;

}

for(k=1;k=n;k++)

{

for(i=1;i=n;i++)

{

for(j=1;j=n;j++)

{

if(map[i][j]map[i][k]+map[k][j])

map[i][j]=map[i][k]+map[k][j];

}

}

}

scanf(“%d%d”,a,b);

printf(“%d\n”,map[a][b]);

system(“pause”);

return 0;

}

第8行的scanf(“%d”,n,m);这里是不是写错了?

弗洛伊德算法c语言

c语言数据结构(考题,测试你的能力)--编写源代码

P88 稀疏矩阵十字链表相加算法如下:

/*假设ha为A稀疏矩阵十字链表的头指针,hb为B稀疏矩阵十字链表的头指针*/

#includestdio.h

#define maxsize 100

struct linknode

{ int i,j;

struct linknode *cptr,*rptr;

union vnext

{ int v;

struct linknode *next;} k;

};

struct linknode creatlindmat( ) /*建立十字链表*/

{ int x, m, n, t, s, i, j, k;

struct linknode *p , *q, *cp[maxsize],*hm;

printf(“请输入稀疏矩阵的行、列数及非零元个数\n”);

scanf(“%d%d%d”,m,n,t);

if (mn) s=m; else s=n;

hm=(struct linknode*)malloc(sizeof(struct linknode)) ;

hm-i=m; hm-j=n;

cp[0]=hm;

for (i=1; i=s;i++)

{ p=(struct linknode*)malloc(sizeof(struct linknode)) ;

p-i=0; p-j=0;

p-rptr=p; p-cptr=p;

cp[i]=p;

cp[i-1]-k.next=p;

}

cp[s]-k.next=hm;

for( x=1;x=t;x++)

{ printf(“请输入一个三元组(i,j,v)\n”);

scanf(“%d%d%d”,i,j,k);

p=(struct linknode*)malloc(sizeof(struct linknode));

p-i=i; p-j=j; p-k.v=k;

/*以下是将p插入到第i行链表中 */

q=cp[i];

while ((q-rptr!=cp[i]) ( q-rptr-jj))

q=q-rptr;

p-rptr=q-rptr;

q-rptr=p;

/*以下是将P插入到第j列链表中*/

q=cp[j];

while((q-cptr!=cp[j]) ( q-cptr-ii))

q=q-cptr;

p-cptr=q-cptr;

q-cptr=p;

}

return hm;

}

/* ha和hb表示的两个稀疏矩阵相加,相加的结果放入ha中*/

struct linknode *matadd(struct linknode *ha, struct linknode *hb)

{ struct linknode *pa, *pb, *qa, *ca,*cb,*p,*q;

struct linknode *hl[maxsize];

int i , j, n;

if((ha-i!=hb-i)||(ha-j!=hb-j))

printf(“矩阵不匹配,不能相加\n”);

else

{ p=ha-k.next; n=ha-j;

for (i=1;i=n; i++)

{ hl[i]=p;

p=p-k.next;

}

ca=ha-k.next; cb=hb-k.next;

while(ca-i==0)

{pa=ca-rptr; pb=cb-rptr;

qa=ca;

while(pb-j!=0)

{ if((pa-jpb-j)(pa-j!=0))

{ qa=pa; pa=pa-rptr;}

else if ((pa-jpb-j)||(pa-j==0)) /*插入一个结点*/

{ p=(struct linknode*)malloc(sizeof(struct linknode));

p-i=pb-i; p-j=pb-j;

p-k.v=pb-k.v;

qa-rptr=p; p-rptr=pa;

qa=p; pb=pb-rptr;

j=p-j; q=hl[j]-cptr;

while((q-ip-i)(q-i!=0))

{ hl[j]=q; q=hl[j]-cptr;}

hl[j]-cptr=p; p-cptr=q;

hl[j]=p;

}

else

{pa-k.v=pa-k.v+pb-k.v;

if(pa-k.v==0) /*删除一个结点*/

{ qa-rptr=pa-rptr;

j=pa-j; q=hl[j]-cptr;

while (q-ipa-i)

{hl[j]=q; q=hl[j]-cptr;}

hl[j]-cptr=q-cptr;

pa=pa-rptr; pb=pb-rptr;

free(q);

}

else

{ qa=pa; pa=pa-rptr;

pb=pb-rptr;

}

}

}

ca=ca-k.next; cb=cb-k.next;

}

}

return ha;

}

void print(struct linknode *ha) /*输出十字链表*/

{ struct linknode *p,*q;

p=ha-k.next;

while(p-k.next!=ha)

{ q=p-rptr;

while(q-rptr!=p)

{ printf(“%3d%3d%3d\t”,q-i,q-j,q-k.v);

q=q-rptr;

}

if(p!=q)

printf(“%3d%3d%3d”,q-i,q-j,q-k.v);

printf(“\n”);

p=p-k.next;

}

q=p-rptr;

while(q-rptr!=p)

{ printf(“%3d%3d%3d\t”,q-i,q-j,q-k.v);

q=q-rptr;

}

if(p!=q)

printf(“%3d%3d%3d”,q-i,q-j,q-k.v);

printf(“\n”);

}

void main()

{

struct linknode *ha=NULL,*hb=NULL,*hc=NULL;

ha=creatlindmat( ); /*生成一个十字链表ha*/

hb=creatlindmat( ); /*生成另一个十字链表hb*/

printf(“A:\n”); /*输出十字链表ha*/

print(ha);printf(“\n”);

printf(“B:\n”); /*输出十字链表hb*/

print(hb);printf(“\n”);

hc=matadd(ha,hb); /*十字链表相加*/

printf(“A+B:\n”); /*输出相加后的结果*/

print(hc);printf(“\n”);

}

P94 数据类型描述如下:

#define elemtype char

struct node1

{ int atom;

struct node1 *link;

union

{

struct node1 *slink;

elemtype data;

} ds;

}

P95 数据类型描述如下:

struct node2

{ elemtype data;

struct node2 *link1,*link2;

}

P96 求广义表的深度depth(LS)

int depth(struct node1 *LS)

{

int max=0,dep;

while(LS!=NULL)

{ if(LS-atom==0) //有子表

{ dep=depth(LS-ds.slink);

if(depmax) max=dep;

}

LS=LS-link;

}

return max+1;

}

P96 广义表的建立creat(LS)

void creat(struct node1 *LS)

{

char ch;

scanf(“%c”,ch);

if(ch==’#’)

LS=NULL;

else if(ch=='(‘)

{LS=(struct node*)malloc(sizeof(struct node));

LS-atom=0;

creat(LS-ds.slink);

}

else

{ LS=(struct node*)malloc(sizeof(struct node));

LS-atom=1;

LS-ds.data=ch;

}

scanf(“%c”,ch);

if(LS==NULL);

else if(ch==’,’)

creat(LS-link);

else if((ch==’)’)||(ch==’;’))

LS-link=NULL;

}

P97 输出广义表print(LS)

void print(struct node1 *LS)

{

if(LS-atom==0)

{

printf(“(“);

if(LS-ds.slink==NULL)

printf(“#”);

else

print(LS-ds.slink);

}

else

printf(“%c “,LS-ds.data);

if(LS-atom==0)

printf(“)”);

if(LS-link!=NULL)

{

printf(“;”);

print(LS-link);

}

}

P98 该算法的时间复杂度为O(n)。整个完整程序如下:

#includestdio.h

#define elemtype char

struct node1

{ int atom;

struct node1 *link;

union

{

struct node1 *slink;

elemtype data;

} ds;

};

void creat(struct node1 LS) /*建立广义表的单链表*/

{

char ch;

scanf(“%c”,ch);

if(ch==’#’)

LS=NULL;

else if(ch=='(‘)

{LS=(struct node1*)malloc(sizeof(struct node1));

LS-atom=0;

creat(LS-ds.slink);

}

else

{ LS=(struct node1*)malloc(sizeof(struct node1));

LS-atom=1;

LS-ds.data=ch;

}

scanf(“%c”,ch);

if(LS==NULL);

else if(ch==’,’)

creat(LS-link);

else if((ch==’)’)||(ch==’;’))

LS-link=NULL;

}

void print(struct node1 LS) /*输出广义单链表*/

{

if(LS-atom==0)

{

printf(“(“);

if(LS-ds.slink==NULL)

printf(“#”);

else

print(LS-ds.slink);

}

else

printf(“%c”,LS-ds.data);

if(LS-atom==0)

printf(“)”);

if(LS-link!=NULL)

{

printf(“;”);

print(LS-link);

}

}

int depth(struct node1 LS) /*求广义表的深度*/

{

int max=0;

while(LS!=NULL)

{ if(LS-atom==0)

{ int dep=depth(LS-ds.slink);

if(depmax) max=dep;

}

LS=LS-link;

}

return max+1;

}

main()

{ int dep;

struct node1 *p=NULL;

creat(p); /*建立广义表的单链表*/

print(p); /*输出广义单链表*/

dep=depth(p); /*求广义表的深度*/

printf(“%d\n”,dep);

}

第六章 树

P109 二叉链表的结点类型定义如下:

typedef struct btnode

{ anytype data;

struct btnode *Lch,*Rch;

}tnodetype;

P109 三叉链表的结点类型定义如下:

typedef struct btnode3

{ anytype data;

struct btnode *Lch,*Rch,*Parent ;

}tnodetype3;

P112 C语言的先序遍历算法:

void preorder (tnodetype *t)

/*先序遍历二叉树算法,t为指向根结点的指针*/

{ if (t!=NULL)

{printf(“%d “,t-data);

preorder(t-lch);

preorder(t-rch);

}

}

P113 C语言的中序遍历算法:

void inorder(tnodetype *t)

/*中序遍历二叉树算法,t为指向根结点的指针*/

{

if(t!=NULL)

{inorder(t-lch);

printf(“%d “,t-data);

inorder(t-rch);

}

}

P113 C语言的后序遍历算法:

void postorder(tnodetype *t)

/*后序遍历二叉树算法,t为指向根结点的指针*/

{

if(t!=NULL)

{ postorder(t-lch);

postorder(t-rch);

printf(“%d “,t-data);

}

}

P114 如果引入队列作为辅助存储工具,按层次遍历二叉树的算法可描述如下:

void levelorder(tnodetype *t)

/*按层次遍历二叉树算法,t为指向根结点的指针*/

{tnodetype q[20]; /*辅助队列*/

front=0;

rear=0; /*置空队列*/

if (t!=NULL)

{ rear++;

q[rear]=t; /*根结点入队*/

}

while (front!=rear)

{ front++;

t=q [front];

printf (“%c\n”,t-data);

if (t-lch!=NULL) /*t的左孩子不空,则入队*/

{ rear++;

q [rear]=t-lch;

}

if (t-rch!=NULL) /*t的右孩子不空,则入队*/

{ rear++;

q [rear]=t-rch;

}

}

}

P115 以中序遍历的方法统计二叉树中的结点数和叶子结点数,算法描述为:

void inordercount (tnodetype *t)

/*中序遍历二叉树,统计树中的结点数和叶子结点数*/

{ if (t!=NULL)

{ inordercount (t-lch); /*中序遍历左子树*/

printf (“%c\n”,t-data); /*访问根结点*/

countnode++; /*结点计数*/

if ((t-lch==NULL)(t-rch==NULL))

countleaf++; /*叶子结点计数*/

inordercount (t-rch); /*中序遍历右子树*/

}

}

P115 可按如下方法计算一棵二叉树的深度:

void preorderdeep (tnodetype *t,int j)

/*先序遍历二叉树,并计算二叉树的深度*/

{ if (t!=NULL)

{ printf (“%c\n”,t-data); /*访问根结点*/

j++;

if (kj) k=j;

preorderdeep (t-lch,j); /*先序遍历左子树*/

preorderdeep (t-rch,j); /*先序遍历右子树*/

}

}

P117 线索二叉树的结点类型定义如下:

struct nodexs

{anytype data;

struct nodexs *lch, *rch;

int ltag,rtag; /*左、右标志域*/

}

P117 中序次序线索化算法

void inorderxs (struct nodexs *t)

/*中序遍历t所指向的二叉树,并为结点建立线索*/

{ if (t!=NULL)

{ inorderxs (t-lch);

printf (“%c\n”,t-data);

if (t-lch!=NULL)

t-ltag=0;

else { t-ltag=1;

t-lch=pr;

} /*建立t所指向结点的左线索,令其指向前驱结点pr*/

if (pr!=NULL)

{ if (pr-rch!=NULL)

pr-rtag=0;

else { pr-rtag=1;

pr-rch=p;

}

} /*建立pr所指向结点的右线索,令其指向后继结点p*/

pr=p;

inorderxs (t-rch);

}

}

P118 在中根线索树上检索某结点的前驱结点的算法描述如下:

struct nodexs * inpre (struct nodexs *q)

/*在中根线索树上检索q所指向的结点的前驱结点*/

{ if (q-ltag==1)

p=q-lch;

else { r=q-lch;

while (r-rtag!=1)

r=r-rch;

p=r;

}

return (p);

}

P119 在中根线索树上检索某结点的后继结点的算法描述如下:

struct nodexs * insucc (struct nodexs *q)

/*在中根线索树上检索q所指向的结点的后继结点*/

{ if (q-rtag==1)

p=q-rch;

else { r=q-rch;

while (r-ltag!=1)

r=r-lch;

p=r;

}

return (p);

}

P120 算法程序用C语言描述如下:

void sortBT(BT *t,BT *s) /*将指针s所指的结点插入到以t为根指针的二叉树中*/

{ if (t==NULL) t=s; /*若t所指为空树,s所指结点为根*/

else if (s-data t-data)

sortBT(t-lch,s); /*s结点插入到t的左子树上去*/

else

sortBT(t-rch,s); /*s结点插入到t的右子树上去*/

}

P121 二叉排序树结点删除算法的C语言描述如下:

void delnode(bt,f,p)

/*bt为一棵二叉排序树的根指针,p指向被删除结点,f指向其双亲*/

/*当p=bt时f为NULL*/

{ fag=0; /*fag=0时需修改f指针信息,fag=1时不需修改*/

if (p-lch==NULL)

s=p-rch; /*被删除结点为叶子或其左子树为空*/

else if (p-rch==NULL)

s=p-lch;

else { q=p; /*被删除结点的左、右子树均非空*/

s=p-lch;

while (s-rch!=NULL)

{ q=s;

s=s-rch;

} /*寻找s结点*/

if (q=p)

q-lch=s-lch;

else q-rch=s-lch;

p-data=s-data; /*s所指向的结点代替被删除结点*/

DISPOSE(s);

Fag=1;

}

if (fag=0) /*需要修改双亲指针*/

{ if (f=NULL)

bt=s; /*被删除结点为根结点*/

else if (f-lch=p)

f-lch=s;

else f-rch=s;

DISPOSE(p); /*释放被删除结点*/

}

}

第七章 图

P134 用邻接矩阵表示法表示图,除了存储用于表示顶点间相邻关系的邻接矩阵外,通常还需要用一个顺序表来存储顶点信息。其形式说明如下:

# define n 6 /*图的顶点数*/

# define e 8 /*图的边(弧)数*/

typedef char vextype; /*顶点的数据类型*/

typedef float adjtype; /*权值类型*/

typedef struct

{vextype vexs[n];

adjtype arcs[n][n];

}graph;

P135 建立一个无向网络的算法。

CREATGRAPH(ga) /*建立无向网络*/

Graph * ga;

{

int i,j,k;

float w;

for(i=0;in;i++ )

ga -vexs[i]=getchar(); /*读入顶点信息,建立顶点表*/

for(i=0;in;i++ )

for(j=0;jn;j++)

ga -arcs[i][j]=0; /*邻接矩阵初始化*/

for(k=0;ke;k++) /*读入e条边*/

(scanf(“%d%d%f”,I,j,w); /*读入边(vi,vj)上的权w */

ga -arcs[i][j]=w;

ga – arcs[j][i]=w;

}

} /*CREATGRAPH*/

P136 邻接表的形式说明及其建立算法:

typedef struct node

{int adjvex; /*邻接点域*/

struct node * next; /*链域*/

}edgenode; /*边表结点*/

typedef struct

{vextype vertex; /*顶点信息*/

edgenode link; /*边表头指针*/

}vexnode; /*顶点表结点*/

vexnode ga[n];

CREATADJLIST(ga) /*建立无向图的邻接表*/

Vexnode ga[ ];

{int i,j,k;

edgenode * s;

for(i=o;in;i++= /*读入顶点信息*/

(ga[i].vertex=getchar();

ga[i].1ink=NULL; /*边表头指针初始化*/

}

for(k=0;ke;k++= /*建立边表*/

{scanf(“%d%d”,i,j); /*读入边(vi , vj)的顶点对序号*/

s=malloc(sizeof(edgenode)); /*生成邻接点序号为j的表结点*s */

s- adjvex=j;

s- – next:=ga[i].Link;

ga[i].1ink=s; /*将*s插入顶点vi的边表头部*/

s=malloc(size0f(edgende)); /*生成邻接点序号为i的边表结点*s */

s -adjvex=i;

s -next=ga[j].1ink;

ga[j].1ink=s; /*将*s插入顶点vj的边表头部*/

}

} /* CREATADJLIST */

P139 分别以邻接矩阵和邻接表作为图的存储结构给出具体算法,算法中g、g1和visited为全程量,visited的各分量初始值均为FALSE。

int visited[n] /*定义布尔向量visitd为全程量*/

Graph g; /*图g为全程量*/

DFS(i) /*从Vi+1出发深度优先搜索图g,g用邻接矩阵表示*/

int i;

{ int j;

printf(“node:%c\n” , g.vexs[i]); /*访问出发点vi+1 */

Visited[i]=TRUE; /*标记vi+l已访问过*/

for (j=0;jn;j++) /*依次搜索vi+1的邻接点*/

if((g.arcs[i][j]==1) &&(! visited[j]))

DFS(j); /*若Vi+l的邻接点vj+l未曾访问过,则从vj+l出发进行深度优先搜索*/

} /*DFS*/

vexnode gl[n] /*邻接表全程量*/

DFSL(i) /*从vi+l出发深度优先搜索图g1,g1用邻接表表示*/

int i;

{ int j;

edgenode * p;

printf(“node:%C\n” ,g1[i].vertex);

vistited[i]=TRUE;

p=g1[i].1ink; /*取vi+1的边表头指针*/

while(p !=NULL) /*依次搜索vi+l的邻接点*/

{

if(! Vistited[p -adjvex])

DFSL(p – adjvex); /*从vi+1的未曾访问过的邻接点出发进行深度优先搜索*/

p=p – next; /*找vi+l的下一个邻接点*/

}

} /* DFSL */

P142 以邻接矩阵和邻接表作为图的存储结构,分别给出宽度优先搜索算法。

BFS(k) /*从vk+l出发宽度优先搜索图g,g用邻接矩阵表示,visited为访问标志向量*/

int k;

{ int i,j;

SETNULL(Q); /*置空队Q */

printf(“%c\n”,g.vexs[k]); /*访问出发点vk+l*x/

visited[k]=TRUE; /*标记vk+l已访问过*/

ENQUEUE(Q,K); /*已访问过的顶点(序号)入队列*/

While(!EMPTY(Q)) /*队非空时执行*/

{i=DEQUEUE(Q); /*队头元素序号出队列*/

for(j=0;jn;j++)

if((g.arcs[i][j]==1)&&(! visited[j]))

{printf(“%c\n” , g.vexs[j]); /*访问vi+l的未曾访问的邻接点vj+l */

visited[j]=TRUE;

ENQUEUE(Q,j); /*访问过的顶点入队*/

}

}

} /* BFS */

BFSL(k) /*从vk+l出发宽度优先搜索图g1,g1用邻接表表示*/

int k

{ int i;

edgenode * p;

SETNULL(Q);

printf(“%c\n” , g1[k].vertex);

visited[k]=TRUE;

ENQUEUE(Q,k);

while(! EMPTY(Q));

{ i=DEQUEUE(Q);

p=g1[i].1ink /*取vi+l的边表头指针*/

while(p !=NULL) /*依次搜索vi+l的邻接点*/

{ if( ! visited[p – adjvex]) /*访问vi+l的未访问的邻接点*/

{ printf{“%c\n” , g1[p – adjvex].vertex};

visited[p – adjvex]=TRUE;

ENQUEUE(Q,p – adjvex); /*访问过的顶点入队*/

}

p=p – next; /*找vi+l的下一个邻接点*/

}

}

} /*BFSL*/

P148 在对算法Prim求精之前,先确定有关的存储结构如下:

typdef struct

{Int fromvex,endvex; /*边的起点和终点*/

float length; /*边的权值*/

} edge;

float dist[n][n]; /*连通网络的带权邻接矩阵*/

edgeT[n-1]; /*生成树*/

P149 抽象语句(1)可求精为:

for(j=1;jn;j++) /*对n-1个蓝点构造候选紫边集*/

{T[j-1].fromvex=1}; /*紫边的起点为红点*/

T[j-1].endvex=j+1; /*紫边的终点为蓝点*/

T[j-1].1ength=dist[0][j]; /*紫边长度*/

}

P149 抽象语句(3)所求的第k条最短紫边可求精为:

min=max; /*znax大于任何边上的权值*/

for (j=k;jn-1;j++) /*扫描当前候选紫边集T[k]到T[n-2],找最短紫边*/

if(T[j].1engthmin)

{min=T[j].1ength;m=j; /*记录当前最短紫边的位置*/

}

P149 抽象语句(4)的求精:

e=T[m];T[m]=T[k];T[k]=e, /* T[k]和T[m]交换*/

v=T[kl.Endvex]; /* v是刚被涂红色的顶点*/

P149 抽象语句(5)可求精为:

for(j=k+1;jn-1;j++) /*调整候选紫边集T[k+1]到T[n-2]*/

{d=dist[v-1][T[j].endvex-1]; /*新紫边的长度*/

if(dT[j].1ength) /*新紫边的长度小于原最短紫边*/

{T[j].1ength=d;

T[j].fromvex=v; /*新紫边取代原最短紫边*/

}

}

P150 完整的算法:

PRIM() /*从第一个顶点出发构造连通网络dist的最小生成树,结果放在T中*/

{int j , k , m , v , min , max=l0000;

float d;

edge e;

for(j=1;jn;j++) /*构造初始候选紫边集*/

{T[j-1].formvex=1; /*顶点1是第一个加入树中的红点*/

T[j-1].endvex=j+1;

T[j-1].length=dist[o][j];

}

for(k=0;kn-1;k++) /*求第k条边*/

{min=max;

for(j=k;jn-1;j++) /*在候选紫边集中找最短紫边*/

if(T[j].1engthmin)

{min=T[j].1ength;

m=j;

} /*T[m]是当前最短紫边*/

}

e=T[m];T[m]=T[k];T[k]=e; /*T[k]和T[m]交换后,T[k]是第k条红色树边*/

v=T[k].endvex ; /* v是新红点*/

for(j=k+1;jn-1;j++) /*调整候选紫边集*/

{d=dist[v-1][T[j].endvex-1];

if(dT[j].1ength);

{T[j].1ength=d;

T[j].fromvex=v;

}

}

} /* PRIM */

P151 Kruskl算法的粗略描述:

T=(V,φ);

While(T中所含边数n-1)

{从E中选取当前最短边(u,v);

从E中删去边(u,v);

if((u,v)并入T之后不产生回路,将边(u,v)并入T中;

}

P153 迪杰斯特拉算法实现。算法描述如下:

#define max 32767 /*max代表一个很大的数*/

void dijkstra (float cost[][n],int v)

/*求源点v到其余顶点的最短路径及其长度*/

{ v1=v-1;

for (i=0;in;i++)

{ dist[i]=cost[v1][i]; /*初始化dist*/

if (dist[i]max)

pre[i]=v;

else pre[i]=0;

}

pre[v1]=0;

for (i=0;in;i++)

s[i]=0; /*s数组初始化为空*/

s[v1]=1; /*将源点v归入s集合*/

for (i=0;in;i++)

{ min=max;

for (j=0;jn;j++)

if (!s[j] (dist[j]min))

{ min=dist[j];

k=j;

} /*选择dist值最小的顶点k+1*/

s[k]=1; /*将顶点k+1归入s集合中*/

for (j=0;jn;j++)

if (!s[j](dist[j]dist[k]+cost[k][j]))

{ dist[j]=dist[k]+cost[k][j]; /*修改 V-S集合中各顶点的dist值*/

pre[j]=k+1; /*k+1顶点是j+1顶点的前驱*/

}

} /*所有顶点均已加入到S集合中*/

for (j=0;jn;j++) /*打印结果*/

{ printf(“%f\n%d”,dist[j],j+1;);

p=pre[j];

while (p!=0)

{ printf(“%d”,p);

p=pre[p-1];

}

}

}

P155 弗洛伊德算法可以描述为:

A(0)[i][j]=cost[i][j]; //cost为图的邻接矩阵

A(k)[i][j]=min{A(k-1) [i][j],A(k-1) [i][k]+A(k-1) [k][j]}

其中 k=1,2,…,n

P155 弗洛伊德算法实现。算法描述如下:

int path[n][n]; /*路径矩阵*/

void floyd (float A[][n],cost[][n])

{ for (i=0;in;i++) /*设置A和path的初值*/

for (j=0;jn;j++)

{ if (cost[i][j]max)

path[i][j]=j;

else { path[i][j]=0;

A[i][j]=cost[i][j];

}

}

for (k=0;kn;k++)

/*做n次迭代,每次均试图将顶点k扩充到当前求得的从i到j的最短路径上*/

for (i=0;in;i++)

for (j=0;jn;j++)

if (A[i][j](A[i][k]+A[k]

Floyd算法是什么?

Floyd算法又称为弗洛伊德算法,插点法,是一种用于寻找给定的加权图中顶点间最短路径的算法。

通过一个图的权值矩阵求出它的每两点间的最短路径矩阵。

从图的带权邻接矩阵A=[a(i,j)] n×n开始,递归地进行n次更新,即由矩阵D(0)=A,按一个公式,构造出矩阵D(1);又用同样地公式由D(1)构造出D(2);……;最后又用同样的公式由D(n-1)构造出矩阵D(n)。矩阵D(n)的i行j列元素便是i号顶点到j号顶点的最短路径长度,称D(n)为图的距离矩阵,同时还可引入一个后继节点矩阵path来记录两点间的最短路径。

采用的是(松弛技术),对在i和j之间的所有其他点进行一次松弛。所以时间复杂度为O(n^3); 其状态转移方程如下: map[i,j]:=min{map[i,k]+map[k,j],map[i,j]} map[i,j]表示i到j的最短距离 K是穷举i,j的断点 map[n,n]初值应该为0,或者按照题目意思来做。

当然,如果这条路没有通的话,还必须特殊处理,比如没有map[i,k]这条路

如何利用弗洛伊德算法求多源最短路径问题c语言

for(k=1;k=n;++k)

for(i=1;i=n;++i)

for(j=1;j=n;++j)

if(f[i][j]f[i][k]+f[k][j])

f[i][j]=f[i][k]+f[k][j];

C++实现D算法F算法求最短路径具体程序

/* 用邻接矩阵表示的图的Dijkstra算法的源程序*/

#includestdio.h

#define MAXVEX 100

typedef char VexType;

typedef float AdjType;

typedef struct

{ VexType vexs[MAXVEX]; /* 顶点信息 */

AdjType arcs[MAXVEX][MAXVEX]; /* 边信息 */

int n; /* 图的顶点个数 */

}GraphMatrix;

GraphMatrix graph;

typedef struct {

VexType vertex; /* 顶点信息 */

AdjType length; /* 最短路径长度 */

int prevex; /* 从v0到达vi(i=1,2,…n-1)的最短路径上vi的前趋顶点 */

}Path;

Path dist[6]; /* n为图中顶点个数*/

#define MAX 1e+8

void init(GraphMatrix* pgraph, Path dist[])

{

int i; dist[0].length=0; dist[0].prevex=0;

dist[0].vertex=pgraph-vexs[0];

pgraph-arcs[0][0]=1; /* 表示顶点v0在集合U中 */

for(i=1; ipgraph-n; i++) /* 初始化集合V-U中顶点的距离值 */

{ dist[i].length=pgraph-arcs[0][i];

dist[i].vertex=pgraph-vexs[i];

if(dist[i].length!=MAX)

dist[i].prevex=0;

else dist[i].prevex= -1;

}

}

void dijkstra(GraphMatrix graph, Path dist[])

{ int i,j,minvex; AdjType min;

init(graph,dist); /* 初始化,此时集合U中只有顶点v0*/

for(i=1; igraph.n; i++)

{ min=MAX; minvex=0;

for(j=1; jgraph.n; j++)

if( (graph.arcs[j][j]==0) (dist[j].lengthmin) ) /*在V-U中选出距离值最小顶点*/

if(minvex==0) break; /* 从v0没有路径可以通往集合V-U中的顶点 */

graph.arcs[minvex][minvex]=1; /* 集合V-U中路径最小的顶点为minvex */

for(j=1; jgraph.n; j++) /* 调整集合V-U中的顶点的最短路径 */

{ if(graph.arcs[j][j]==1) continue;

if(dist[j].lengthdist[minvex].length+graph.arcs[minvex][j])

{ dist[j].length=dist[minvex].length+graph.arcs[minvex][j];

dist[j].prevex=minvex;

}

}

}

}

void initgraph()

{

int i,j;

graph.n=6;

for(i=0;igraph.n;i++)

for(j=0;jgraph.n;j++)

graph.arcs[i][j]=(i==j?0:MAX);

graph.arcs[0][1]=50;

graph.arcs[0][2]=10;

graph.arcs[1][2]=15;

graph.arcs[1][4]=5;

graph.arcs[2][0]=20;

graph.arcs[2][3]=15;

graph.arcs[3][1]=20;

graph.arcs[3][4]=35;

graph.arcs[4][3]=30;

graph.arcs[5][3]=3;

graph.arcs[0][4]=45;

}

int main()

{

int i;

initgraph();

dijkstra(graph,dist);

for(i=0;igraph.n;i++)

printf(“(%.0f %d)”,dist[i].length,dist[i].prevex);

return 0;

}

}

}

}

void initgraph()

{

int i,j;

graph.n=6;

for(i=0;igraph.n;i++)

for(j=0;jgraph.n;j++)

graph.arcs[i][j]=(i==j?0:MAX);

graph.arcs[0][1]=50;

graph.arcs[0][2]=10;

graph.arcs[1][2]=15;

graph.arcs[1][4]=5;

graph.arcs[2][0]=20;

graph.arcs[2][3]=15;

graph.arcs[3][1]=20;

graph.arcs[3][4]=35;

graph.arcs[4][3]=30;

graph.arcs[5][3]=3;

graph.arcs[0][4]=45;

}

int main()

{

int i;

initgraph();

dijkstra(graph,dist);

for(i=0;igraph.n;i++)

printf(“(%.0f %d)”,dist[i].length,dist[i].prevex);

return 0;

}

这个稍作改动就可以了。

本文来自投稿,不代表【】观点,发布者:【

本文地址: ,如若转载,请注明出处!

举报投诉邮箱:253000106@qq.com

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2024年3月24日 22:51:31
下一篇 2024年3月24日 23:00:25

相关推荐

  • c语言次方用什么表示,c语言次方用什么表示出来

    C语言中,如何表示一个变量的n次方? 1、C语言中计算一个数的N次方可以用库函数pow来实现。函数原型:double pow(double x,double y)。 2、用pow函数 pow函数的形式:pow(double x,double y);用来求解x的y次方。使用dupow函数时,如果变量原先定义为整型,需要强制转换为浮点型。举例:double a …

    2024年5月16日
    3800
  • aes加密解密c语言报告,c++ aes解密

    使用C/C++语言,将DES/AES加密算法,用代码实现 1、源代码文件加密后,不影响软件的正常编译,合法用户正常双击打开,在授权范围内使用。源代码加密软件推荐使用德人合科技的透明加密防泄密软件系统,是一套从源头上保障数据安全和使用安全的软件系统。 2、、nmake -f ms\ntdll.mak编译后在openssl解压目录下执行,完成编译后。 3、AES…

    2024年5月16日
    3500
  • 曾怡c语言视频教程>,曾瑛的c#教程

    哪里有C语言视频教程全集呀 1、《C语言视频教程》百度网盘高清资源免费在线观看 链接:https://pan.baidu.com/s/1qiSgpEBY5eb-K5LZsCnvSA 提取码:8yck 作品相关介绍:C语言是一门面向过程的、抽象化的通用程序设计语言,广泛应用于底层开发。 2、编程c语言视频在线搜索有资源。根据查询相关公开资料得知,编程c语言视频…

    2024年5月16日
    4600
  • c语言把两个字符串结合到一起,c语言将两个字符串合并成一个字符串

    C语言编程:编一程序,将两个字符串联接起来,不要用Strcat函数。_百度… 思路:输入两个字符串a和b,首先找到第一个字符串a的结束位置,接着把b的所有元素放到a的末尾,最后加上结束标志。 思路:字符串连接先需要找到第一字符串的结束位置,接着把第二字符串元素放到第一字符串后面,最后加上结束标志即可。 查找到第一个字符串的结尾 2 遍历第二个字符…

    2024年5月16日
    3000
  • c语言求112,C语言求1155之间所有偶数的平均值

    C语言问题 如果用户自己定义标识符,则下列不正确的是哪些?并且说明不正确的原因。 根据这些信息,只知道变量b周围的栈出了问题。建议用单步调试(vc0环境下按F10),跟踪一下几个变量,看看内存的情况,一点点定位问题。拓展:C语言是一门通用计算机编程语言,应用广泛。 C语言规定总是从main()开始执行的(这个函数也叫“主函数”)。因此,你发来的题目中的(8)…

    2024年5月16日
    3000
  • c语言写头文件,c 语言 头文件

    c语言头文件有哪些 1、c语言头文件如下:fprintf函数,功能:格式输出(文件)。fscanf函数,功能:格式输入(文件)。prntf函数,功能:格式输出(控制台)。scanf函数,功能:格式输入(控制台)。fclose函数,功能:关闭文件。 2、c语言头文件:fprintf函数,功能:格式输出(文件);fscanf函数,功能:格式输入(文件);prnt…

    2024年5月16日
    3700
  • c语言返回null,C语言返回值类型

    …与另一字符串相等的字符串,函数返回值为该字符串的地址或NULL… 1、strcat函数作用是把src所指向的字符串(包括“\0”)复制到dest所指向的字符串后面(删除*dest原来末尾的“\0”)。保证*dest足够长,以容纳被复制进来的*src。*src中原有的字符不变。 2、字符串比较函数,一般形式为strcmp(字符串1,字…

    2024年5月16日
    3500
  • c语言插入一个数,c语言中如何输入一个数

    在c语言中,如何在数组中插入一个数? 可以用下面代码把数插入一个排好序的数组,数组进行迭代取值。下面是数组排序的代码,这里是按大小排序的,每次取值和输入的数比较,比输入的数小,就往后移动移位,直到移出输入数该放的位置,反之也是。 C语言中,数组是一组连续的相同类型的数据集合。 所以要在数组中插入元素,需要按照以下步骤:找到插入点;将插入点所在元素,及之后的所…

    2024年5月16日
    3400
  • c语言小学数学测试系统,c语言小学算术运算测试程序

    用C语言编一个小学算术运算测试程序 int m=1,n=0,a,b,daan;while(1) //这里得解决/的情况,因为这里保证是整数,所以一些条件要满足才能除,若不成立,改为+得了。 case和后面的表达式用而个空格 隔开要 。char a 要在最前面定义。 设计的流程:1. 主界面设计,选择练习或测试,按ESC结束程序。 2. 题型选择界面设计,选择…

    2024年5月16日
    3400
  • 嗨翻c语言完整版pdf,嗨翻c语言适合入门吗

    嗨翻C语言的作者介绍 1、作者:(美国)维斯 译者:冯舜玺Mark Allen Weiss是佛罗里达国际大学计算机学院教授,普林斯顿大学计算机科学博士。 2、《C程序设计语言》这本书属于进阶水平 ,不太适合小白。 3、C语言是由UNIX的研制者丹尼斯·里奇(Dennis Ritchie)和肯·汤普逊(Ken Thompson)于1970年研制出的B语言的基础…

    2024年5月16日
    3700

发表回复

登录后才能评论



关注微信