数据结构-最小生成树

一.最小生成树的定义

从V个顶点的图里生成的一颗树,这颗树有V个顶点是连通的,有V-1条边,并且边的权值和是最小的,而且不能有回路

二.Prim算法

Prim算法又叫加点法,算法比较适合稠密图

每次把边权最小的顶点加入到树中,最小生成树的不是唯一的,但最小边权是唯一的

Prim算法和 Dijkstra

核心代码

/*更新顶点距离树的距离*/for(W=0;W<Graph->Nv;W++)/*对图中顶点每个顶点W*/if (dist[W] != 0 && Graph->G[V][W] < INFINITY) {/*若W是V的邻接点并且未被收录*/if (Graph->G[V][W] < dist[W]) {/*若收录V使得dist[W]变小*/dist[W] = Graph->G[V][W];parent[W] = V;/*更新树*/}}

dist每个顶点的变化

dist[i]=0表示已经加入到最小生成树,距离树的距离是0,65535表示和树没有连接

全部代码

#include<iostream>
using namespace std;#define INFINITY 65535
#define MaxvertexNum 100
typedef int Vertex;
typedef int WeightType;
Vertex Visited[MaxvertexNum];
Vertex parent[MaxvertexNum];/*边的定义*/
typedef struct ENode* PtrToENode;
struct ENode
{Vertex V1, V2;WeightType Weight;/*边权*/
};
typedef PtrToENode Edge;typedef struct AdjVNode* PtrToAdjVNode;
struct AdjVNode
{Vertex Adjx;/*邻接点下标*/WeightType Weight;/*边权*/PtrToAdjVNode Next;/*指向下一个邻接点*/
};
typedef struct Vnode {PtrToAdjVNode FirstEdge;/*边表头结点*/}AdjList[MaxvertexNum];/*邻接表*/
typedef struct LGNode* PtrToLGNode;
typedef struct LGNode {int Nv;/*顶点数*/int Ne;/*边数*/AdjList G;
};
typedef PtrToLGNode LGraph;/*邻接表方式存储*/
/*图的定义*/
typedef struct GNode* PtrToGNode;
struct GNode {int Nv;/*顶点数*/int Ne;/*边数*/WeightType G[MaxvertexNum][MaxvertexNum];
};
typedef PtrToGNode MGraph;
LGraph Create(int Vertexnum) {Vertex V;LGraph Graph = new LGNode();Graph->Nv = Vertexnum;Graph->Ne = 0;for (V = 0; V < Graph->Nv; V++) {Graph->G[V].FirstEdge = NULL;}return Graph;
}
void Insert(LGraph Gaph, Edge E) {PtrToAdjVNode NewNode;NewNode = new AdjVNode();NewNode->Adjx = E->V2;NewNode->Next = Gaph->G[E->V1].FirstEdge;Gaph->G[E->V1].FirstEdge = NewNode;NewNode = new AdjVNode();NewNode->Adjx = E->V1;NewNode->Next = Gaph->G[E->V2].FirstEdge;Gaph->G[E->V2].FirstEdge = NewNode;
}
//插入边
void InsertEdge(MGraph Graph, Edge E) {Graph->G[E->V1][E->V2] = E->Weight;Graph->G[E->V2][E->V1] = E->Weight;
}
MGraph CreateGraph(int VertexNum) {MGraph Graph = new GNode();Graph->Nv = VertexNum;Graph->Ne = 0;for (int V = 0; V < Graph->Nv; V++)for (int W = 0; W < Graph->Nv; W++)Graph->G[V][W] = INFINITY;return Graph;
}
MGraph BuildGraph() {MGraph Graph;Edge E;int Nv;/*顶点*/cin >> Nv;Graph = CreateGraph(Nv);cin >> Graph->Ne;if (Graph->Ne != 0) {for (int i = 0; i < Graph->Ne; i++) {E = new ENode();cin >> E->V1 >> E->V2 >> E->Weight;InsertEdge(Graph, E);}}return Graph;}
Vertex FindMinDist(MGraph Graph, WeightType dist[]) {/*返回未被收录顶点中dist最小者*/Vertex MinV, V;WeightType MinDist = INFINITY;for (V = 0; V < Graph->Nv; V++) {if (dist[V] != 0 && dist[V] < MinDist) {MinDist = dist[V];MinV = V;}}if (MinDist < INFINITY)return MinV;else return 0;
}
int Prim(MGraph Graph, LGraph& MST) {/*将最小生成树保存为邻接表存储的图MST,返回最小权重和*//*dist表示顶点到树的距离*/ /*权重*/WeightType dist[MaxvertexNum], Tota1Weight;Vertex V, W;int VCount;Edge E;/*初始化。默认初始点下标是0*/for (V = 0; V < Graph->Nv; V++) {/*这里假设V到W没有直接边,则Graph->G[V][W]定义INF*/dist[V] = Graph->G[0][V];parent[V] = 0;/*暂且定义所以顶点的父亲结点都是初始化0*/}Tota1Weight = 0;/*初始化权重*/VCount = 0;/*初始化收入的顶点个数*//*创建一个没有边的邻接表*/MST = Create(Graph->Nv);E = new ENode();/*将初始点0收录MST*/dist[0] = 0;VCount++;parent[0] = -1;/*当前树根是0*/while (1) {V = FindMinDist(Graph,dist);/*V=未被收录顶点中dist最小者*/if (V == 0)/*若这样的V不存在*/break;/*算法结束*/E->V1 = parent[V];/*父亲顶点*/E->V2 = V;/*子结点*/E->Weight = dist[V];Insert(MST, E);Tota1Weight += dist[V];dist[V] = 0;/*将顶点收录集合树*/VCount++;/*更新顶点距离树的距离*/for(W=0;W<Graph->Nv;W++)/*对图中顶点每个顶点W*/if (dist[W] != 0 && Graph->G[V][W] < INFINITY) {/*若W是V的邻接点并且未被收录*/if (Graph->G[V][W] < dist[W]) {/*若收录V使得dist[W]变小*/dist[W] = Graph->G[V][W];parent[W] = V;/*更新树*/}}}/*while结束*/if (VCount < Graph->Nv)/* MST中收的顶点不到|V|个*/Tota1Weight = 0;return Tota1Weight;
}void DFS(LGraph Graph, Vertex V) {cout << V << endl;PtrToAdjVNode W;Visited[V] = 1;for (W = Graph->G[V].FirstEdge; W; W = W->Next) {if (Visited[W->Adjx] == 0) {DFS(Graph, W->Adjx);}}}
int main()
{MGraph G = BuildGraph();LGraph Gr =NULL;Prim(G,Gr);DFS(Gr, 0);for (int i = 0; i < G->Nv; i++)cout << i<<" " << parent[i] << endl;return 0;
}
/*
*
6 10
0 1 6
0 2 1
0 3 5
1 4 3
3 2 4
1 2 5
4 2 6
3 5 2
5 2 4
4 5 6
*/

三.Kruskal算法

Kruskal算法又叫加边法,算法比较适合稀疏图

代码

#include<iostream>
using namespace std;
#define MaxVertexNum 100
typedef int Vertex;
typedef int WeightType;
typedef Vertex ElementType;/*默认元素可以用非负正数表示*/
typedef Vertex SetName;/*默认用根结点的下标作为集合名称*/
typedef ElementType SetType[MaxVertexNum];/*假设集合元素下标从0开始*/
Vertex Visited[MaxVertexNum];
typedef struct ENode* PtrToENode;struct ENode
{Vertex V1, V2;WeightType Weight;
};
typedef PtrToENode Edge;typedef struct AdjVNode* PtrToAdjVNode;struct AdjVNode
{Vertex Adjx;/*邻接点下标 */WeightType Weight;/*边权重*/PtrToAdjVNode Next;/*向下下一个邻接点*/
};
typedef struct Vnode {PtrToAdjVNode FirstEdge;/* 边表头指针*/}AdjList[MaxVertexNum];
typedef struct GNode* PtrToGNode;
typedef struct GNode {int Nv;/*顶点个数*/int Ne;/*边的个数*/AdjList G;
};
typedef PtrToGNode LGraph;/*邻接表方式存储*/void InsertEdge(LGraph Graph, Edge E);
LGraph CreateGraph(int Vertexnum) {Vertex W, V;LGraph Graph = new GNode();Graph->Nv = Vertexnum;Graph->Ne = 0;for (V = 0; V < Graph->Nv; V++) {Graph->G[V].FirstEdge = NULL;}return Graph;
}
LGraph BuildGraph() {int Nv;Vertex V;Edge E;cin >> Nv;LGraph Graph =  CreateGraph(Nv);cin >> Graph->Ne;if (Graph->Ne != 0) {for (V = 0; V < Graph->Ne; V++) {E = new ENode();cin >> E->V1 >> E->V2 >> E->Weight;InsertEdge(Graph, E);}}return Graph;
}
void InsertEdge(LGraph Graph, Edge E) {PtrToAdjVNode W;W = new AdjVNode();W->Adjx = E->V2;W->Weight = E->Weight;W->Next = Graph->G[E->V1].FirstEdge;Graph->G[E->V1].FirstEdge = W;W = new AdjVNode();W->Adjx = E->V1;W->Weight = E->Weight;W->Next = Graph->G[E->V2].FirstEdge;Graph->G[E->V2].FirstEdge = W;}
void InitializeVSet(SetType S, int N) {/*初始化并查集*/ElementType X;for (X = 0; X < N; X++)S[X] = -1;
}
void Union(SetType S, SetName Root1, SetName Root2) {/*这里默认Root1和Root2是不同集合的根节点*/if (S[Root2] < S[Root1]) { /*如果集合2比较大*/S[Root2] += S[Root1];/*集合1并入集合2*/S[Root1] = Root2;}else {S[Root1] += S[Root2];/*集合2并入集合1*/S[Root2] = Root1;}
}
SetName Find(SetType S, ElementType X) {/*默认集合元素全部初始化为-1*/if (S[X] < 0)/*找到集合的根*/return X;elsereturn S[X] = Find(S, S[X]);/*路径压缩*/
}
bool ChekCycle(SetType VSet, Vertex V1, Vertex V2) {/*检查连接V1和V2的边是否在现有的最小生成树子集中构成回来*/Vertex Root1, Root2;Root1 = Find(VSet, V1);/*得到V1所属的连通集名称*/Root2 = Find(VSet, V2);/*得到V2所属的连通集名称*/if (Root1 == Root2)/*若V1和V2已经连通,则该边不能要*/return false;else {/*否则改边可以被收集同时将V1和V2并入同一连通集*/Union(VSet, Root1, Root2);return true;}
}/*边的最小堆*/
/*将N个元素的边数组以ESet[p]为根的子堆调整为关于Weight的最小堆*/
void PerDown(Edge ESet,int p,int N) {//直接用数组,不用heap结构了int Parent, Child;struct ENode X;X = ESet[p];for (Parent = p; (Parent * 2 + 1) < N; Parent = Child) {Child = Parent * 2 + 1;if ((Child != N - 1) && (ESet[Child].Weight > ESet[Child + 1].Weight))Child++;if (X.Weight <= ESet[Child].Weight)break;else/*下滤*/ESet[Parent] = ESet[Child];}ESet[Parent] = X;
}
/*将图的边存入数组ESet,并且初始化为最下堆*/
void InitializeESet(LGraph Graph, Edge ESet) {Vertex V;PtrToAdjVNode W;int ECount;/*将图的边存入数组ESet*/ECount = 0;for(V=0;V<Graph->Nv;V++)for(W=Graph->G[V].FirstEdge;W;W=W->Next)if (V < W->Adjx) {/*避免重复录入无向图的边 只收V1<V2的边*/ESet[ECount].V1 = V;ESet[ECount].V2 = W->Adjx;ESet[ECount++].Weight = W->Weight;}/*初始化最小堆*/for (ECount = Graph->Ne / 2; ECount >= 0; ECount--)PerDown(ESet, ECount, Graph->Ne);
}
void Swap(struct ENode* a, struct ENode* b) {struct ENode* c;c = a;a = b;b = c;
}
/*给定当前堆的大小CurrentSize,将当前最小边位置弹出并调整*/
int GetEdeg(Edge ESet, int CurrentSize) {Swap(&ESet[0], &ESet[CurrentSize - 1]);/*将最小边与当前堆的最后一个位置的边交换*/PerDown(ESet, 0, CurrentSize - 1);/*将剩下的边继续调整成最小堆*/return CurrentSize - 1;/*返回最小边所在位置*/
}
int Kruskal(LGraph Graph, LGraph& MST) {WeightType TotalWeight;int ECount, NextEdge;SetType VSet;/*顶点数组*/Edge ESet;//边数组InitializeVSet(VSet, Graph->Nv);/*初始化顶点并查集*/ESet = (Edge)malloc(sizeof(struct ENode) * Graph->Ne);//ESet = new ENode[Graph->Ne];InitializeESet(Graph, ESet);/*初始化边的最小堆*///创建MSV图MST = CreateGraph(Graph->Nv);TotalWeight = 0;ECount = 0;NextEdge = Graph->Ne;//原始边集合的规模while (ECount < Graph->Nv - 1) {//当收集的边下与顶点数-1时NextEdge = GetEdeg(ESet, NextEdge);if (NextEdge < 0)//边收集已经空break;if (ChekCycle(VSet, ESet[NextEdge].V1, ESet[NextEdge].V2))//如果不构成回来{// 插入边到MST中InsertEdge(MST, ESet + NextEdge);//相当于&ESet[NextEdge] ;TotalWeight += ESet[NextEdge].Weight;ECount++;}}//while循环结束 if (ECount < Graph->Nv - 1)TotalWeight = -1;//设置错误标准return TotalWeight;
}
void DFS(LGraph Graph, Vertex V) {cout << V << endl;PtrToAdjVNode W;Visited[V] = 1;for (W = Graph->G[V].FirstEdge; W; W = W->Next) {if (Visited[W->Adjx] == 0) {DFS(Graph, W->Adjx);}}}
int main()
{LGraph Graph = BuildGraph();LGraph MST = NULL;Kruskal(Graph, MST);DFS(MST, 0);for(int i=0;i<Graph->Ne;i++)return 0;
}

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

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

相关文章

ASP.NET Web(.Net Framework) Http服务器搭建以及IIS站点发布

ASP.NET Web&#xff08;.Net Framework&#xff09; Http服务器搭建以及IIS站点发布 介绍创建ASP.NET Web &#xff08;.Net Framework&#xff09;http服务器创建项目创建脚本部署Http站点服务器测试 Get测试编写刚才的TestWebController.cs代码如下测试写法1测试写法2 Post测…

【AI系统】昇腾 AI 架构介绍

昇腾 AI 架构介绍 昇腾计算的基础软硬件是产业的核⼼&#xff0c;也是 AI 计算能⼒的来源。华为&#xff0c;作为昇腾计算产业⽣态的⼀员&#xff0c;是基础软硬件系统的核⼼贡献者。昇腾计算软硬件包括硬件系统、基础软件和应⽤使能等。 而本书介绍的 AI 系统整体架构&#…

org.apache.commons.lang3包下的StringUtils工具类的使用

前言 相信平时在写项目的时候&#xff0c;一定使用到StringUtils.isEmpty()&#xff1b;StringUtils.isBlank();但是你真的了解他们吗&#xff1f; 也许你两个都不知道&#xff0c;也许你除了isEmpty/isNotEmpty/isNotBlank/isBlank外&#xff0c;并不知道还有isAnyEmpty/isNon…

vscode中json文件的注释飘红

vscode的json文件 添加注释&#xff0c;提示json中不允许有注释&#xff0c;点编辑器最下面的json&#xff0c;如下图 然后选择如上图的json with comments就好了

【AI日记】24.11.30 kaggle 比赛 Titanic-3

【AI论文解读】【AI知识点】【AI小项目】【AI战略思考】【AI日记】 工作 内容&#xff1a;学习 kaggle 入门比赛 Titanic - Machine Learning from Disaster&#xff0c;学习机器学习课程时间&#xff1a;5 小时评估&#xff1a;继续 读书 书名&#xff1a;美丽新世界时间&a…

抓包之查看websocket内容

写在前面 本文看下websocket抓包相关内容。 1&#xff1a;正文 websocket基础环境搭建参考这篇文章。 启动后&#xff0c;先看chrome的network抓包&#xff0c;这里我们直接使用is:running来过滤出websocket的请求&#xff1a; 可以清晰的看到发送的内容以及响应的内容。在…

开源项目:纯Python构建的中后台管理系统

来源&#xff1a;Python大数据分析 费弗里 大家好我是费老师&#xff0c;目前市面上有很多开源的「中后台管理系统」解决方案&#xff0c;复杂如「若依」那种前端基于Vue&#xff0c;后端基于Java的框架&#xff0c;虽然其提供了较为完善的一整套前后端分离权限管理系统解决方…

Power BI - Connect to SharePoint online list with Image column

1.简单介绍 当前SharePoint online list有modern和classic两种模式&#xff0c;现在使用modern模式的比较多。list中有Image类型的列&#xff0c;Power BI如何连接到SharePoint list并显示image呢 note, SharePoint list中的Image列&#xff0c;Lookup列&#xff0c;People列…

DroneCAN 最新开发进展,Andrew在Ardupilot开发者大会2024的演讲

本文是Andrew演讲的中文翻译&#xff0c;你可以直接观看视频了解演讲的全部内容&#xff0c;此演讲视频的中文版本已经发布在Ardupilot社区的Blog板块&#xff0c;你可以在 Arudpilot官网&#xff08;https://ardupilot.org) 获取该视频&#xff1a; 你也可以直接通过Bilibili链…

DataWhale—PumpkinBook(TASK07支持向量机)

课程开源地址及相关视频链接&#xff1a;&#xff08;当然这里也希望大家支持一下正版西瓜书和南瓜书图书&#xff0c;支持文睿、秦州等等致力于开源生态建设的大佬✿✿ヽ(▽)ノ✿&#xff09; Datawhale-学用 AI,从此开始 【吃瓜教程】《机器学习公式详解》&#xff08;南瓜…

基于Python制作一个简易UI界面

基于Python制作一个简易UI界面 目录 基于Python制作一个简易UI界面1 原理简介2 编写程序3 程序测试 1 原理简介 这里用到了Python自带的UI库tkinter。 tkinter 是 Python 的标准 GUI&#xff08;图形用户界面&#xff09;库&#xff0c;用于创建和管理图形界面。它提供了一个简…

【electron-vite】搭建electron+vue3框架基础

一、拉取项目 electron-vite 中文文档地址&#xff1a; https://cn-evite.netlify.app/guide/ 官网网址&#xff1a;https://evite.netlify.app/ 版本 vue版本&#xff1a;vue3 构建工具&#xff1a;vite 框架类型&#xff1a;Electron JS语法&#xff1a;TypeScript &…

操作无法完成,因为其中的文件夹或文件已在另一程序中打开 请关闭该文件夹或文件,然后重试。>>怎么删除被打开的文件

出现这种弹窗是不是很烦人, 也很烦我, 今天就了结了它 我们可以使用一款命令行工具来查看哪些软件正在占用这个文件, 把这些使用文件的软件进程都关闭就可以了 解决办法: 1.下载命令行工具handle 打开浏览器&#xff0c;访问 Sysinternals 官方网站的 Handle 页面, 在页面上…

修改IDEA配置导致Spring Boot项目读取application.properties中文乱码问题

之前很多配置都是放在nacos里面&#xff0c;然后这次同事有个配置写在application.properties中&#xff0c;这个配置含有中文&#xff0c;启动之后发现拿到的中文值会乱码&#xff0c;然后就帮忙看了一下问题。 排查问题 经过不停的百度、排查发现&#xff0c;spring读取app…

常用端口与Udp协议

目录 1.再谈端口 1.1 五元组 1.2 端口号范围划分 1.3 两个指令 1.3.1 netstat 1.3.2 pidof 2.UDP协议 2.1 协议整体格式 2.2 udp特点 2.3 udo缓冲区 1.再谈端口 1.1 五元组 端口号表示了一个主机上进行通信的不同的应用程序&#xff1b;在Tcp/IP协议中&#xff0c;用…

webpack(react)基本构建

文章目录 概要整体架构流程技术名词解释技术细节小结 概要 Webpack 是一个现代 JavaScript 应用程序的静态模块打包工具。它的主要功能是将各种资源&#xff08;如 JavaScript、CSS、图片等&#xff09;视为模块&#xff0c;并将它们打包成一个或多个输出文件&#xff0c;以便…

MATLAB期末复习笔记(中)

三、MATLAB函数和程序结构 1.MATLAB文件 两种类型的M文件&#xff1a; • 脚本 &#xff0c;不接受输入参数或返回输出参数。它们处理工作区中的数据。 • 函数 &#xff0c;可接受输入参数&#xff0c;并返回输出参数。内部变量是函数的局部变量。 ① 函数文件是另一类 m 文…

Mouser EDI 需求分析

为了提高供应链的自动化水平&#xff0c;贸泽电子&#xff08;Mouser Electronics&#xff09;使用EDI技术更好地管理与其全球合作伙伴之间的业务数据往来。对接Mouser EDI&#xff0c;对于企业而言&#xff0c;需要在本地部署EDI软件&#xff0c;建立与Mouser之间的EDI连接通道…

[免费]SpringBoot+Vue景区订票(购票)系统【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的SpringBootVue大景区订票(购票)系统&#xff0c;分享下哈。 项目视频演示 【免费】SpringBootVue景区订票(购票)系统 Java毕业设计_哔哩哔哩_bilibili 项目介绍 现代经济快节奏发展以及不断完善升级的信息…

GitLab的使用

文章目录 一、什么是GitLab、有什么用、与Jenkins的区别什么是GitLab及其用途GitLab与Jenkins的区别GitLab的CI/CD功能介绍 二、GitLab的安装与配置Linux下GitLab的安装*Linux下GitLab的简单使用 /etc/gitlab/gitlab.rb 的配置GitLab服务器的域名邮箱配置功能优化关闭一些暂时不…