构建最小生成树普利姆算法和克鲁斯卡尔算法(P&C)
普利姆算法和克鲁斯卡尔算法的思想可以归为贪心算法即:以每次局部最优解最后得全局最优解。
相同点:
- 都适用于无向图。
- 都是用了贪心思想
不同点:
- 普利姆算法是顶点优先,克鲁斯卡尔是边优先。二者应对不同情况效率不同。
- 普利姆算法平均时间复杂度为O(n^2),是顶点数的平方。
- 克鲁斯卡尔算法平均时间复杂度取决于选用的排序算法,是和边数相关的。
普利姆算法分析如下:
// 构建lowcost
for (int i =0; i < g.n;i++){
lowcost[i] = g.edges[v0][i];
}
for (int k = 0; k < g.n; k++) { // 用邻接矩阵存储无向图, 维护一个 lowcost[],一个vset[] vset数组用于记录已经选择的顶点 for (int i = 0; i < g.n; i++){ //找到lowcost中 没有被选择过的最小值 if (vset[i] == 0 && lowcast[i] < min){ min = lowcost[i]; min_index = i; } } // 将 min_index 点并入 vset[min_index] = 1; //维护lowcost数组 for (int j = 0; j < g.n; j++){ // min_index 点位新加入的点, 只要该点到其他点的距离小于 lowcost[j] 就覆盖,由此lowcost[]一直都是子树到各点的最小距离 if (vset[j] == 0 && g.edges[min_index][j] < lowcost[j] ){ lowcost[j] =g.edges[min_index][j]; } } }
克鲁斯卡尔算法运用并查集工具判断是否形成回路。 并查集本质是在一个数组存了一棵二叉树,通过查找不同子节点的根节点判断是否会形成回路。
//并查集工具 public int getRoot(int a){ // v[] 存放二叉树 while(a != v[a]){ a = v[a]; } return a; } //定义边的类 包含边的左节点有节点和边的长度 class Edge{ int leftNode; int rightNode; int length } //初始化并查集工具用到的数组 for (int i = 0; i < g.n; i++){ v[i] = i; } // 将边按照从小到大顺序排列 sort(Edge[] edges, g.E); for (int i = 0; i < g.e; i++){ // 获取左右两个节点的根节点 leftNode = getRoot(edges[i].leftNode); rightNode = getRoot(edges[i].rightNode); if (leftNode != rightNode){ // 说明是两棵独立的子树 可以合并 v[leftNode] = rightNode; } }
欺骗自己最简单,欺骗自己最困难。
安慰自己最简单,安慰自己最困难。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】