🎉情人节快乐!
🎉 没有对象就搁这儿好好学习,有对象了就为了对象好好学习
🎉写在前面
最小生成树的问题还是比较热门的,最经典的莫过于Prime算法和Kruskal算法了,这篇博文我会详细讲解Prime算法的设计思想与具体代码的实现,不要求数据结构学的有多好,只要跟着我的思路来,一步一步的分析,调试,终能成就自己,那就让我们开始吧!
🎉目录
浅析最小生成树
Prime算法思想
此算法核心部分
结构体的选择
实现思路
构造实例
构造过程
代码详解
调试结果
总结
浅析最小生成树设G=(V,E)是无向连通带权图。E中每条边(v,w)的权为c[v][w]。
生成树:如果G的子图G’是一棵包含G的所有顶点的树,则称G’为G的生成树。
耗费:生成树上各边权的总和
最小生成树:在G的所有生成树中,耗费最小的生成树最小生成树在实际中有广泛应用。
例如,在设计通信网络时,用图的顶点表示城市,用边(v,w)的权c[v][w]表示建立城市v和城市w之间的通信线路所需的费用,则最小生成树就给出建立通信网络的最经济的方案。
Prime算法思想牵扯到贪心策略
设G=(V,E)是无向连通带权图,V={1,2,…,n};
设最小生成树T=(U,TE),算法结束时U=V,TE E。
首先,令U={u0},TE={}。然后,只要U是V的真子集,就做如下贪心选择:选取满足条件i U,j V-U,且边(i,j)是连接U和V-U的所有边中的最短边,即该边的权值最小。然后,将顶点j加入集合U,边(i,j)加入集合TE。继续上面的贪心选择一直进行到U=V为止,此时,选取到的所有边恰好构成G的一棵最小生成树T。需要注意的是,贪心选择这一步骤在算法中应执行多次,每执行一次,集合TE和U都将发生变化,即分别增加一条边和一个顶点。
此算法核心部分 结构体的选择选择一个合适的数据结构可以让程序的实现效率大大提高,难度大大降低;既然是生成最小生成树,不妨选择点和边结构体;因此创建两个结构体,第一个点node结构体包含所有的结点;第二个边结构体包含所有待选择的边、连接点及权值。
实现思路tips:onTreet 属性是布尔类型,为true时该结点在“树”上
首先对应第一个结点找我们需要的边,我们需要什么样的边呢,那就是在边的两个连接点中,有且仅有一个连结点等于结点的名称(这个可以在点结构体中加ID属性),并且这个结点必须是根结点(即onTree为true),满足这个条件,就把另一个连接点的onTree属性设为true;最后为了把满足条件的边连起来,我就个边结构体也加一个onTree属性,输出所有onTree 为true的边结构体即可。
构造实例按Prim算法对如图所示的无向连通带权图构造一棵最小生成树。
点和边结构体数组图示如上所示,我们需要的最终效果为下图所示:
#include
using namespace std;
struct Node {
int ID;//结点序号
bool OnTree;//是否属于最小生成树
};
struct LS {
int N1, N2; int V; bool OnTree;//OnTree用于判断此边是否在“树”上
LS(int n1, int n2, int v) {
N1 = n1; N2 = n2; V = v; OnTree = false;//N1,N2为边左右连接点,v是边的权值
}
};
Node A[] = { {1,false}, {2,false}, {3,false}, {4,false}, {5,false} };//点结构体数组
LS L[8] = { LS(1,2,1),LS(1,3,4) ,LS(2,3,2),
LS(2,5,2),LS(4,5,4),LS(3,4,6),LS(3,5,3),LS(1,4,8)};//边结构体数组
bool FindOne(LS L ,Node A[]) {//布尔类型
int m = 0;
for (int i = 0; i < 5; i++)
if (L.N1 == A[i].ID && A[i].OnTree) m++;
for (int i = 0; i < 5; i++)
if (L.N2 == A[i].ID && A[i].OnTree) m++;
return m ==1;//只有N1和N2的一个连接到了在“树”上的结点才为真
}
int main()
{
A[0].OnTree = true;
for (int i = 0; i < 5; i++) {
int p = 0;
for (int j = 0; j < 8; j++) {
if (FindOne(L[j], A)) {
p = j; break;
}
}
for (int i = 0; i < 8; i++) {
if (FindOne(L[i], A))
if (L[i].V < L[p].V) p = i;
}
L[p].OnTree = true;//选中的边设置为在“树”上
//将边的连接点放在“树”上
for (int i = 0; i < 5; i++) {
if (L[p].N1 == A[i].ID) A[i].OnTree = true;
if (L[p].N2 == A[i].ID) A[i].OnTree = true;
}
}
//输出最小生成树所有边
for (int i = 0; i < 8; i++) {
cout
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?