最小生成树之Prim算法的实现

这个算法的实现与克鲁斯卡尔算法的实现,个人感觉思想还是差很多的。K算法从第一个迭代就保证了符合最小生成树的基础上的算法正确性,因为每一次选的都是符合规则的前提下代价最小的。然而P算法却不是这么想的,当初上课的时候还问老师,如何证明P算法的正确性。最后发现,不管首次选取的是哪一个点,都是找与此点相关联的边中代价最小的,所以经过某些轮的迭代(最后是图的边数目次)就会把所有权值中最小的那个加进去,倒数第二小的也会进去,第三就不一定了。从极值与最值的关系上也可以理解这个问题,K算法好比每次都是取当前的极值,而P算法是取出所有满足条件的极值,这样子就肯定能把整体下的极值找到。Prim算法和克鲁斯卡尔算法需要的结构框架一样的。

Prim算法:

#pragma once
#include<iostream>
#include<fstream>
#include"MinSpanTree.h"
#include"F:\QQPCmgr\documents\visual studio 2010\Projects\Graph\Graph_list\GraphAdjList.h"
#include"F:\QQPCmgr\documents\visual studio 2010\Projects\UFSet\UFSet\UFset.h"
#include"F:\QQPCmgr\Documents\Visual Studio 2010\Projects\Heap\Heap\MinHeap.h"
using namespace std;

template<class T, class E>
void PrimAlgorithm(GraphAdjList<T,E> &targetG,const T &beginVertex, MinSpanTree<E> &targetMSTree) //初始化算法需要的结构
{
	int verticesNum = targetG.GetVerticesNum(); //获取图的顶点数目
	int edgesNum = targetG.GetEdgesNum(); //获取图的边数目
	int beginIndex = targetG.GetVertexPos(beginVertex); //获取起始操作顶点
	MSTEdgeNode<E> tempEdgeNode; //一个生成树边结点的辅助变量
	MinHeap<MSTEdgeNode<E>> mh(edgesNum); //用图的边数目初始化最小堆
	bool *verticesMST = new bool[verticesNum]; //用于标志一个顶点在哪个顶点域内(如为true则在verticesMST,否则在V-verticesMST) V为图的顶点域
	for(int i = 0; i < verticesNum; i++)
	{
		verticesMST[i] = false; //最初均在V域内
	}

	verticesMST[beginIndex] = true; //先把第一个操作的顶点置为true
	int edgeCount = 1; //进入生成树的边数目计数器
	int beginAdjIdx; //边所关联的另一个顶点索引
	int nullIdx = targetG.GetNullIdx();
	do
	{
		beginAdjIdx = targetG.GetVertexPos(targetG.GetFirstNeighbor(targetG.GetVertexValue(beginIndex))); //获取当前的第一个邻接顶点
		while(beginAdjIdx != nullIdx) //第一个邻接顶点存在
		{
			if(verticesMST[beginAdjIdx] == false) //并且这个顶点还在吐的顶点域内
			{
				tempEdgeNode.head = beginIndex; //获取这个边的信息
				tempEdgeNode.tail = beginAdjIdx;
				tempEdgeNode.key = targetG.GetEdgeWeight(beginIndex, beginAdjIdx);
				mh.Insert(tempEdgeNode); //放入最小堆中
			}
			beginAdjIdx = targetG.GetVertexPos(targetG.GetNextNeighbor(beginIndex, beginAdjIdx));  //再以此当前边找其他的关联边
		}
		//当前的关联边木有 执行下面的语句
		while((mh.IsEmpty() == false) && (edgeCount < verticesNum)) //最小堆不为空,且生成树所需的边数目还不够
		{
			mh.RemoveMinelem(tempEdgeNode); //从最小堆中取出权值最小的边
			if(verticesMST[tempEdgeNode.tail] == false) //判断该边的尾顶点是否还在图顶点域 是的话执行if语句块
			{
				targetMSTree.InsertEdge(tempEdgeNode); //这条边放进生成树中
				beginIndex = tempEdgeNode.tail; //再将这个边的尾顶点置为当前顶点开始搜索其所关联的边
				verticesMST[beginIndex] = true; //将此顶点从图顶点域中踢出,放入verticesMST中
				edgeCount++; //边计数器加1
				break; //一次只找一条边进入生成树,找到就跳出此while循环
			}
		}


	}while(edgeCount < verticesNum); //最外层循环,边数目达到生成树要求,退出

}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值