图——最小生成树算法Prim

package Graph

import (
	"sort"
	"testing"
)
/*
最小生成树算法Prim
1.可以从任意节点出发来寻找最小生成树
2.某个点加入到被选取的点中后,解锁从这个点触发的所有新的边
3.在所有解锁的边中选最小的边,然后看看这个边会不会形成环
4.如果会,不要当前边,继续考察剩下解锁的边中最小的边,重复3
5.如果不会,要当前边,将该边的指向点加入到被选取的点钟,重复2
6.当所有点都被选取,最小生成树就得到了
*/
//最小生成树算法Prim
func PrimMST(graph *Graph) *EdgeSet {
	edgesQueue := new(EdgeSet)             //解锁的边进入队列
	nodeSet := make(map[*Node]struct{}, 0) //哪些点被解锁出来了
	edgeSet := make(map[*Edge]struct{}, 0) //已经考虑过的边不重复考虑
	result := new(EdgeSet)                 //依次挑选的边放入结果集

	k := 0 //找入度为0的点出发,否则可能会出现出度为0的情况
	for k, _ = range graph.Nodes {
		if graph.Nodes[k].In == 0 { //应为随便挑选的一个点
			break
		}
	}

	//for k,_:=range graph.Nodes{    //防森林
	if _, ok := nodeSet[graph.Nodes[k]]; !ok {
		nodeSet[graph.Nodes[k]] = struct{}{}
		for i, _ := range graph.Nodes[k].Edges {
			if _, ok := edgeSet[graph.Nodes[k].Edges[i]]; !ok {
				edgeSet[graph.Nodes[k].Edges[i]] = struct{}{}
				*edgesQueue = append(*edgesQueue, graph.Nodes[k].Edges[i])
			}
		}
		sort.Sort(edgesQueue)

		for len(([]*Edge)(*edgesQueue)) != 0 {
			edge := (*edgesQueue)[0]           //最小的边
			*edgesQueue = (*edgesQueue)[1:]    //删掉该边
			toNode := edge.To                  //可能的一个新的点
			if _, ok := nodeSet[toNode]; !ok { //不含有的时候,就是新的点
				nodeSet[toNode] = struct{}{}
				*result = append(*result, edge)
				for j, _ := range toNode.Edges {
					if _, ok := edgeSet[toNode.Edges[j]]; !ok {
						edgeSet[toNode.Edges[j]] = struct{}{}
						*edgesQueue = append(*edgesQueue, toNode.Edges[j])
					}
				}
				sort.Sort(edgesQueue)
			}
		}
	}
	//break
	//}

	return result

}

func TestPrim(t *testing.T) {
	matrix := [][]int{
		{2, 1, 4},
		{5, 1, 2},
		{3, 1, 5},
		{3, 4, 3},
		{8, 4, 5},
		{9, 5, 6},
		{5, 3, 7},
		{6, 3, 2},

		{2, 2, 6},
		{7, 2, 7},
		{6, 6, 7},
	}

	g := CreateGraph(matrix)
	for k, v := range *PrimMST(g) {
		t.Log("顺序", k+1, "-- 权重:", v.Weight, "从:", v.From.Value, "到:", v.To.Value)
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

metabit

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值