数据结构之最小生成树

prime算法

普里姆(Prim)算法,是用来求加权连通图的最小生成树的算法。

基本思想
对于图G而言,V是所有顶点的集合;现在,设置两个新的集合U和T,其中U用于存放G的最小生成树中的顶点,T存放G的最小生成树中的边。 从所有uЄU,vЄ(V-U) (V-U表示出去U的所有顶点)的边中选取权值最小的边(u, v),将顶点v加入集合U中,将边(u, v)加入集合T中,如此不断重复,直到U=V为止,最小生成树构造完毕,这时集合T中包含了最小生成树中的所有边。

邻接矩阵实现

基本定义

class MatrixUDG {#define MAX    100#define INF    (~(0x1<<31))        // 无穷大(即0X7FFFFFFF)private:char mVexs[MAX];    // 顶点集合int mVexNum;             // 顶点数int mEdgNum;             // 边数int mMatrix[MAX][MAX];   // 邻接矩阵public:// 创建图(自己输入数据)MatrixUDG();// 创建图(用已提供的矩阵)//MatrixUDG(char vexs[], int vlen, char edges[][2], int elen);MatrixUDG(char vexs[], int vlen, int matrix[][9]);~MatrixUDG();// 深度优先搜索遍历图void DFS();// 广度优先搜索(类似于树的层次遍历)void BFS();// prim最小生成树(从start开始生成最小生成树)void prim(int start);// 打印矩阵队列图void print();private:// 读取一个输入字符char readChar();// 返回ch在mMatrix矩阵中的位置int getPosition(char ch);// 返回顶点v的第一个邻接顶点的索引,失败则返回-1int firstVertex(int v);// 返回顶点v相对于w的下一个邻接顶点的索引,失败则返回-1int nextVertex(int v, int w);// 深度优先搜索遍历图的递归实现void DFS(int i, int *visited);};

MatrixUDG是邻接矩阵对应的结构体。
mVexs用于保存顶点,mVexNum是顶点数,mEdgNum是边数;mMatrix则是用于保存矩阵信息的二维数组。例如,mMatrix[i][j]=1,则表示”顶点i(即mVexs[i])”和”顶点j(即mVexs[j])”是邻接点;mMatrix[i][j]=0,则表示它们不是邻接点。

prime算法

/** prim最小生成树** 参数说明:*   start -- 从图中的第start个元素开始,生成最小树*/
void MatrixUDG::prim(int start)
{int min,i,j,k,m,n,sum;int index=0;         // prim最小树的索引,即prims数组的索引char prims[MAX];     // prim最小树的结果数组int weights[MAX];    // 顶点间边的权值// prim最小生成树中第一个数是"图中第start个顶点",因为是从start开始的。prims[index++] = mVexs[start];// 初始化"顶点的权值数组",// 将每个顶点的权值初始化为"第start个顶点"到"该顶点"的权值。for (i = 0; i < mVexNum; i++ )weights[i] = mMatrix[start][i];// 将第start个顶点的权值初始化为0。// 可以理解为"第start个顶点到它自身的距离为0"。weights[start] = 0;for (i = 0; i < mVexNum; i++){// 由于从start开始的,因此不需要再对第start个顶点进行处理。if(start == i)continue;j = 0;k = 0;min = INF;// 在未被加入到最小生成树的顶点中,找出权值最小的顶点。while (j < mVexNum){// 若weights[j]=0,意味着"第j个节点已经被排序过"(或者说已经加入了最小生成树中)。if (weights[j] != 0 && weights[j] < min){min = weights[j];k = j;}j++;}// 经过上面的处理后,在未被加入到最小生成树的顶点中,权值最小的顶点是第k个顶点。// 将第k个顶点加入到最小生成树的结果数组中prims[index++] = mVexs[k];// 将"第k个顶点的权值"标记为0,意味着第k个顶点已经排序过了(或者说已经加入了最小树结果中)。weights[k] = 0;// 当第k个顶点被加入到最小生成树的结果数组中之后,更新其它顶点的权值。for (j = 0 ; j < mVexNum; j++){// 当第j个节点没有被处理,并且需要更新时才被更新。if (weights[j] != 0 && mMatrix[k][j] < weights[j])weights[j] = mMatrix[k][j];}}// 计算最小生成树的权值sum = 0;for (i = 1; i < index; i++){min = INF;// 获取prims[i]在mMatrix中的位置n = getPosition(prims[i]);// 在vexs[0...i]中,找出到j的权值最小的顶点。for (j = 0; j < i; j++){m = getPosition(prims[j]);if (mMatrix[m][n]<min)min = mMatrix[m][n];}sum += min;}// 打印最小生成树cout << "PRIM(" << mVexs[start] << ")=" << sum << ": ";for (i = 0; i < index; i++)cout << prims[i] << " ";cout << endl;
}

kruskal算法

克鲁斯卡尔(Kruskal)算法,是用来求加权连通图的最小生成树的算法。

基本思想:按照权值从小到大的顺序选择n-1条边,并保证这n-1条边不构成回路。
具体做法:首先构造一个只含n个顶点的森林,然后依权值从小到大从连通网中选择边加入到森林中,并使森林中不产生回路,直至森林变成一棵树为止。

克鲁斯卡尔算法分析

根据前面介绍的克鲁斯卡尔算法的基本思想和做法,我们能够了解到,克鲁斯卡尔算法重点需要解决的以下两个问题:
问题一 对图的所有边按照权值大小进行排序。
问题二 将边添加到最小生成树中时,怎么样判断是否形成了回路。

问题一很好解决,采用排序算法进行排序即可。

问题二,处理方式是:记录顶点在”最小生成树”中的终点,顶点的终点是”在最小生成树中与它连通的最大顶点”(关于这一点,后面会通过图片给出说明) 。然后每次需要将一条边添加到最小生存树时,判断该边的两个顶点的终点是否重合,重合的话则会构成回路。 以下图来进行说明:

在将

// 边的结构体
class EData
{public:char start; // 边的起点char end;   // 边的终点int weight; // 边的权重public:EData(){}EData(char s, char e, int w):start(s),end(e),weight(w){}
};

EData是邻接矩阵边对应的结构体。

class MatrixUDG {#define MAX    100#define INF    (~(0x1<<31))        // 无穷大(即0X7FFFFFFF)private:char mVexs[MAX];    // 顶点集合int mVexNum;             // 顶点数int mEdgNum;             // 边数int mMatrix[MAX][MAX];   // 邻接矩阵public:// 创建图(自己输入数据)MatrixUDG();// 创建图(用已提供的矩阵)//MatrixUDG(char vexs[], int vlen, char edges[][2], int elen);MatrixUDG(char vexs[], int vlen, int matrix[][9]);~MatrixUDG();// 深度优先搜索遍历图void DFS();// 广度优先搜索(类似于树的层次遍历)void BFS();// prim最小生成树(从start开始生成最小生成树)void prim(int start);// 克鲁斯卡尔(Kruskal)最小生成树void kruskal();// 打印矩阵队列图void print();private:// 读取一个输入字符char readChar();// 返回ch在mMatrix矩阵中的位置int getPosition(char ch);// 返回顶点v的第一个邻接顶点的索引,失败则返回-1int firstVertex(int v);// 返回顶点v相对于w的下一个邻接顶点的索引,失败则返回-1int nextVertex(int v, int w);// 深度优先搜索遍历图的递归实现void DFS(int i, int *visited);// 获取图中的边EData* getEdges();// 对边按照权值大小进行排序(由小到大)void sortEdges(EData* edges, int elen);// 获取i的终点int getEnd(int vends[], int i);
};

MatrixUDG是邻接矩阵对应的结构体。
mVexs用于保存顶点,mVexNum是顶点数,mEdgNum是边数;mMatrix则是用于保存矩阵信息的二维数组。例如,mMatrix[i][j]=1,则表示”顶点i(即mVexs[i])”和”顶点j(即mVexs[j])”是邻接点;mMatrix[i][j]=0,则表示它们不是邻接点。

/** 克鲁斯卡尔(Kruskal)最小生成树*/
void MatrixUDG::kruskal()
{int i,m,n,p1,p2;int length;int index = 0;          // rets数组的索引int vends[MAX]={0};     // 用于保存"已有最小生成树"中每个顶点在该最小树中的终点。EData rets[MAX];        // 结果数组,保存kruskal最小生成树的边EData *edges;           // 图对应的所有边// 获取"图中所有的边"edges = getEdges();// 将边按照"权"的大小进行排序(从小到大)sortEdges(edges, mEdgNum);for (i=0; i<mEdgNum; i++){p1 = getPosition(edges[i].start);      // 获取第i条边的"起点"的序号p2 = getPosition(edges[i].end);        // 获取第i条边的"终点"的序号m = getEnd(vends, p1);                 // 获取p1在"已有的最小生成树"中的终点n = getEnd(vends, p2);                 // 获取p2在"已有的最小生成树"中的终点// 如果m!=n,意味着"边i""已经添加到最小生成树中的顶点"没有形成环路if (m != n){vends[m] = n;                       // 设置m"已有的最小生成树"中的终点为nrets[index++] = edges[i];           // 保存结果}}delete[] edges;// 统计并打印"kruskal最小生成树"的信息length = 0;for (i = 0; i < index; i++)length += rets[i].weight;cout << "Kruskal=" << length << ": ";for (i = 0; i < index; i++)cout << "(" << rets[i].start << "," << rets[i].end << ") ";cout << endl;
}

References
Prim算法(二)之 C++详解 - 如果天空不死 - 博客园

Kruskal算法(二)之 C++详解 - 如果天空不死 - 博客园

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

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

相关文章

打造无所不及的智能:徐直军发布华为AI战略及全栈全场景方案

来源&#xff1a;C114通信网摘要&#xff1a;选择正确的问题比寻找新奇的方案更重要。“这是一个伟大的时代&#xff0c;华为立志为推动人类进步和世界繁荣做出贡献。2017年底&#xff0c;我们提出了新的愿景和使命&#xff0c;‘把数字世界带入每个人、每个家庭、每个组织&…

同步博客到CSDN

经过一些朋友的多次邀请&#xff0c;现同步博客到CSDN&#xff0c;地址:http://blog.csdn.net/knightswarrior。 转载于:https://www.cnblogs.com/KnightsWarrior/p/BackupToCSDN.html

四超多强 一文看懂中国CV独角兽格局

来源&#xff1a;网易智能通过短短两三年的攻城略地&#xff0c;中国CV&#xff08;Computer Vision&#xff0c;计算机视觉&#xff09;行业形成“四超多强”的格局。商汤、云从、依图、旷视还被称为“四小龙”&#xff0c;他们之间的故事由来已久&#xff0c;谈及最多的当属他…

http://www.shengshiyouxi.com

android从Linux系统启动有4个步骤&#xff1b; (1) init进程启动 (2) Native服务启动 (3) System Server&#xff0c;Android服务启动 (4) Home启动 总体启动框架图如&#xff1a; 第一步&#xff1a;initial进程(system\core\init) init进程&…

清华 Aminer 发布最新2018人脸识别研究报告

来源&#xff1a;专知AMiner平台由清华大学计算机系研发&#xff0c;拥有我国完全自主知识产权。平台包含了超过2.3亿学术论文/专利和1.36亿学者的科技图谱&#xff0c;提供学者评价、专家发现、智能指派、学术地图等科技情报专业化服务。 今日&#xff0c;该平台发布最新的201…

敏捷实践:比每日会议更疯狂的半日会议!

由“每周例会”说起 每天项目例会的话&#xff0c;频率太高了&#xff0c;可能会浪费时间&#xff0c;如果每月一次&#xff0c;似乎时间太长了&#xff0c;于是我们往往会“每周例会”。 有一次我参加了某项目的每周例会&#xff0c;开会的时间是周五&#xff0c;会上其中一位…

智能生产的现状与未来!

来源&#xff1a;数字化企业北京机械工业自动化研究所首席专家蒋明炜先生是我国最早投身企业管理及其信息化事业的专家之一&#xff0c;积累了宝贵的理论实践经验&#xff0c;在国家提出《中国制造2025》之后&#xff0c;蒋明炜先生作为该领域资深专家&#xff0c;先后组织领导…

82岁的北大教授证明了黎曼猜想?

来源&#xff1a;AI科技大本营最近&#xff0c;黎曼猜想有点热。上个月&#xff0c;89 岁的菲尔兹奖与阿贝尔奖双料得主、英国皇家学会院士迈克尔阿蒂亚爵士&#xff08;Michael Atiyah&#xff09;刚刚宣布自己证明了黎曼猜想。近日&#xff0c;82 岁的北大教授&#xff08;已…

Atlas机器人再秀逆天操作!波士顿动力科研or商业化,将何去何从?

来源&#xff1a;物联网智库在众多机器人相关的技术公司里&#xff0c;波士顿动力的核心特点在于&#xff0c;他们始终将「仿生」看作机器人设计的最高宗旨。其创始人Raibert 也称自己的目的是建造一种能和动物以及人一模一样的&#xff0c;完成一切事情的机器人。这既是波士顿…

OpenGL6-纹理动画

代码下载 #include "CELLWinApp.hpp"#include <gl/GLU.h>#include <assert.h>#include <math.h>#pragma comment(lib,"opengl32.lib")#pragma comment(lib,"glu32.lib")#pragma comment(lib,"winmm.lib") /*** 这个…

《科学美国人》:美国应保持太空、网络、生物领域的科技优势

来源&#xff1a;美国《科学美国人》转自&#xff1a;国防科技要闻&#xff08;ID&#xff1a;CDSTIC&#xff09;作者&#xff1a;军事科学院军事科学信息研究中心 吴海近日&#xff0c;美国《科学美国人》杂志发表《我们准备好迎接未来战争了吗&#xff1f;》一文&#xff…

微信开发入门

微信开发需要搭建PHP环境 参考链接&#xff1a;Apache2.2与php5.3.5如何整合&#xff1f;如何能够被使用_百度经验 搭建的过程出现了很多坑&#xff0c;只能小心&#xff0c;重复搭建了&#xff0c;错误原因可能是VC9或VC11环境没有配置的原因&#xff0c;多试试才行。 然后…

实现计算机界“大满贯”,芮勇博士再获技术成就大奖

来源&#xff1a;联想研究院近日&#xff0c;国际计算机协会&#xff08;ACM&#xff09;多媒体专委会&#xff08;Special Interest Group on Multimedia&#xff0c;简称SIGMM&#xff09;2018技术成就奖揭晓了。在全球众多的候选人当中&#xff0c;该奖最终花落联想集团首席…

机器人流程自动化崛起,中国是否准备好迎接智能自动化时代?

来源&#xff1a;亿欧智库摘要&#xff1a;机器人流程自动化&#xff08;Robotic Process Automation, RPA&#xff09;正迅速成为企业改善服务、提高效率和降低成本的关键工具。对此&#xff0c;PWC针对国内RPA市场展开了调查&#xff0c;预计未来45%的工作活动可以实现自动化…

加州伯克利大学:自动驾驶中虚拟到现实的强化学习|厚势汽车

来源&#xff1a;同济智能汽车研究所UCB 提出了虚拟场景到真实场景的翻译网络&#xff0c;解决强化学习用于自动驾驶虚拟测试中与现实测试的差异。强化学习需要大量的试错&#xff0c;而真实的自动驾驶车辆&#xff08;AV&#xff09;无法提供大量的试错为此 AV 强化学习使用虚…

2019年机器学习:追踪人工智能发展之路

作者&#xff5c;Hussain Fakhruddin编译&#xff5c;专知整理&#xff5c;Yingying&#xff0c;李大囧摘要&#xff1a;“智能助理”的时代已经到来了。机器学习已经成为全球数字化转型的关键要素之一 ,在企业领域&#xff0c;机器学习用例的增长在过去几年中也是显著的。预计…

价值2950亿美元的「量子霸权」,技术水平到了哪个阶段

来源&#xff1a;36Kr摘要&#xff1a;谁掌握了量子计算机&#xff0c;谁就可能引领下一次信息革命。当前经典计算体系&#xff0c;并不能解决所有问题。量子计算将给现有的计算理论带来深刻变革&#xff0c;将极大加深人类对物质与信息的理解&#xff1b;将是一种前所未有的计…

微信开发简单实例

本文主要包括以下内容 1. 微信聊天机器人 微信聊天机器人 利用图灵机器人接口实现微信聊天机器人 <?phpdefine("TOKEN", "weixin"); $wechatObj new wechatCallbackapiTest(); if (isset($_GET[echostr])) {$wechatObj->valid(); }else{$wec…

开放政府数据价值:内涵、评价与实践

来源&#xff1a;《政府数据开放研究》作者&#xff1a;陈美 湖北工业大学经济与管理学院分析开放政府数据的价值与评价&#xff0c;有助于政府数据开放更高效地开展。文章在界定开放政府数据价值内涵与层次划分的基础上&#xff0c;介绍国外开放政府数据价值评价进展&#xff…

Smarty模板技术学习

模板引擎技术&#xff1a;使得php代码和html代码分离的技术就称为“模板引擎技术” 自定义smarty模板技术实现 <?php//迷你smarty原理 class MiniSmarty{public $var_arr array();public $template_dir "./view/";public $compile_dir "./view_c/"…