2021-04-19:手写代码:最小生成树算法之Kruskal。
2021-04-19:手写代码:最小生成树算法之Kruskal。
福大大 答案2021-04-19:
并查集。边从小到大,找最小边,无环。
代码用golang编写。代码如下:
package main
import (
"fmt"
"sort"
)
func main() {
graph := &Graph{}
graph.nodes = make(map[int]*Node)
graph.nodes[0] = &Node{}
graph.nodes[1] = &Node{}
graph.nodes[2] = &Node{}
graph.edges = make(map[*Edge]struct{})
graph.edges[&Edge{weight: 22, from: graph.nodes[0], to: graph.nodes[1]}] = struct{}{}
graph.edges[&Edge{weight: 33, from: graph.nodes[1], to: graph.nodes[2]}] = struct{}{}
graph.edges[&Edge{weight: 11, from: graph.nodes[2], to: graph.nodes[0]}] = struct{}{}
ret := kruskalMST(graph)
fmt.Println("结果:")
for a, _ := range ret {
fmt.Println(a.weight)
}
}
type Edge struct {
weight int
from *Node
to *Node
}
// 点结构的描述
type Node struct {
value int
in int
out int
nexts []*Node
edges []*Edge
}
type Graph struct {
nodes map[int]*Node
edges map[*Edge]struct{}
}
func printPriorityQueue(priorityQueue []*Edge) {
for _, edge := range priorityQueue {
fmt.Println(edge.weight)
}
}
func kruskalMST(graph *Graph) map[*Edge]struct{} {
unionFind := &UnionFind{}
unionFind.makeSets(graph.nodes)
// 从小的边到大的边,依次弹出,小根堆!
priorityQueue := make([]*Edge, 0)
for edge, _ := range graph.edges {
priorityQueue = append(priorityQueue, edge)
}
fmt.Println("排序前:")
printPriorityQueue(priorityQueue)
//排序
sort.SliceStable(priorityQueue, func(i int, j int) bool {
return priorityQueue[i].weight > priorityQueue[j].weight
})
fmt.Println("--------")
fmt.Println("排序后:")
printPriorityQueue(priorityQueue)
fmt.Println("--------")
result := make(map[*Edge]struct{})
for len(priorityQueue) > 0 { // M 条边
edge := priorityQueue[len(priorityQueue)-1]
priorityQueue = priorityQueue[0 : len(priorityQueue)-1]
if !unionFind.isSameSet(edge.from, edge.to) { // O(1)
result[edge] = struct{}{}
unionFind.union(edge.from, edge.to)
}
}
return result
}
type UnionFind struct {
// key 某一个节点, value key节点往上的节点
fatherMap map[*Node]*Node
// key 某一个集合的代表节点, value key所在集合的节点个数
sizeMap map[*Node]int
}
func (this *UnionFind) makeSets(nodes map[int]*Node) {
this.fatherMap = make(map[*Node]*Node)
this.sizeMap = make(map[*Node]int)
for _, node := range nodes {
this.fatherMap[node] = node
this.sizeMap[node] = 1
}
}
func (this *UnionFind) findFather(n *Node) *Node {
path := make([]*Node, 0)
for n != this.fatherMap[n] {
path = append(path, n)
n = this.fatherMap[n]
}
for len(path) > 0 {
this.fatherMap[path[len(path)-1]] = n
path = path[0 : len(path)-1]
}
return n
}
func (this *UnionFind) isSameSet(a *Node, b *Node) bool {
return this.findFather(a) == this.findFather(b)
}
func (this *UnionFind) union(a *Node, b *Node) {
if a == nil || b == nil {
return
}
aDai := this.findFather(a)
bDai := this.findFather(b)
if aDai != bDai {
aSetSize := this.sizeMap[aDai]
bSetSize := this.sizeMap[bDai]
if aSetSize <= bSetSize {
this.fatherMap[aDai] = bDai
this.sizeMap[bDai] = aSetSize + bSetSize
delete(this.sizeMap, aDai)
} else {
this.fatherMap[bDai] = aDai
this.sizeMap[aDai] = aSetSize + bSetSize
delete(this.sizeMap, bDai)
}
}
}
执行结果如下:
2021-04-19:手写代码:最小生成树算法之Kruskal。的更多相关文章
- .netER的未来路,关于基础是否重要和应该自己手写代码吗?
http://www.cnblogs.com/onepiece_wang/p/5558341.html#!comments 引用"基础知识的学习,一开始可能是背书,但是在后续若干年的工作过程 ...
- ClownFish:比手写代码还快的通用数据访问层
http://www.cnblogs.com/fish-li/archive/2012/07/17/ClownFish.html 阅读目录 开始 ClownFish是什么? 比手写代码还快的执行速度 ...
- 手写代码自动实现自动布局,即Auto Layout的使用
手写代码自动实现自动布局,即Auto Layout的使用,有需要的朋友可以参考下. 这里要注意几点: 对子视图的约束,若是基于父视图,要通过父视图去添加约束. 对子视图进行自动布局调整,首先对UIVi ...
- 如果选择构建ui界面方式,手写代码,xib和StoryBoard间的博弈
代码手写UI这种方法经常被学院派的极客或者依赖多人合作的大型项目大规模使用. 大型多人合作项目使用代码构建UI,主要是看中纯代码在版本管理时的优势,检查追踪改动以及进行代码合并相对容易一些. 另外,代 ...
- 手写代码UI,xib和StoryBoard间的的优劣比较
在UI制作方面,逐渐分化三种主要流派:使用代码手写UI:使用单个xib文件组织viewController或者view:使用StoryBoard来通过单个或很少的几个文件构建UI.三种方式各有优劣,也 ...
- UI到底应该用xib/storyboard完成,还是用手写代码来完成?
UI到底应该用xib/storyboard完成,还是用手写代码来完成? 文章来源:http://blog.csdn.net/libaineu2004/article/details/45488665 ...
- 2019前端面试系列——JS高频手写代码题
实现 new 方法 /* * 1.创建一个空对象 * 2.链接到原型 * 3.绑定this值 * 4.返回新对象 */ // 第一种实现 function createNew() { let obj ...
- Appium初始化设置:手写代码连接手机、appium-desktop连接手机
一.包名获取的三种方式 1)找开发要2)mac使用命令:adb logcat | grep START win使用命令:adb logcat | findstr START 或者可以尝试使用第3条命令 ...
- gcd手写代码及STL中的使用方法
一.手写代码 inline int gcd(int x,int y){ if(y==0) return x; else return(gcd(y,x%y)); } 二.STL中的使用方法 注:在STL ...
- SpringCloud-Ribbon负载均衡机制、手写轮询算法
Ribbon 内置的负载均衡规则 在 com.netflix.loadbalancer 包下有一个接口 IRule,它可以根据特定的算法从服务列表中选取一个要访问的服务,默认使用的是「轮询机制」 Ro ...
随机推荐
- windows2012通过powershell安装远程组件技巧
概要: 通过服务器管理器安装远程桌面服务会报错一直没有办法解决 之后了解到安装组件可以通过powershell命令安装 powershell命令说明 https://docs.microsoft. ...
- 痞子衡嵌入式:我拿到了CSDN博客专家实体证书
「CSDN」作为中国最具人气的专业 IT 社区,一直是广大 IT 技术博主的主选阵地.这些年 CSDN 在知识付费领域的探索也远远超过其它平台,大家(尤其是创作型博主)对 CSDN 的认可度也越来越高 ...
- VsCode新建Java、SpringBoot、Python、JavaWeb项目的基本步骤
新建Java项目 选中正上方的搜索框,按下F1快捷键,输入create Java,即可出现这样的一个命令: 选中这个: 然后为新创建的项目选择一个合适的位置就好啦! 新建SpringBoot项目 选中 ...
- Cesium渲染模块之Command
1. 引言 Cesium是一款三维地球和地图可视化开源JavaScript库,使用WebGL来进行硬件加速图形,使用时不需要任何插件支持,基于Apache2.0许可的开源程序,可以免费用于商业和非商业 ...
- RHEL8使用NMCLI管理网络
使用 NMCLI 配置静态以太网连接 要在命令行上配置以太网连接,请使用 nmcli 工具. 例如,以下流程使用以下设置为 enp7s0 设备创建 NetworkManager 连接配置文件: 静态 ...
- 声网Agora 实时音视频服务正式上线 HTC VIVE Sync App,支持非 VR 用户
全球实时互动云服务开创者和引领者声网Agora(纳斯达克股票代码:API)宣布其视频 SDK 现已集成到领先的 VR/XR 远程协作及会议应用 HTC VIVE Sync App 中. 通过集成声网A ...
- 关于MySQL建立库表时大写自动转换为小写的解决方案
mysql 5.6以上windows对大小写敏感要在my.ini中的[mysqld]下面设置lower_case_table_names = 2 网上有的要改成0 亲测报错 [○・`Д´・ ○]
- Hadoop 安装及目录结构
一.准备工作 [1]创建用户:useradd 用户名[2]配置创建的用户具有 root权限,修改 /etc/sudoers 文件,找到下面一行,在root下面添加一行,如下所示:(注意:需要先给sud ...
- 为什么我推荐你使用 systemd timer 替代 cronjob?
概述 前几天在使用 Terraform + cloud-init 批量初始化我的实验室 Linux 机器.正好发现有一些定时场景需要使用到 cronjob, 进一步了解到 systemd timer ...
- 逍遥自在学C语言 | 逻辑运算符
前言 一.人物简介 第一位闪亮登场,有请今后会一直教我们C语言的老师 -- 自在. 第二位上场的是和我们一起学习的小白程序猿 -- 逍遥. 二.构成和表示方式 逻辑运算符是用来比较和操作布尔值的运算符 ...