最小生成树问题
来源:互联网 发布:php curl urlencode 编辑:程序博客网 时间:2024/06/05 20:18
假设要在n个城市之间建立通信网,则联通n个城市只需要n-1条线路,这是,自然会考虑如何在最节省经费的前提下建立这个通信网,这就是经典的最小生成树问题。
构造最小生成树有多种算法,多数利用最小生成树的MST性质,此处以普里姆算法为例。
MST性质:
N={V, {E}}是连通网, V顶点集合, E边的集合,
TE是N上最小生成树中边的集合
从U = {u0} (U0属于V),TE = { } 开始,重复执行下列错做:
在所有u属于V,v属于V-U的边(u, v)属于E中找一条代价最小的边(u0, v0)并入集合TE ,同时v0并入U,直至U=V为止,此时TE中必有n-1条边,则T = {U, {TE}}为最小生成树。
此处以数组法表示的无向网构造最小生成树,用邻接表示法表示的网算法与此类似。
首先构造一个无向网,再用该无向网从第0个顶点出发构造一棵最小生成树。
无向网G
构造后的最小生成树
#include <stdio.h>#define MAX 20 //最大顶点数typedef struct ArcCell //无向网中的弧{ int adj; //弧的权值}ArcCell, AdjMatrix[MAX][MAX];typedef struct MGraph //数组表示法表示图{ char vexs[MAX]; //顶点值 AdjMatrix arcs; //临接矩阵 int vexnum; //顶点数 int arcnum; //弧数}MGraph;typedef struct Arc //生成树中的弧{ int fir; //生成树中表示弧的第一个顶点 int sec; //生成树中表示弧的第二个顶点 int weight; //弧的权值}Arc;typedef struct Vex //生成树中的顶点{ char value; //存放顶点值}Vex;typedef struct MiniTree //最小生成树{ Arc arcs[MAX]; //弧 Vex vexs[MAX]; //顶点 int vexnum; //顶点数 int arcnum; //弧数}MiniTree;typedef enum Bool{FALSE, TRUE} Bool;typedef struct Temp //辅助结构{ int pos; //存放顶点编号 int lowcost; //存放最小值 Bool visited; //访问标志}Temp;//确定输入的顶点值在无向网中的位置int LocateVex(MGraph **G, char c){ int i; for(i=0; i<(*G)->vexnum; i++) { if((*G)->vexs[i] == c) return i; } return -1;}//数组表示法构造无向网void CreateUDN(MGraph *G){ int i, j, k; printf("Input vexnum and arcnum:\n"); //提示输入顶点数和弧数 scanf("%d", &(G->vexnum));getchar(); scanf("%d", &(G->arcnum));getchar(); printf("Input vex's value:\n"); //输入顶点值 for(i=0; i<G->vexnum; i++) { scanf("%c", &(G->vexs[i]));getchar(); } for(i=0; i<G->vexnum; i++) //初始化临接矩阵 { for(j=0; j<G->vexnum; j++) G->arcs[i][j].adj = 0; } printf("Input %d arc\n", G->arcnum); for(k=0; k<G->arcnum; k++) { char v1, v2; //两个顶点值int w; //两个顶点间的权值scanf("%c %c %d", &v1, &v2, &w);getchar();i = LocateVex(&G,v1);j = LocateVex(&G,v2);G->arcs[i][j].adj = G->arcs[j][i].adj = w; }}//选出辅助数组中未访问的非0最小值int selectMin(Temp *temp, MiniTree **mt){ //找到第一个不为0的元素,设为最小值 int i, min; for(i=0; i<(*mt)->vexnum; i++) { if(temp[i].lowcost != 0 && temp[i].visited == FALSE) break; } min = i; for(i=0; i<(*mt)->vexnum; i++) { if(temp[i].lowcost !=0 && temp[i].visited == FALSE){ if(temp[min].lowcost > temp[i].lowcost) min = i;} } return min;}//以无向网为例,从第u个顶点出发,构造最小生成树void CreateMiniTree(MGraph *G, int u, MiniTree *mt){ int i, j, k; Temp temp[MAX]; mt->vexnum = G->vexnum; mt->arcnum = mt->vexnum - 1; for(i=0; i<G->vexnum; i++) //辅助数组初始化 { if(i != u){ Temp t = {u, G->arcs[u][i].adj, FALSE}; temp[i] = t;} } Temp t = {u, 0, TRUE}; temp[u] = t; for(i=1; i<G->vexnum; i++) { k = selectMin(temp, &mt);mt->arcs[i-1].fir = temp[k].pos;mt->arcs[i-1].sec = k;mt->arcs[i-1].weight = temp[k].lowcost;temp[k].lowcost = 0; //第k个顶点并入Utemp[k].visited = TRUE;//开始调整下一行,保留存在路径的较小值及顶点值,保留之前lowcost为0后来存在路径的新值及顶点值for(j=0; j<G->vexnum; j++){ if(temp[j].visited == FALSE) { if(temp[j].lowcost != 0){ if(G->arcs[k][j].adj < temp[j].lowcost && G->arcs[k][j].adj != 0) { Temp t = {k, G->arcs[k][j].adj, FALSE};temp[j] = t; }}else{ if(G->arcs[k][j].adj != 0) { Temp t = {k, G->arcs[k][j].adj, FALSE};temp[j] = t; }} }} }}int main(){ int i, j, k; MGraph G; MiniTree mt; CreateUDN(&G); //构造无向网G for(i=0; i<G.vexnum; i++) //测试顶点值 { printf("%c ", G.vexs[i]); } printf("\n"); for(i=0; i<G.vexnum; i++) //测试临接矩阵 { for(j=0; j<G.vexnum; j++){ printf("%d ", G.arcs[i][j].adj);}printf("\n"); } CreateMiniTree(&G, 0, &mt); //从第0个元素(v1)开始构造最小生成树 for(i=0; i<mt.arcnum; i++) //输出构造的最小生成树的各个弧以及权值 { char fir = G.vexs[mt.arcs[i].fir];char sec = G.vexs[mt.arcs[i].sec]; int weight = mt.arcs[i].weight;printf("%c %c %d\n", fir, sec, weight); } printf("test\n"); return 0;}
输入G的顶点数和边数
输入G的顶点值,此处以1代表v1,2代表v2,以此类推
输入表示弧的两个顶点的编号以及弧的权值
显示构造的无向网G的各个顶点值 ,此处以1代表v1,2代表v2,以此类推
显示构造的无向网G的邻接矩阵
输出构成最小生成数的弧以及权值,
分别对应为 (v1, v3, 1)
(v3, v6, 4)
(v6, v4, 2)
(v3, v2, 5)
(v2, v5, 3)
- 最小生成树问题
- 最小生成树问题
- 最小生成树问题
- 最小生成树问题
- 最小生成树问题
- 最小生成树问题
- 最小生成树问题
- 最小生成树问题
- 最小生成树问题
- 最小生成树问题
- 最小生成树问题
- C++最小生成树问题
- 布线问题-最小生成树
- 最小生成树问题【PAT】
- 关于最小生成树问题
- 复习最小生成树问题
- 数据结构--最小生成树问题
- kruskal最小生成树问题
- 初入职场的感受与展望
- 如何在博客上保存网上的资源
- 云计算中的网络拓扑设计和Hadoop平台研究
- 别人的Emacs配置1
- 总结2013,展望2014
- 最小生成树问题
- DOS删除服务
- 排序(一)
- javascript禁用浏览器滚动条
- 判断字符串的编码
- [20140101_Examploe04]简单的Person类
- Android Animation之初涉动画
- 虚拟主机的配置
- wpf相关好资源(转)