Go语言数据结构和算法(三十)最小生成树Prim算法

24 阅读3分钟

最小生成树是连接的无向图中的边子集.它将所有点连接在一起.没有任何循环.并且具

有最小可能的总边权.MST是一个生成树.其边权重之和尽可能小.

生成树的代价是树中所有边的权重之和.可以有很多颗生成树.最小生成树是所有生成

树中最小的树.

1.Prim算法:

Prim算法也使用贪心算法来寻找最小生成树.在Prim算法中.从起始位置开始生成树.

与Kruskal算法不同.Prim算法将顶点添加到不断增长的生成树中.

2.应用场景:

网络设计:

在计算机网络中.设计高效的网络拓扑非常重要.最小生成树可用于识别连接网络中所

有节点需要的最小连接集.

交通系统:

最小生成树可用于寻找连接一个国家所有城市的最低成本.可用于规划货物和服务交

通的运输.

图像处理:

在图像处理中.最小生成树可以用于识别给定图像的最小生成树,并分析图像结构.

3.Prim算法介绍:

Prim算法是一种贪心算法.用于从图中找到最小生成树.Prim算法找到包含图的每个

顶点的边的子集.以便可以最小化边的权重之和.Prim算法从单个节点开始.并在每一

步探索所有具有连接边的相邻节点.因为选择了具有最小权重的边.所以图中没有循环.

4.Prim算法步骤:

使用随机选择顶点初始化一个最小生成树.

找到将步骤一生成的树与新顶点连接起来的所有边.从找到的边中选择最小边将其添加到树中.

重复步骤二直到形成最小生成树.

5.实现:

5.1方法:

package data

import "math"

const MAX = math.MaxInt32

func Prims(graph [][]int, n int) int {
	//初始化变量.
	key := make([]int, n)
	mst := make([]int, n)
	visited := make([]bool, n)
	for i := 0; i < n; i++ {
		key[i] = MAX
		mst[i] = -1
	}

	key[0] = 0
	mst[0] = -1
	//寻找最小生成树.
	for i := 0; i < n-1; i++ {
		minIndex := findMinVertex(key, visited, n)
		visited[minIndex] = true
		for j := 0; j < n; j++ {
			if graph[minIndex][j] != 0 && !visited[j] && graph[minIndex][j] < key[j] {
				key[j] = graph[minIndex][j]
				mst[j] = minIndex
			}
		}
	}
	//计算最小生成树的权重.
	sum := 0
	for i := 1; i < n; i++ {
		sum += graph[i][mst[i]]
	}
	return sum
}

func findMinVertex(key []int, visited []bool, n int) int {
	min := MAX
	minIndex := -1
	for i := 0; i < n; i++ {
		if visited[i] == false && key[i] < min {
			min = key[i]
			minIndex = i
		}
	}
	return minIndex
}

5.2main方法:

func main() {
	graph := [][]int{
		{0, 2, 0, 6, 0},
		{2, 0, 3, 8, 5},
		{0, 3, 0, 0, 7},
		{6, 8, 0, 0, 9},
		{0, 5, 7, 9, 0},
	}
	fmt.Println("最小生成树的权重", data.Prims(graph, 5))
}

6.实战:

6.1方法:

// 最小生成树的prim算法.
func MinCost(points [][]int) (ans int) {
	n := len(points)
	dis := make([]int, n)
	x, y := points[0][0], points[0][1]
	for i := range dis {
		dis[i] = absPrim(points[i][0]-x) + abs(points[i][1]-y)
	}
	mark := make([]bool, n)
	for {
		chosen, min := -1, 1_000_000_000
		for i := range dis {
			if !mark[i] && dis[i] < min {
				min, chosen = dis[i], i
			}
		}
		if chosen == -1 {
			break
		}
		mark[chosen] = true
		ans += dis[chosen]
		for i := range dis {
			if mark[i] {
				continue
			}
			d := absPrim(points[i][0]-points[chosen][0]) + absPrim(points[i][1]-points[chosen][1])
			if dis[i] > d {
				dis[i] = d
			}
		}
	}
	return
}

func absPrim(x int) int {
	if x < 0 {
		return -x
	}
	return x
}

6.2main方法:

func main() {
	points := [][]int{{1, 2}, {3, 4}}
	res := data.MinCost(points)
	fmt.Println(res)
}

辞去经年.





如果大家喜欢我的分享话.可以关注我的微信公众号

念何架构之路