前言

这个和前面一节有关系,是这样子的,前面是用顶点作为参照条件,这个是用边作为参照条件。

正文

图解如下:

每次选择最小的边。

但是会遇到一个小问题,就是会构成回路。

比如说第四步中,最小边是CE,但是没有选择CE,因为CE会形成回路。

那么如何判断是否有回路呢?

判断两个点的终点,是否一致。

这个是怎么来的呢?为什么判断终点是否一致就可以判断有回路呢?

是这样子的,如何两个点可以共同到达任何一个点,那么他们之间一定是通的,这一点是肯定的,如果他们本来就是通的,再在他们之间加一条那么肯定回路的。

那么为什么选择终点呢?是这样子的,假如他们之间选来不相通,他们肯定在两条路上。

假设选了cd和ef这两条路。那么他们这两条路的终点分别是d(c->d)和f(e->f),他们的终点不同,那么他们没有在一条路上,所以把c->d的终点d的终点设置为e->另一条路的终点也就是f,连接后所有节点都有公共的终点,那么终点就可以作为判断依据,这样就不用去遍历了。

代码如下:

private static int INF = int.MaxValue;

static void Main(string[] args)
{
char[] vertexs = { 'A', 'B', 'C', 'D', 'E', 'F', 'G' };
//克鲁斯卡尔算法的邻接矩阵
int[,] matrix = {
/*A*//*B*//*C*//*D*//*E*//*F*//*G*/
/*A*/ { 0, 12, INF, INF, INF, 16, 14},
/*B*/ { 12, 0, 10, INF, INF, 7, INF
},
/*C*/ { INF, 10, 0, 3, 5, 6, INF},
/*D*/ { INF, INF, 3, 0, 4, INF, INF},
/*E*/ { INF, INF, 5, 4, 0, 2, 8},
/*F*/ { 16, 7, 6, INF, 2, 0, 9},
/*G*/ { 14, INF, INF, INF, 8, 9, 0}};
KruskaCase kruskaCase = new KruskaCase(vertexs,matrix);
kruskaCase.kruskal();
Console.ReadKey();
}
} public class KruskaCase
{
private int edgeNum;//边的个数 private char[] vertexs;//顶点数组 private int[,] matrix;//邻接矩阵 private static int INF = int.MaxValue; public KruskaCase(char[] vertexs, int[,] matrix)
{
int vlen = vertexs.Length;
//初始化顶点,避免污染数据
this.vertexs = new char[vlen];
for (int i=0;i<vlen;i++)
{
this.vertexs[i] = vertexs[i];
} //初始化边, 避免污染数据
this.matrix = new int[vlen,vlen];
for (int i = 0; i < vlen; i++)
{
for (int j = 0; j < vlen; j++)
{
this.matrix[i,j] = matrix[i,j];
}
}
for (int i = 0; i < vlen; i++)
{
for (int j = i+1; j < vlen; j++)
{
if (matrix[i, j] != INF)
{
edgeNum++;
}
}
}
} public void kruskal()
{
//表示第几条边加入最后的结果
int index = 0;
//记录每个顶点的终点
int[] ends = new int[edgeNum];
//最后边的个数肯定是节点数量-1
EData[] result = new EData[vertexs.Length-1];
EData[] edges = getEData();
sortEData(edges);
for (int i=0;i<edgeNum;i++)
{
var start = getPosition(edges[i].start);
var end = getPosition(edges[i].end);
int startEndPoint = getEnd(ends,start);
int endEndPoint = getEnd(ends, end);
if (startEndPoint != endEndPoint)
{
ends[startEndPoint] = endEndPoint;
result[index++] = edges[i];
}
}
Console.WriteLine("最小生成树为:");
for (int i=0;i<result.Length;i++)
{
Console.WriteLine(result[i]);
}
} private int getPosition(char ch)
{
for (int i = 0; i < vertexs.Length; i++)
{
if (vertexs[i] == ch)
{
return i;
}
}
return -1;
} private int getEnd(int[] ends, int i)
{ // i = 4 [0,0,0,0,5,0,0,0,0,0,0,0]
while (ends[i] != 0)
{
i = ends[i];
}
return i;
} /// <summary>
/// 对边数组进行排序
/// </summary>
/// <param name="edges">需要排序的边数组</param>
private void sortEData(EData[] edges)
{
for (int i = 0; i < edges.Length - 1; i++)
{
for (int j = 0; j < edges.Length - 1 - i; j++)
{
if (edges[j].weight > edges[j + 1].weight)
{//交换
EData tmp = edges[j];
edges[j] = edges[j + 1];
edges[j + 1] = tmp;
}
}
}
}

结果:

重新整理数据结构与算法(c#)——算法套路k克鲁斯算法[三十]的更多相关文章

  1. 数据结构与算法系列研究五——树、二叉树、三叉树、平衡排序二叉树AVL

    树.二叉树.三叉树.平衡排序二叉树AVL 一.树的定义 树是计算机算法最重要的非线性结构.树中每个数据元素至多有一个直接前驱,但可以有多个直接后继.树是一种以分支关系定义的层次结构.    a.树是n ...

  2. 数据结构- 串的模式匹配算法:BF和 KMP算法

      数据结构- 串的模式匹配算法:BF和 KMP算法  Brute-Force算法的思想 1.BF(Brute-Force)算法 Brute-Force算法的基本思想是: 1) 从目标串s 的第一个字 ...

  3. C基础 算法实现层面套路

    引言 - 从实践狗讲起 理论到实践(有了算法到实现) 中间有很多过程. 算法方面本人啥也不懂, 只能说说实现方面. 例如下面 一个普通的插入排序. // // 插入排序默认从大到小 // extern ...

  4. C语言二级选择题考点汇总-数据结构与算法-【考点一】 什么是算法

      1.算法及其基本特征 算法是指对方案的准确描述,是解决问题的执行步骤. 算法不等于数学上的计算方法,也不等于程序.程序是算法的载体. 算法的基本特征如下: (1)可行性:步骤可实现,执行结果可达到 ...

  5. 深入浅出数据结构C语言版(2)——简要讨论算法的时间复杂度

    所谓算法的"时间复杂度",你可以将其理解为算法"要花费的时间量".比如说,让你用抹布(看成算法吧--)将家里完完全全打扫一遍大概要5个小时,那么你用抹布打扫家里 ...

  6. 【算法总结】强化学习部分基础算法总结(Q-learning DQN PG AC DDPG TD3)

    总结回顾一下近期学习的RL算法,并给部分实现算法整理了流程图.贴了代码. 1. value-based 基于价值的算法 基于价值算法是通过对agent所属的environment的状态或者状态动作对进 ...

  7. 基于改进人工蜂群算法的K均值聚类算法(附MATLAB版源代码)

    其实一直以来也没有准备在园子里发这样的文章,相对来说,算法改进放在园子里还是会稍稍显得格格不入.但是最近邮箱收到的几封邮件让我觉得有必要通过我的博客把过去做过的东西分享出去更给更多需要的人.从论文刊登 ...

  8. 推荐一个算法编程学习中文社区-51NOD【算法分级,支持多语言,可在线编译】

    最近偶尔发现一个算法编程学习的论坛,刚开始有点好奇,也只是注册了一下.最近有时间好好研究了一下,的确非常赞,所以推荐给大家.功能和介绍看下面介绍吧.首页的标题很给劲,很纯粹的Coding社区....虽 ...

  9. 《算法导论》读书笔记之图论算法—Dijkstra 算法求最短路径

    自从打ACM以来也算是用Dijkstra算法来求最短路径了好久,现在就写一篇博客来介绍一下这个算法吧 :) Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的 ...

  10. K Nearest Neighbor 算法

    文章出处:http://coolshell.cn/articles/8052.html K Nearest Neighbor算法又叫KNN算法,这个算法是机器学习里面一个比较经典的算法, 总体来说KN ...

随机推荐

  1. 【Flink入门修炼】2-2 Flink State 状态

    什么是状态?状态有什么作用? 如果你来设计,对于一个流式服务,如何根据不断输入的数据计算呢? 又如何做故障恢复呢? 一.为什么要管理状态 流计算不像批计算,数据是持续流入的,而不是一个确定的数据集.在 ...

  2. 【拉格朗日优化dp】P4365 [九省联考 2018] 秘密袭击 coat

    [拉格朗日优化dp]P4365 [九省联考 2018] 秘密袭击 coat 题目简述 求树上所有连通块第 \(k\) 大点权(不足 \(k\) 点记为 \(0\))的和. \(1\leq k\leq ...

  3. coding 的pages 静态要六分钱一个月,我也是醉了。

    前言 前几天,收到个短信,说coding 竟然免费开放 动态pages,我这心说 NB啊,这咱得蹭上一波热度. github 总是打不开 gitee 每次pages都要手动点下发布,而且是静态的. c ...

  4. DatePicker 日期选择器 split-panels 数组的时候,清空这个费劲啊,最后走的后门

    这里的核心问题就是验证的时候value值不对,总是初始化的值,不论怎么设置,开始觉得是数组指针的问题,最后也不行,null也不行,组件的props都已经是null了,验证就是这么神奇,最后把this放 ...

  5. pod探针的三种类型及三种检测方式

    Pod探针是Kubernetes中的一种机制,用于检测Pod中的容器是否正常运行.它主要有三种类型:存活探针(LivenessProbe).就绪探针(ReadinessProbe)和启动探针(Star ...

  6. 基于英特尔® Gaudi® 2 AI 加速器的文本生成流水线

    随着生成式人工智能 (Generative AI,GenAI) 革命的全面推进,使用 Llama 2 等开源 transformer 模型生成文本已成为新风尚.人工智能爱好者及开发人员正在寻求利用此类 ...

  7. MYSQL 是如何保证binlog 和redo log同时提交的?

    MYSQL 一个事务在提交的时候能够保证binlog和redo log是同时提交的,并且能在宕机恢复后保持binlog 和redo log的一致性. 先来看看什么是redo log 和binlog,以 ...

  8. Window资源管理器插件增强,可显示Android的apk图标

    身为Android开发人员,更习惯看到apk的图标,但是windows系统默认不支持显示pak图标,找了会插件,终于是找到了 安装 下载软件压缩包,下载地址:https://stars-one.lan ...

  9. AOSP12内置三方apk

    一.准备工作 1.可正常编译的Android12的源码 2.三方apk:我这里选择的是一个ChatGPT的apk(下载地址:https://aigcfun.com/app-download),选择这个 ...

  10. TCP可靠传输的保证

    我们知道传输层提供最主要的两种协议,TCP和UDP,其中TCP是保证可靠传输,为什么他要保证可靠传输呢,IP说:当然是我不能,我只提供尽力而为的服务,不保证你能不能交付,不保证能不能正确的交付,不保证 ...