【开卷数据结构 】图的应用——最短生成树

简介: 【开卷数据结构 】图的应用——最短生成树

最小生成树


Q:什么是广度优先搜索


A:一个连通图的生成树含有图中全部的顶点,并且只含尽可能少的边。若砍去它的一条边,则会使生成树变成非连通图。若给它增加一条边,则会形成图中的一条回路。


对于一个带权连通无向图 G=(V, E) ,生成树不同,每棵树的权(即树中所有边上的权值之和)也可能不同,其中边的权值之和最小的那棵生成树(构造连通网的最小代价生成树),称为G的最小生成树。


通过定义不难看出,最小生成树具有以下性质:


1)最小生成树不是唯一的,即最小生成树的树形不唯一,所有生成树中可能有多个最小生成树。当图 G 中的各边权值互不相等时,G 的最小生成树是唯一的。 若无向连通图 G 的边数比顶点数少1,即 G 本身是一棵树时,则 G 的最小生成树就是它本身。

2)最小生成树的边的权值之和总是唯一的,虽然最小生成树不唯一,但其对应的边的权值之和总是唯一的,而且是最小的。

3)最小生成树的边数为顶点数减1。

构造最小生成树 有多种算法,但大多数算法都利用了最小生成树的下列性质:假设  G=(V,E) 是一个带权连通无向图,U 是顶点集 V 的一个非空子集。若 (u,v) 是一条具有最小权值的边,其中  u∈U,v∈V−U , 则必存在一棵包含边 (u,v) 的最小生成树。


下面介绍一个通用的最小生成树算法:


GENERIC_MST(G){
  T=NULL;
  while T 未形成一棵生成树;
  do 找到一条最小代价边(u, v)并且加入T后不会产生回路;
    T=T ∪ (u, v);
}

通用算法每次加入一条边以逐渐形成一棵生成树,下面介绍两种实现上述通用算法的途径。


Prim算法实现最小生成树


Q:如何通过Prim算法构建最小生成树


A:初始时从图中任取一顶点加入树 T,此时树中只含有一个顶点。之后选择一个与当前 T 中顶点集合距离最近的顶点,并将该顶点和相应的边加入 T。每次操作后 T 中的顶点数和边数都增 1。以此类推,直至图中所有的顶点都并入 T,得到的 T 就是最小生成树。此时 T 中必然有 n-1条边。


通俗来讲,Prim算法构建最小生成树流程如下:


1) 从某顶点 u0 出发,选择与它关联的具有最小权值的边 (u0, v),将其顶点 v 加入到生成树的顶点集合 U 中。

2) 每一步从一个顶点在 U 中,而另一个顶点不在 U 中的各条边中选择权值最小的边 (u, v),把它的顶点 v 加入到 U 中。

3)直到所有顶点都加入到生成树顶点集合 U 中为止。

Prim算法的简单实现如下:


void Prim(G,T)
{
  t=NULL;    //初始化空树 
  U={w};    //添加任一结点 w
  while((V-U)!=NULL)  //若树中不含全部结点
  {
  设(u,v)是使 u∈U与v∈(V-U),且权值最小的边;
  T=T∪{{u,v}} //边归入树 
  U=U∪{v};  //顶点归入树 
  } 
}

Prim 算法的时间复杂度为 O(n^2),不依赖于|E|,因此它适用于求解边稠密的图的最小生成树。


kruskal算法实现最小生成树


与 Prim 算法从顶点开始扩展最小生成树不同,Kruskal 算法是一种按权值的递增次序选择合适的边来构造最小生成树的方法。


Q:如何通过kruskal算法构建最小生成树


A:初始时为只有 n 个顶点而无边的非连通图 T=V,每个顶点自成一个连通分量,然后按照边的权值由小到大的顺序,不断选取当前未被选取过且权值最小的边,若该边依附的顶点落在 T 中不同的连通分量上,则将此边加入 T,否则舍弃此边而选择下一条权值最小的边。以此类推,直至 T 中所有顶点都在一个连通分量上。


通俗来讲,kruskal算法构建最小生成树流程如下:


1)设连通网络 N = { V, E },构造一个只有 n 个顶点,没有边的非连通图 T = { V, Ø }, 每个顶点自成一个连通分量。

2) 在 E 中选最小权值的边,若该边的两个顶点落在不同的连通分量上,则加入 T 中;否则舍去,重新选择。

3)重复下去,直到所有顶点在同一连通分量上为止。

kruskal算法的简单实现如下::


void Kruskal(V,T)
{
  T=V;    //初始化树T,仅含顶点
  numS=n    //连通分量数
  while(numS>1){  //若连通分量数大于 1 
  从 E 中取出权值最小的边(v,u); 
  T=T ∪{{v,u}}; //将此边加入生成树中 
  numS--;   //连通分量减 1 
  } 
}

kruskal 算法的时间复杂度为 O(ElogE) ,因此它适用于求解边稀疏而顶点多的图的最小生成树。


相关文章
|
3月前
|
算法
数据结构之博弈树搜索(深度优先搜索)
本文介绍了使用深度优先搜索(DFS)算法在二叉树中执行遍历及构建链表的过程。首先定义了二叉树节点`TreeNode`和链表节点`ListNode`的结构体。通过递归函数`dfs`实现了二叉树的深度优先遍历,按预序(根、左、右)输出节点值。接着,通过`buildLinkedList`函数根据DFS遍历的顺序构建了一个单链表,展示了如何将树结构转换为线性结构。最后,讨论了此算法的优点,如实现简单和内存效率高,同时也指出了潜在的内存管理问题,并分析了算法的时间复杂度。
78 0
|
2天前
|
DataX
☀☀☀☀☀☀☀有关栈和队列应用的oj题讲解☼☼☼☼☼☼☼
### 简介 本文介绍了三种数据结构的实现方法:用两个队列实现栈、用两个栈实现队列以及设计循环队列。具体思路如下: 1. **用两个队列实现栈**: - 插入元素时,选择非空队列进行插入。 - 移除栈顶元素时,将非空队列中的元素依次转移到另一个队列,直到只剩下一个元素,然后弹出该元素。 - 判空条件为两个队列均为空。 2. **用两个栈实现队列**: - 插入元素时,选择非空栈进行插入。 - 移除队首元素时,将非空栈中的元素依次转移到另一个栈,再将这些元素重新放回原栈以保持顺序。 - 判空条件为两个栈均为空。
|
1月前
|
存储 C++
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
【数据结构——树】哈夫曼树(头歌实践教学平台习题)【合集】目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果:任务描述 本关任务:编写一个程序构建哈夫曼树和生成哈夫曼编码。 相关知识 为了完成本关任务,你需要掌握: 1.如何构建哈夫曼树, 2.如何生成哈夫曼编码。 测试说明 平台会对你编写的代码进行测试: 测试输入: 1192677541518462450242195190181174157138124123 (用户分别输入所列单词的频度) 预
59 14
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
|
1月前
|
Java C++
【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
48 12
|
1月前
|
C++
【C++数据结构——树】二叉树的性质(头歌实践教学平台习题)【合集】
本文档介绍了如何根据二叉树的括号表示串创建二叉树,并计算其结点个数、叶子结点个数、某结点的层次和二叉树的宽度。主要内容包括: 1. **定义二叉树节点结构体**:定义了包含节点值、左子节点指针和右子节点指针的结构体。 2. **实现构建二叉树的函数**:通过解析括号表示串,递归地构建二叉树的各个节点及其子树。 3. **使用示例**:展示了如何调用 `buildTree` 函数构建二叉树并进行简单验证。 4. **计算二叉树属性**: - 计算二叉树节点个数。 - 计算二叉树叶子节点个数。 - 计算某节点的层次。 - 计算二叉树的宽度。 最后,提供了测试说明及通关代
46 10
|
1月前
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
49 2
|
3月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
99 5
|
3月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
99 1
|
3月前
|
缓存 NoSQL PHP
Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出
本文深入探讨了Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出。文章还介绍了Redis在页面缓存、数据缓存和会话缓存等应用场景中的使用,并强调了缓存数据一致性、过期时间设置、容量控制和安全问题的重要性。
68 5
|
3月前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
149 16