当前课程知识点:数据结构 >  第7章 图 >  7.4 最小生成树 >  7.4.1 普里姆算法

返回《数据结构》慕课在线视频课程列表

7.4.1 普里姆算法在线视频

下一节:7.4.2 克鲁斯卡尔算法

返回《数据结构》慕课在线视频列表

7.4.1 普里姆算法课程教案、知识点、字幕

同学们大家好

我是云南大学信息学院教师孔兵

这节课我们讨论最小生成树的问题

最小生成树是在连通网上考虑的

也就是带权的无向连通图

先看一个引例

假设要在n个城市之间建立通信联络网

则连通n个城市只需要n-1条线路

每条线路有建设的代价

不同线路,建设的代价是不同的

那么在所有可能的n(n-1)/2条线路中

挑选那n-1条线路就是一个问题

比如说我们考虑最省钱的方案

希望这n-1条线路能保证所有顶点连通

并且总的造价最低

这就是最小生成树要解决的问题

最小生成树的定义是,连通网的最小代价生成树

所谓生成树的代价是树上各边的代价之和

求最小生成树的方法有很多

主要都是是基于最小生成树性质

也叫MST性质

MST性质是说,假设N是一个连通网

顶点集是V,边集是E,U是顶点集V的一个非空子集

若(u, v)是一条具有最小权值或者说代价的边

其中u∈U,v∈V-U

则必存在一棵包含边(u, v)的最小生成树

MST性质的含义是说

如果把连通网中的顶点

任意剖分为两个集合,其中一个集合是U

那么另一个集合就是V-U

如果有一条边(u, v)

边一端的顶点在集合U中,另一端的顶点在V-U中

并且(u, v)是一端在U一端在V-U的所有边中代价最小的

那么必存在一棵包含边(u, v)的最小生成树

下面我们结合图示来证明一下

证明的方法是反证法

假设网N的任何一棵最小生成树都不包含边(u, v)

设T是连通网上的一棵最小生成树

我们仍然把T中的顶点看作U和V-U两个集合

因为T是生成树,那么在T中

顶点u和顶点v之间必然有一条路径

这条路径从大U中的顶点u中到V-U中的顶点v

那么这条路径中,必定有一条边

其一端在U一端在V-U,设这条边为(u’,v’)

其中u’属于U,v’属于V-U,如图左边红色边所示

我们对最小生成树T做一个变换

在T中删除(u’,v’)这条边

增加(u, v)这条边,其它不变

变换后的树称为T’,如图右边所示

T’仍然是有n-1条边,删一条增一条

那么,T’是生成树吗?

我们只需要说明,T’仍然是连通的就可以了

考虑T’任意两个顶点

如果在T中它们之间的路径不经过(u’,v’)

那么在T’中它们之间仍然有路径

如果在T中它们之间的路径经过(u’,v’)

那么在T’中,可以通过u’, u, v, v’来连通

因此T’是生成树,根据(u, v)的性质

T’的代价小于等于T,所以T’是一棵最小生成树

和假设矛盾

文字的证明过程同学们参看教材

下面介绍求最小生成树的第一个算法---普里姆算法

看一下算法的描述

TE是已生成的最小生成树中边的集合

U是已生成的最小生成树中顶点的集合

普里姆算法采用的是构造法

从一个顶点开始,逐步构造出一颗最小生成树

算法分为三步

第一步,U={u0}(u0∈V), TE={ }

其中u0是构造的出发点,TE是空集,完成初始化

第二步,在所有u∈U, v∈V-U的边(u, v)∈E中

找一条代价最小的边(u0,v0)并入TE

同时v0并入U,完成一步构造

第三步, 当U≠V时,重复执行第二步

若U=V,表示构造完成,获得了一棵最小生成树

可能同学们注意到了

普里姆算法是对MST性质的直接应用

普里姆算法实现的关键问题

有这样两个,一是找出一端属于U

一端V-U的所有边

二是在这些边里确定代价最小的边

确定代价最小的边很容易

找一端属于U,一端V-U的所有边有些麻烦

难点是随着构造过程,U和V-U是变化的

假设从顶点v1开始构造,初始的时候

大U中只有一个顶点v1,TE是空

v2到v6都在V-U中

一端在U一端在V-U的边共有三条

(v1,v2), (v1,v3),(v1,v4),按算法找出代价最小的

是(v1,v3),把(v1,v3)加入到TE中

顶点v3加入大U。这个时候大U发生了变化

当然V-U肯定也发生了变化

那么一端在U一端在V-U的边需要重新寻找

为了适应这样的变化

我们关注的是V-U中的每个顶点到U中顶点的最小代价边

如果已知这些最小代价边

那么其中最小的就是一端在U一端在V-U的最小代价边

下面我们一个通过例子来看一下普里姆算法执行过程

观察图1

算法的核心是通过一个一维的closedge数组记录

每个V-U中的顶点到U中顶点的最小代价边

数组的大小和存储顶点的一维数组相同

在这里,我们设v1到v6的6个顶点存储位置是0~5

数组的每个元素是一个结构体

结构体中有两个成员,一个成员lowcost

这里简写为low

用来记录该顶点到U中顶点的最小代价边

另外一个成员adjvex,这里简写为adj

用来记录这条最小代价边

所依附的U中的顶点是哪个

观察一下图1中的closedge

0号单元对应的是顶点v1,因为v1是属于大U的

那么对应的low为0,说明这是大U当中的顶点

也是目前大U当中唯一的一个顶点

1单元对应的是顶点v2,因U中只有一个顶点v1

v2到v1的边就是目前v2到大U中顶点的最小边

代价low是6,依附的顶点adj是v1

同样地,v3的最小边是(v1,v3),代价是1

v4的最小边是(v1,v4),代价是5

v5,v6没有到v1的边,那么代价就是无穷

所有边依附的顶点都是v1

图1中就closedge初始的状态

记录了目前每个V-U中的顶点到U中顶点最小代价边的情况

按照普里姆算法第2步,需要找出一端属于U

一端V-U的代价最小的边,基于closedge数组

只要找low非零最小的一个就可以了

现在,我们可以找到2号单元记录的v1到v3的这一条边

代价是1

按照算法,把(v1,v3)加入TE

v3加入到大U当中

观察图2

现在U增加了顶点v3

V-U就是剩下的v2v4v5v6

大U发生了变化

因为新的一个顶点v3的加入

我们需要重新考察

V-U中的顶点到新加入的v3之间是否有边

如果有的话,这条边的代价是不是

比原来记录的最小代价边还要小

如果是的话,closedge数组中的相关单元需要更新

考察v2到v3,边是5,原来v2到U的最短边是6

比原来的小,需要更新

更新以后,v2到U的最短边长度是5

依附的U中的顶点是v3

考察v4到v3,长度是5,它原来的最短边也是5

不必更新。v5v6,他们原来的最短边都是无穷

现在更新为6和4,依附的大U中的顶点都是v3

更新后数组的情况如图2中所示

图3图4是后续步骤图示

其中红色的边是被挑选出加入TE的边

最后一条构造的边是v2到v5这一条

图6中是我们最终构造出的最小生成树

此时U=V,算法结束

顶点加入U的次序是v1,v3,v6,v4,v2,v5

数组closedge的两个成员前面做过说明,这里就不重复了

下面我们看一下普利姆算法的程序实现

涉及到的参数有两个

一个是以数组表示法存储的图G

一个是构造的出发点u

算法中首先定义了closedge数组

绿色框中是算法的初始化

k=LocateVex(G, u),确定出发点u的存储位置

赋值给k

随后用for循环对closedge数组进行初始化

每次循环考察一个顶点j

当j不是我们出发点的时候

把j到k的代价

和u赋值给closedge数组的j号单元

完成初始化

把出发点的lowcost赋值0,表示是大U中的顶点

随后的for循环中,每次循环我们在基于closedge数组

调用minimal函数找出一条一端在U一端在V-U代价最小的边

并把该边对应的V-U中顶点的位置返回赋值给k

printf把这条边在屏幕输出,k对应的lowcost赋值0

表示顶点k加入大U集合中

k加入到大U以后

黄色框中的循环依次处理V-U中的顶点

考察该顶点到新加入的k之间边的代价

如果代价比原来的最小代价边还要小

则更新

前面结合例子详细讨论过

这里不重复了

普里姆算法的时间复杂度是O(n2)

主要是两个嵌套的for循环语句

同学们,最小生成树我们先讨论到这

下次课再见

数据结构课程列表:

前言

-1.算法概念导入

--1.1 算法概念导入

-2.数据结构课程介绍

--2.数据结构课程介绍

-数据结构前言PPT

第0章 预备知识

-0.1变量、类型和表达式

--0.1变量、类型和表达式

-0.2 函数

--0.2 函数

-0.3 指针和单链表

--0.3 指针和单链表

-0.4 数组、指向函数的指针

--0.4 数组、指向函数的指针

-第0章 预备知识讨论题

-数据结构第0章预备知识PPT

第1章 绪论

-1.1什么是数据结构

--1.1什么是数据结构

--测试题

-1.2基本概念和术语

--1.2基本概念和术语

--测试题

-1.3数据结构的描述

--1.3数据结构的描述

--测试题

-1.4抽象数据类型的定义和实现

--1.4抽象数据类型的定义和实现

--测试题

-1.5算法和算法分析概念

--1.5算法和算法分析概念

--测试题

-1.6算法分析示例

--1.6算法分析示例

--测试题

-第1章 绪论讨论题

-数据结构第1章 绪论PPT

第2章 线性表

-2.1 线性表的类型定义

--2.1线性表的类型定义

--测试题

-2.2线性表的顺序表示和实现

--2.2 线性表的顺序表示和实现

--测试题

-2.3 线性链表

--2.3 线性链表

--测试题

-2.4 静态链表

--2.4 静态链表

--测试题

-2.5 循环链表和双向链表

--2.5 循环链表和双向链表

--测试题

-第2章 线性表讨论题

-数据结构第2章线性表PPT

第3章 栈和队列

-3.1 栈

--3.1栈

--测试题

-3.2 栈的实现

--3.2 栈的实现

--测试题

-3.3 栈的应用

--3.3 栈的应用

-3.4 栈与递归的实现

--3.4栈与递归的实现

--测试题

-3.5 队列和链队列

--3.5 队列和链队列

--测试题

-3.6 循环队列

--3.6 循环队列

--测试题

-第3章 栈和队列讨论题

-数据结构第3章栈和队列PPT

第4章 串

-4.1 串

--4.1 串

--测试题

-数据结构第4章 串PPT

第5章 数组

-5.1 数组定义和表示

--5.1 数组定义和表示

--测试题

-5.2矩阵的压缩存储

--5.2 矩阵的压缩存储

--测试题

-第5章 数组讨论题

-数据结构第5章数组PPT

第6章 树和二叉树

-6.1 树的定义和基本术语

--6.1 树的定义和基本术语

-6.2 二叉树和二叉树的性质

--6.2 二叉树和二叉树的性质

--测试题

-6.3 二叉树的存储结构

--6.3二叉树的存储结构

--测试题

-6.4 遍历二叉树

--6.4 遍历二叉树(1)

--6.4 遍历二叉树(2)

--测试题

-6.5 线索二叉树

--6.5 线索二叉树

--测试题

-6.6 树的存储

--6.6树的存储

-6.7 树的转换和遍历

--6.7 树的转换和遍历

--测试题

-6.8 赫夫曼树

--6.8 赫夫曼树

-6.9 赫夫曼编码

--6.9 赫夫曼编码

--测试题

-第6章 树和二叉树讨论题

-数据结构第6章树和二叉树PPT

第7章 图

-7.1 图的定义和术语

--7.1.1图的定义和术语(1)

--7.1.2图的定义和术语(2)

--测试题

-7.2 图的存储结构

--7.2.1 数组表示法(1)

--7.2.2 数组表示法(2)

--7.2.3 邻接表

--测试题

-7.3 图的遍历

--7.3.1 深度优先搜索

--7.3.2 广度优先搜索

--测试题

-7.4 最小生成树

--7.4.1 普里姆算法

--7.4.2 克鲁斯卡尔算法

--测试题

-7.5 有向无环图

--7.5.1 拓扑排序

--7.5.2 关键路径

--测试题

-7.6 最短路径

--7.6.1 单源最短路径-迪杰斯特拉算法

--7.6.2 每一对顶点之间的最短路径-弗洛伊德算法

--测试题

-第7章 图讨论题

-数据结构第7章图PPT

第8章 查找

-8.1 查找基本概念和顺序查找

--8.1 查找基本概念及顺序查找

--测试题

-8.2 有序表的查找

--8.2 有序表的查找

--测试题

-8.3 二叉排序树

--8.3.1 二叉排序树(1)

--8.3.2 二叉排序树(2)

--测试题

-8.4 平衡二叉树

--8.4 平衡二叉树

--测试题

-8.5 哈希表

--8.5.1 哈希表及哈希函数的构造

--8.5.2 解决冲突的方法

--8.5.3 哈希表的查找和性能分析

--测试题

-第8章 查找讨论题

-数据结构第8章查找PPT

第9章 内部排序

-9.1插入排序

--9.1.1 插入排序(1)

--9.1.2 插入排序(2)

--测试题

-9.2 希尔排序

--9.2 希尔排序

--测试题

-9.3 快速排序

--9.3 快速排序

--测试题

-9.4 选择排序

--9.4 选择排序

--测试题

-9.5 堆排序

--9.5 堆排序

--测试题

-9.6 归并排序

--9.6 归并排序

--测试题

-9.7 基数排序

--9.7 基数排序

--测试题

-9.8 排序方法总结

--9.8 排序方法总结

-第9章 内部排序讨论题

-数据结构第9章内部排序PPT

7.4.1 普里姆算法笔记与讨论

也许你还感兴趣的课程:

© 柠檬大学-慕课导航 课程版权归原始院校所有,
本网站仅通过互联网进行慕课课程索引,不提供在线课程学习和视频,请同学们点击报名到课程提供网站进行学习。