普利姆算法
- 最小生成树,Minimum Spanning Tree
无向网的最小生成树是图的一个子集,在这个子集中,边的数量比顶点数量少1,所有顶点被这些边连接在一起,而且这些边的权值和为最小。值得一提的是,由于最终的结果为树,所以子集中不含有环(cycle). - Lazy Prim 算法
Lazy Prim算法需要使用优先队列(Priority Queue),队列中的元素为生成边,定义生成边的结构体如下:
typedef struct edge
{
int from; //start vertex
int to; //end vertex
VRType cost; //weight of cost
}edge;
以边中的权值为Priority Queue的主元素,建立最小堆。
主要代码如下:
typedef edge priority_queue_element;
void mst_prim_lazy(MGraph G, Heap H, int s, edge *mst_edges, int *mst_cost, int (*pf)(priority_queue_element e1, priority_queue_element e2))
{
int i;
int edge_count;
int node_index;
priority_queue_element arc;
for(i=0;i<G.vexnum;i++)
{
visited[i]=0;
}
*mst_cost=0;
edge_count=0;
add_edges(G,s,H,pf);
while(H->size>0 && edge_count!=(G.vexnum-1))
{
arc=heap_extract_min(H,pf);
node_index = arc.to;
if (!visited[node_index])
{
mst_edges[edge_count++]=arc;
*mst_cost+=arc.cost;
add_edges(G,node_index,H,pf);
}
}
//need to check if there is MST in the graph
return;
}
void add_edges(MGraph G,int node_index, Heap H, int (*pf)(priority_queue_element e1, priority_queue_element e2))
{
int v;
int w;
priority_queue_element arc;
visited[node_index]=1;
v=node_index;
for (w = FirstAdjVex(G, G.vexs[v]); w >= 0; w = NextAdjVex(G, G.vexs[v], G.vexs[w]))
{
if(!visited[w])
{
arc.from=v;
arc.to=w;
arc.cost=G.arcs[v][w].adj;
min_heap_insert(H,arc,pf);
}
}
}
int less_than(priority_queue_element e1, priority_queue_element e2)
{
return (e1.cost<e2.cost);
}
Main 函数如下:
int main(void)
{
Heap H;
MGraph G;
FILE *fp;
int i;
int mst_cost=0;
int s=0;
fp=fopen("UDN.txt","r");
CreateGraph(&G,fp);
edge mst_edges[G.vexnum-1];
init_min_heap(&H, G.arcnum);
mst_prim_lazy(G,H,s,mst_edges,&mst_cost,less_than);
for(i=0;i<G.vexnum-1;i++)
{
printf("-%c-%c-%d-\n", G.vexs[mst_edges[i].from], G.vexs[mst_edges[i].to], mst_edges[i].cost);
}
fclose(fp);
PressEnter;
return EXIT_SUCCESS;
}