Prim
问题背景
加入你遇到这样一个问题,在一个表示了很多村庄的交通图中,其中有每两个村庄之间的交通开销。我们怎么才能够将所有的村庄都相连,并且没有回路,即离散数学里的极小连通图。我们的Prim算法给出了一种经典的解决方法。
思路分析
数学抽象
我们运用离散数学中的图来简化模型,将村庄视作点,边视作连线,然后赋予对应的一个权值。
关键思路分析
以点为中心
因为最终生成的路径一定要包含所有的顶点,所以我们可以从点的角度考虑。任取一个点,找到与其邻接的所有顶点,然后找到最小的权值对应的顶点,把该点放入我们的点集合里,然后然后重复上面的步骤就可以了。
更新权值
一个比较关键的地方就是要不断检查权值,然后对应进行更新。
其实思路总体还是比较清晰,简单,不过在代码里面有很多巧妙的地方
代码设计
如何存储点的信息
我们定义一个Prim特有的数据结构来进行存储
1
2
3
4
5
6
7// 这个就是Prim算法的特殊数据结构,就是你使用这个算法就必须要想起的一个结构
//
// ADT
typedef struct closeedge {
int adjvex;
int lowcast; //? low cast
};思路很妙,lowcast记录该点的最小开销,而adjvex对应最小开销的对应的边。不过我们还有一个问题,那就是我们会发现,怎么检查一个点是否已经在我们的已经考虑过的集合里,然后又怎么决定两条边是否相连,我们分别对下面 的问题进行解决。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// ? love favorite
using Status = int;
using VerTexType = char;
using ArcType = int;
typedef struct {
VerTexType vertices[MVNum];
ArcType arcs[MVNum][MVNum];
int vertexnum{MVNum};
int arcnum{ 0 }; //? Low cost
}AMGraph;我们使用边集数组的数据结构来表示,(这就是数据结构的魅力),然后我们在初始化的时候将对角线初始化为0,以lowcast=0来代表不能建路径,以INF一个极大值来检查是否连通。这就是算法中的关键思路
判断条件(如上)
完整代码
1 | /*****************************************************************//** |
总结
之前很少细想算法设计的思路,自己的思维没有得到锻炼,其中的数学简化思想与代码设计很巧妙与优美,完
- Post title:Prim
- Post author:Winter
- Create time:2023-03-24 19:47:09
- Post link:https://spikeihg.github.io/2023/03/24/Prim/
- Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.
if (hexo-config('comment.enable') == true && hexo-config('comment.use') != "") {
if (hexo-config('comment.use') == "waline") {
@require "./waline.styl"
} else if (hexo-config('comment.use') == "gitalk") {
@require "./gitalk.styl"
} else if (hexo-config('comment.use') == "twikoo") {
@require "./twikoo.styl"
}
}
.comments-container {
display inline-block
margin-top $spacing-unit
width 100%
#comment-anchor {
width 100%
height 10px
}
.comment-area-title {
width 100%
margin 10px 0
font-size 1.38rem
color var(--default-text-color)
font-family "Noto Sans", "Noto Sans SC",sans-serif
font-weight bold
i {
color var(--default-text-color)
}
+redefine-tablet() {
margin 5px 0
font-size 1.2rem
}
}
}