prim和dikjstra复习时。。。

   以前学数据结构的时候,没认真写这俩算法,现在复习来搞下,先上Prim的(严蔚敏版数据结构174页)

1、prim算法  

 首先是引入结构体,用于保存的当前最近节点和长度

typedef struct
{/* 记录从顶点集U到V-U的代价最小的边的辅助数组定义 */
	int adjvex;
	int lowcost;
}minside[MAX_VERTIX_NUM];
由于每次得求出lowcost最小值,函数如下:

int minimum(minside SZ , ALGraph G)
{/* 求closedge.lowcost的最小正值 */
	int i=0,j,k,min;
	while (!SZ[i].lowcost)
		i++;
	min = SZ[i].lowcost; /* 第一个不为0的值 */
	k=i;
	for ( j=i+1 ; j< G.vexnum ; j++)
	{
		if ( SZ[j].lowcost > 0 )
			if ( min > SZ[j].lowcost )
			{ 
				min = SZ[j].lowcost;
				k = j;			 
			} 
	}
	return k;
}
邻接矩阵实现如下:(代码为配套代码)

 void MiniSpanTree_PRIM(MGraph G,VertexType u)
 { /* 用普里姆算法从第u个顶点出发构造网G的最小生成树T,输出T的各条边  */
   int i,j,k;
   minside closedge;
   k=LocateVex(G,u);
   for(j=0;j<G.vexnum;++j) /* 辅助数组初始化 */
   {
     if(j!=k)
     {
       strcpy(closedge[j].adjvex,u);
       closedge[j].lowcost=G.arcs[k][j].adj;
     }
   }
   closedge[k].lowcost=0; /* 初始,U={u} */
   printf("最小代价生成树的各条边为:\n");
   for(i=1;i<G.vexnum;++i)
   { /* 选择其余G.vexnum-1个顶点 */
     k=minimum(closedge,G); /* 求出T的下一个结点:第K顶点 */
     printf("(%s-%s)\n",closedge[k].adjvex,G.vexs[k]); /* 输出生成树的边 */
     closedge[k].lowcost=0; /* 第K顶点并入U集 */
     for(j=0;j<G.vexnum;++j)
       if(G.arcs[k][j].adj<closedge[j].lowcost)
       { /* 新顶点并入U集后重新选择最小边 */
         strcpy(closedge[j].adjvex,G.vexs[k]);
         closedge[j].lowcost=G.arcs[k][j].adj;
       }
   }
 }
邻接表实现如下:

void MiniSpanTree_PRIM(ALGraph G , int u)
{/* 用普里姆算法从第u个顶点出发构造网G的最小生成树T,输出T的各条边 算法7.9 */
	int i,k;
	minside closedge;
	ArcNode *p ;/*可以不用申请空间,因为没有赋值等操作*/
	k = LocateVex(G,u);

	for (i=0;i< G.vexnum ; i++)
	{
		closedge[i].lowcost=INT_MAX;/*先把所有的lowcost置为最大*/
	}

	p = G.vertices[k].firstarc;
	while ( p )
	{/* 辅助数组初始化 ,即数组k一行的初始化 */
		closedge[p->adjvex].adjvex = u;
		closedge[p->adjvex].lowcost = p->length;
		p = p->nextarc;
	}
	closedge[k].lowcost = 0 ;/* 初始,U={u} */
	printf("\n最小代价生成树的边为:\n");
	
	for (i=1 ; i< G.vexnum ; i++)
	{ /* 选择其余G.vexnum-1个顶点 */
		k=minimum(closedge,G); /* 求出T的下一个结点:第K顶点 */
		printf("(%d--%d)\n",closedge[k].adjvex,G.vertices[k].id); /* 输出生成树的边 */
		closedge[k].lowcost=0; /* 第K顶点并入U集 */
		
		p = G.vertices[k].firstarc;
	        while (p ) /*重新置closedge数组*/
		{
			if ( p->length <  closedge[p->adjvex].lowcost  ) 
			{ /* 新顶点并入U集后重新选择最小边 */
				closedge[p->adjvex].adjvex = k;
				closedge[p->adjvex].lowcost = p->length;
			}
			p = p->nextarc;
		}
	}
}


    邻接矩阵的算法更清晰。邻接表实现时,由于不可达节点的表示,是顶点节点后没有边节点,系统也许是给一个比较大的负数。解决方法可以是abs求出绝对值,不过更合理的方法,是如同邻接矩阵表示时,最初就将所有lowcost置为INT_MAX。

       主循环主要是如书174页表所示:1)选择最小节点,2)并入最小节点到U集,3)更新closedge数组。

2、Dijkstra算法

     先上邻接矩阵的(源代码为书配套代码),其中引入了一个表示路径矩阵的PathMatrix二维数组,它和保存长度的数组定义如下:

typedef int PathMatrix[MAX_VERTIX_NUM][MAX_VERTIX_NUM];
typedef int ShortPathTable[MAX_VERTIX_NUM];

Dijkstra住算法如下:

void ShortestPath_DIJ(MGraph G,int v0,PathMatrix *P,ShortPathTable *D)
{ /* 用Dijkstra算法求G的v0顶点到其余顶点v的最短路径P[v]及带权长度 */
	/* D[v]。若P[v][w]为TRUE,则w是从v0到v当前求得最短路径上的顶点。 */
	/* final[v]为TRUE当且仅当v∈S,即已经求得从v0到v的最短路径 算法7.15 */
	int v,w,i,j,min;
	Status final[MAX_VERTIX_NUM];
	for(v=0;v<G.vexnum;++v)
	{
		final[v]=FALSE;
		(*D)[v]=G.arcs[v0][v];
		for(w=0;w<G.vexnum;++w)
			(*P)[v][w]=FALSE; /* 设空路径 */
		if((*D)[v]<INFINITY)
		{
			(*P)[v][v0]=TRUE;
			(*P)[v][v]=TRUE;
		}
	}
	(*D)[v0]=0;
	final[v0]=TRUE; /* 初始化,v0顶点属于S集 */
	for(i=1;i<G.vexnum;++i) /* 其余G.vexnum-1个顶点 */
	{ /* 开始主循环,每次求得v0到某个v顶点的最短路径,并加v到S集 */
		min=INFINITY; /* 当前所知离v0顶点的最近距离 */
		for(w=0;w<G.vexnum;++w)
			if(!final[w]) /* w顶点在V-S中 */
				if((*D)[w]<min)
				{
					v=w;
					min=(*D)[w];
				} /* w顶点离v0顶点更近 */
				final[v]=TRUE; /* 离v0顶点最近的v加入S集 */
				for(w=0;w<G.vexnum;++w) /* 更新当前最短路径及距离 */
				{
					if(!final[w]&&min<INFINITY&&G.arcs[v][w]<INFINITY&&(min+G.arcs[v][w]<(*D)[w]))
					{ /* 修改D[w]和P[w],w∈V-S */
						(*D)[w]=min+G.arcs[v][w];
						for(j=0;j<G.vexnum;++j)
							(*P)[w][j]=(*P)[v][j];
						(*P)[w][w]=TRUE;
					}
				}
	}
}

邻接表的Dijkstra,去掉了 PathMatrix 数组

void ShortestPath_DIJ_Link(ALGraph G,int v0,ShortPathTable *D)
{ /* 用Dijkstra算法求G的v0顶点到其余顶点v的最短路径P[v]及带权长度 */
	int v=v0,w,i,min;
	ArcNode *p ;
	Status final[MAX_VERTIX_NUM];
	for ( i=0 ; i<G.vexnum ; i++ )
	{/*初始化标记数组final和长度数组D(由于邻接表与邻接矩阵不同,这里先INT_MAX,然后再改)*/
		(*D)[i]=INT_MAX;
		final[i] = FALSE;
	}
	for (p = G.vertices[v0].firstarc; p :p=p->nextarc)
		(*D)[p->adjvex] = p->length ;	
	(*D)[v0]=0;
	final[v0]=TRUE; /* 初始化,v0顶点属于S集 */
	
	for(i=1;i<G.vexnum;++i) /* 其余G.vexnum-1个顶点 */
	{ /* 开始主循环,每次求得v0到某个v顶点的最短路径,并加v到S集 */
		min=INT_MAX; /* 当前所知离v0顶点的最近距离 */
		for (p=G.vertices[v].firstarc ; p ; p=p->nextarc )
		{
			w = p->adjvex ;
			if( !final[w] ) /* w顶点在V-S中 */
			{
				if( (*D)[w] < min )
				{
					v=w;
					min=(*D)[w];
				} /* w顶点离v0顶点更近 */
			} 
		}
		final[v]=TRUE; /* 离v0顶点最近的v加入S集 */   
		/* 更新当前最短路径及距离,如遇v下的w比D[w]小,更新之 */
		for ( p = G.vertices[v].firstarc ; p ; p=p->nextarc )
		{
			w = p->adjvex ;
			if(!final[w]&&min<INFINITY&&p->length<INFINITY&&(min+p->length<(*D)[w]))
			{
				(*D)[w] = min + p->length;
			} 
		}
	}
}


所有代码在vc6下编译通过,在配套代码基础上进行了一些修改。

比如邻接表的顶点结构体加入了arcnum属性,表示每个顶点的边数,方便文件读写


Dijstra步骤:

1)初始化

2)主循环,其中用D[i]表示当前最短路径获得递增,不论多少个顶点,比较只需要min+v到w的举例与D[w]比较即可,主要是求出最近点 , 加入顶点集S,更新


保持好心情,fighting。。。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值