最小生成树【做题记录】c++(Prim,Kruskal)

目录

Prim算法求最小生成树

【算法思想】

【算法实现】

【数据结构设计】

【算法步骤】

【输入输出】

【代码示例】

Kruskal算法求最小生成树

【算法思想】

判断是否会产生回路的方法

【算法描述】

【图的存储结构】

【输入输出】

【代码示例】


Prim算法求最小生成树

【算法思想】

普里姆算法在找最小生成树时,将顶点分为两类,一类是在查找的过程中已经包含在树中的(设为 已选集合),剩下的是另一类(设为 待选集合)。

对于给定的连通网,起始状态全部顶点都归为 待选集合。在找最小生成树时,选定任意一个顶点作为起始点,并将之从 待选集合移至已选集合;然后找出 待选集合中到已选集合中的顶点之间权值最小的顶点,将之从 待选集合移至已选集合,如此重复,直到 待选集合中没有顶点为止。

所走过的顶点和边就是该连通图的最小生成树。

【算法实现】

输入:网(带权值的图)

输出:依次访问各个顶点 创建一个辅助数组,每次将当前已选类顶点到待选类顶点的距离填写到数组中。然后从中筛选出权值最小的边的邻接点。

在辅助数组中找出权值最小的边的数组下标,就可以间接找到此边的终点顶点。找到后lowcost标记为0。

【数据结构设计】

  1. 图的存储结构:由于在算法执行过程中,需要不断读取任意两个顶点之间边的权值,所以,图采用邻接矩阵存储。
  2. 候选最短边集:设置数组shortEdge[n]表示候选最短边集,数组元素包括adjvex和lowcost两个域,分别表示候选最短边的邻接点和权值。

【算法步骤】

  1. 初始化两个辅助数组lowcost和adjvex;
  2. 输出顶点u0,将顶点u0加入集合U中;
  3. 重复执行下列操作n-1次 3.1 在lowcost中选取最短边,取adjvex中对应的顶点序号k; 3.2 输出顶点k和对应的权值; 3.3 将顶点k加入集合U中; 3.4 调整数组lowcost和adjvex;

【输入输出】

第一行输入顶点的个数n

第二行输入n个顶点的值

第三行输入边的条数m

下面m行依次输入边的起点的值,终点的值和权值。

输出最小生成树,每行输出它的一条边。

【测试数据】

输入:

请输入顶点的个数:6

请依次输入6个顶点的值:

A B C D E F

请输入边的个数:9

请依次输入9个边的起点、终点和权值:

A C 46

A F 19

A B 34

B E 12

E F 26

D E 38

D F 25

C D 17

C F 25

输出:

最小生成树是:

(AF)19

(FC)25

(CD)17

(FE)26

(EB)12

【代码示例】

#include <iostream>
#include <limits.h>
#include <string> // 包含string以便处理顶点的字符表示
#define MAX_V_NUM 20using namespace std;struct closedge
{char adjvex; // 邻接点的字符表示int lowcost; // 到邻接点的最小权值
};closedge shortEdge[MAX_V_NUM]; // 存储候选最短边集class MGraph
{
private:char vertex[MAX_V_NUM]; // 图的顶点数组int arc[MAX_V_NUM][MAX_V_NUM]; // 图的邻接矩阵int vexNum, arcNum; // 顶点数和边数public:MGraph(); // 构造函数void Prim(int start); // 实现Prim算法
};MGraph::MGraph()
{cout << "请输入顶点的个数:";cin >> vexNum;cout << "请依次输入" << vexNum << "个顶点的值:" << endl;for (int i = 0; i < vexNum; i++){cin >> vertex[i];}cout << "请输入边的个数:";cin >> arcNum;char vi, vj;int w;// 初始化邻接矩阵for (int i = 0; i < vexNum; i++){for (int j = 0; j < vexNum; j++){if(i==j){arc[i][j] =0;}else{arc[i][j]=INT_MAX;}}}cout << "请依次输入" << arcNum << "个边的起点、终点和权值:" << endl;for (int i = 0; i < arcNum; i++){cin >> vi >> vj >> w;arc[vi - 'A'][vj - 'A'] = w;arc[vj - 'A'][vi - 'A'] = w; // 因为是无向图}// 假设从顶点0开始Prim算法Prim(0);
}void MGraph::Prim(int start)
{// 初始化shortEdge数组for (int i = 0; i < vexNum; i++){shortEdge[i].lowcost = arc[start][i];shortEdge[i].adjvex = start;}shortEdge[start].lowcost = 0;cout << "最小生成树是:" << endl;for (int i = 0; i < vexNum - 1; i++){int k = 0;for (int j = 0; j < vexNum; j++){if(shortEdge[j].lowcost!=0&&shortEdge[j].lowcost!=INT_MAX){k=j;break;}}for (int j = 0; j < vexNum; j++){if (shortEdge[j].lowcost!=0&&shortEdge[k].lowcost>shortEdge[j].lowcost){k =j;break;}}// 输出最小边cout << "(" << vertex[shortEdge[k].adjvex] << vertex[k] << ")" << shortEdge[k].lowcost << endl;// 将找到的最小边标记为0,表示已访问shortEdge[k].lowcost = 0;for (int j = 0; j < vexNum; j++){if (arc[k][j]!=0&&arc[k][j] < shortEdge[j].lowcost){shortEdge[j].lowcost = arc[k][j];shortEdge[j].adjvex = k;}}}
}int main()
{MGraph graph;return 0;
}

Kruskal算法求最小生成树

【算法思想】

将所有边按照权值的大小进行升序排序,然后从小到大一一判断,条件为:如果这个边不会与之前选择的所有边组成回路,就可以作为最小生成树的一部分;反之,舍去。直到具有 n 个顶点的连通网筛选出来 n-1 条边为止。筛选出来的边和所有的顶点构成此连通网的最小生成树。

注意:排序时如果两条边权值相同,起点下标较小边排在前面,保证测试数据的准确。

判断是否会产生回路的方法

1、标记法:在初始状态下给每个顶点赋予不同的标记,对于遍历过程的每条边,其都有两个顶点,判断这两个顶点的标记是否一致,如果一致,说明它们本身就处在一棵树中,如果继续连接就会产生回路;如果不一致,说明它们之间还没有任何关系,可以连接。 假设遍历到一条由顶点 A 和 B 构成的边,而顶点 A 和顶点 B 标记不同,此时不仅需要将顶点 A 的标记更新为顶点 B 的标记,还需要更改所有和顶点 A 标记相同的顶点的标记,全部改为顶点 B 的标记。

2、初始时每个顶点构成一棵生成树,然后每生长一次就将两棵树合并,到最后合并成一棵树。判断两个顶点是否在同一课树中,如果在同一棵树则产生了回路。

判断顶点是否在同一棵树中,可以从顶点出发,寻找树的根结点。如果两个顶点的根结点相同,则属于同一棵树。

【算法描述】

设无向连通网为G=(V, E),令G的最小生成树为T=(U, TE),其初态为U=V,TE={ },然后,按照边的权值由小到大的顺序,考察G的边集E中的各条边。

若被考察的边的两个顶点属于T的两个不同的连通分量,则将此边作为最小生成树的边加入到T中,同时把两个连通分量连接为一个连通分量;若被考察边的两个顶点属于同一个连通分量,则舍去此边,以免造成回路,如此下去,当T中的连通分量个数为1时,此连通分量便为G的一棵最小生成树。

【图的存储结构】

因为Kruskal算法是依次对图中的边进行操作,因此考虑用边集数组存储图中的边,为了提高查找速度,将边集数组按边上的权排序。

struct EdgeType

{

int from,to; //边依附的两个顶点

int weight; //边上的权值

};

【输入输出】

请输入图的顶点数和边数:6 9

请输入顶点的值:0 1 2 3 4 5

请输入边的起点终点和权值:

1 4 12

2 3 17

0 5 19

2 5 25

3 5 25

4 5 26

0 1 34

3 4 38

0 2 46

用Kruskal算法生成最小生成树的生成次序为:

(1,4)12

(2,3)17

(0,5)19

(2,5)25

(4,5)26

【代码示例】

#include <iostream>
#include <algorithm>
using namespace std;
const int MAX = 10000;
template <class T>
struct EdgeType
{T from, to;     //边依附的两个顶点int weight;      //边上的权值
};
template <class T>
class EdgeGraph
{
private:char* vertex;  //存放图顶点的数组EdgeType<char>* edge;      //存放边的数组int vertexNum, edgeNum;         //图的顶点数和边数
public:EdgeGraph(int vNum, int eNum);//构造函数void inputGraph();//输入图void Kruskal();int getIndex(char v){for (int i = 0; i < vertexNum; i++) {if (vertex[i] == v) {return i;}}return -1; // 如果找不到顶点,返回-1}void sorts();
private:T findRoot(int parent[], T v);//找到树的根
};
template <class T>
EdgeGraph<T>::EdgeGraph(int vNum, int eNum)
{vertexNum = vNum;edgeNum = eNum;vertex = new char[vertexNum];edge = new EdgeType<T>[edgeNum];char v;T f, t;int w;cout << "请输入顶点的值:";for (int i = 0; i < vertexNum; i++){cin >> v;vertex[i] = v;}cout << "请输入边的起点终点和权值:\n";for (int i = 0; i < edgeNum; i++){cin >> f >> t >> w;edge[i].from = f;edge[i].to = t;edge[i].weight = w;}sorts();}
//对weight排序
// 最开始写的冒泡排序,但是有问题
// 冒泡排序不是对边的数组edge中的元素进行排序,而是对数组的索引进行排序。这意味着数组edge中的元素并没有按照权值从小到大进行排序,而是数组的索引被重新排列,使得具有较小权值的边的索引在前。这并不是Kruskal算法所需要的。
// 需要对边的数组edge中的EdgeType对象按照权值进行排序,而不是对索引进行排序。
// 修正后,使用了C++11的lambda表达式来定义排序准则,即按照weight成员进行比较。这样,edge数组中的EdgeType对象将根据它们的权值进行排序,而不是它们的索引。
template <class T>
void EdgeGraph<T>::sorts()
{// 使用标准库的sort函数对边按照权值进行排序sort(edge, edge + edgeNum, [](const EdgeType<T>& a, const EdgeType<T>& b) {return a.weight < b.weight;});}
template <class T>
void EdgeGraph<T>::Kruskal()
{int parent[MAX] = { 0 };T vex1, vex2;sorts();for (int i = 0; i < vertexNum; i++){parent[i] = -1;}for (int num = 0, i = 0; i < edgeNum; i++){//找到所在生成树的根节点int idx1 = getIndex(edge[i].from);int idx2 = getIndex(edge[i].to);vex1 = findRoot(parent, idx1);vex2 = findRoot(parent, idx2);if (vex1 != vex2) //如果两个根节点不同,不会构成环{cout << "(" << edge[i].from << "," << edge[i].to << ")" << edge[i].weight << endl;parent[vex2] = vex1;//合并生成树num++;if (num == vertexNum - 1)  //循环了顶点数-1次,提前返回return;}}
}
//求根节点
template <class T>
T EdgeGraph<T>::findRoot(int parent[], T v)
{T t = v;while (parent[t] > -1){t = parent[t];}return t;
}
int main()
{int vNum, eNum;cout << "请输入图的顶点数和边数:";cin >> vNum >> eNum;EdgeGraph<char> edgegraph(vNum, eNum);cout << "用Kruskal算法生成最小生成树的生成次序为:\n";edgegraph.Kruskal();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/17509.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AirBnb架构简史

2007 年&#xff0c;布莱恩切斯基 (Brian Chesky) 和乔加比亚 (Joe Gabbia) 搬到了旧金山。他们一边想为自己的创业想法筹集资金&#xff0c;一边又需要支付房租。 碰巧的是&#xff0c;当时城里正要举行一个设计会议&#xff0c;这意味着很多设计师都会寻找住处。他们想出了在…

Java 五种内部类演示及底层原理详解

内部类 什么是内部类 在A类的内部定义B类&#xff0c;B类就被称为内部类 发动机类单独存在没有意义 发动机为独立个体 可以在外部其他类里创建内部类的对象去调用方法 类的五大成员 属性 方法 构造方法 代码块 内部类 内部类的访问特点 内部类可以直接访问外部类的成员&a…

AI手语研究数据集;视频转视频翻译和风格化功能如黏土动画;AI检测猫咪行为;开放源码的AI驱动搜索引擎Perplexica

✨ 1: Prompt2Sign 多语言手语数据集&#xff0c;便捷高效用于手语研究。 Prompt2Sign 是一个全面的多语言手语数据集&#xff0c;旨在通过工具自动获取和处理网络上的手语视频。该数据集具有高效、轻量的特点&#xff0c;旨在减少先前手语数据集的不足之处。该数据集目前包含…

AI架构设计7:TGI

这个专栏主要关注围绕着AI运用于实际的业务场景所需的系统架构设计。整体基于云原生技术&#xff0c;结合开源领域的LLMOps或者MLOps技术&#xff0c;充分运用低代码构建高性能、高效率和敏捷响应的AI中台。该专栏需要具备一定的计算机基础。 若在某个环节出现卡点&#xff0c;…

员工管理和激励怎么做?试试场景化激励解决方案!

截止到2020年底&#xff0c;中国企业主体数量达3858.3万&#xff0c;同比增速达11.1%。如何留住人才、激励人才以强化人才与企业“黏性”&#xff0c;最大化提升员工的忠诚度与敬业度&#xff0c;成为企业未来人才发展战略的主要方向之一。 一、传统激励方式存在哪些不足 传统的…

香橙派 AIpro初体验

香橙派&#xff08;Orange Pi&#xff09;AI Pro开发板是一款高性能的AI开发板&#xff0c;由香橙派联合华为精心打造。香橙派&#xff08;Orange Pi&#xff09;&#xff0c;作为深圳市迅龙软件有限公司倾力打造的开源产品品牌&#xff0c;致力于向全球个人及企业用户提供卓越…

设计软件有哪些?建模和造型工具篇(3),渲染100邀请码1a12

这次我们接着介绍建模工具。 1、FloorGenerator FloorGenerator是由CG-Source开发的3ds Max插件&#xff0c;用于快速创建各种类型的地板和瓷砖。该插件提供了丰富的地板样式和布局选项&#xff0c;用户可以根据需要轻松创建木质地板、石板地板、砖瓦地板等不同风格的地面。F…

人生二选一:央企就业?美国做博士后?—请看她的抉择

一位30岁的女博士&#xff0c;收到国内央企和德国、美国的博士后邀请函&#xff0c;她该如何选择&#xff1f;知识人网小编推荐这篇文章&#xff0c;为大家解开谜题的同时&#xff0c;也给有同样纠结的学者提供一些启迪。 去年12月底的一个晚上&#xff0c;我收到美国一所高校发…

100个 Unity小游戏系列六 -Unity 抽奖游戏专题四 翻卡游戏

一、演示效果 二、知识点讲解 2.1 布局 void CreateItems(){reward_data_list reward_data_list ?? new List<RewardData>();reward_data_list.Clear();for (int i 0; i < ItemCount; i){GameObject item;if (i 1 < itemParent.childCount){item itemParent…

Python解析网页-requests_html

目录 1、什么是requests_html 2、安装与配置 3、快速入门 4、图片下载 1.什么是requests_html requests_html是一个Python库&#xff0c;用于从Web页面中提取数据。 它提供了对HTML内容的解析和处理功能&#xff0c;使您可以轻松地从网页中提取文本、链接、图像和其他元素。…

嵌入式UI开发-lvgl+wsl2+vscode系列:4、动画(Animations)

文章目录 一、前言二、动画示例1、示例1&#xff08;基础按钮label的组合动画&#xff09;2、示例2&#xff08;回放效果动画&#xff09;3、示例3&#xff08;贝塞尔曲线3动画&#xff09;4、示例4&#xff08;动画时间轴&#xff09; 三、最后 一、前言 接下来我们进行动画的…

Golang | Leetcode Golang题解之第101题对称二叉树

题目&#xff1a; 题解&#xff1a; func isSymmetric(root *TreeNode) bool {u, v : root, rootq : []*TreeNode{}q append(q, u)q append(q, v)for len(q) > 0 {u, v q[0], q[1]q q[2:]if u nil && v nil {continue}if u nil || v nil {return false}if …

JWT使用方法

目录 基础概念 依赖 生成令牌 工具类 控制层 解析令牌 工具类 网关过滤器 效果 基础概念 Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准&#xff08;(RFC 7519).该token被设计为紧凑且安全的&#xff0c;特别适用于分布式站点…

深入解读力扣154题:寻找旋转排序数组中的最小值 II(多种方法及详细ASCII图解)

❤️❤️❤️ 欢迎来到我的博客。希望您能在这里找到既有价值又有趣的内容&#xff0c;和我一起探索、学习和成长。欢迎评论区畅所欲言、享受知识的乐趣&#xff01; 推荐&#xff1a;数据分析螺丝钉的首页 格物致知 终身学习 期待您的关注 导航&#xff1a; LeetCode解锁100…

弘君资本:沪指跌0.46%,电力板块逆市爆发,半导体板块强势

28日&#xff0c;沪指早盘窄幅震动&#xff0c;午后回落走低&#xff1b;深证成指、创业板指大幅下探&#xff1b;两市成交额小幅萎缩。 截至收盘&#xff0c;沪指跌0.46%报3109.57点&#xff0c;深证成指跌1.23%报9391.05点&#xff0c;创业板指跌1.35%报1806.25点&#xff0c…

Windows 11 HBuilder X的安装和环境搭建教程

文章目录 目录 文章目录 安装流程 小结 概要安装流程技术细节小结 概要 HBuilder X是一个由DCloud推出的集成开发环境&#xff08;IDE&#xff09;&#xff0c;主要用于构建基于HTML、CSS和JavaScript的跨平台应用程序&#xff0c;如微信小程序、App、H5等。它提供了丰富的功能…

【Unity】颜色混合计算

在图形渲染中&#xff0c;颜色混合&#xff08;Color Blending&#xff09;是指将多个颜色值组合在一起以生成最终显示的颜色。颜色混合技术广泛用于处理半透明效果、光照效果和后期处理效果。以下是一些常见的颜色混合模式&#xff1a; 1. 正常混合&#xff08;Normal Blendi…

简单四步完成基于云服务器ARL资产侦察灯塔系统搭建

简单四步完成基于云服务器ARL资产侦察灯塔系统搭建及使用 前言 官网介绍&#xff1a;ARL全称-Asset Reconnaissance Lighthouse&#xff0c;中文含义&#xff1a;资产侦察灯塔系统。 旨在快速侦察与目标关联的互联网资产&#xff0c;构建基础资产信息库。 协助甲方安全团队或…

DragonKnight CTF复现(一)

这次的 re 题也是挺难的&#xff0c;按 wp 来学习一波 elec_go 下次遇到这种给了很多东西&#xff0c;又不知道怎么分析的&#xff0c;先百度一下。 Electron程序逆向&#xff08;asar归档解包&#xff09;_asar解包-CSDN博客 [原创] electron开发、打包与逆向分析-软件逆向-…

AutoDL搭建 ChatGLM3

租用新实例 这里选择的西北 B 区、RTX 409024GB 创建虚拟环境并激活 # 安装虚拟环境至数据盘 conda create --prefix /root/autodl-tmp/envs/chatglm3-demo python3.10# 激活虚拟环境 conda activate /root/autodl-tmp/envs/chatglm3-demo拉取ChatGLM3仓库代码 # 开启学术…