Prim算法实现类

来复习复习最小生成树的算法,其中的prim算法比较简单。虽说用一般的邻接矩阵需要O(V2)的的时间复杂度。但是改为邻接表之后,会稍微提高到O(E log(V))

不过,这个,测试数据输错了,把我郁闷了半个钟头。太大意了。

这个Prim算法的原理呢,和Dijkstra算法有些类似。一个小城镇的扩张,慢慢侵蚀离它最近的点,吞噬成为其一部分,然后再继续吞噬。

Wiki上给出的比较好懂,我的比较抽象了。如下:

从单一顶点开始,普里姆算法按照以下步骤逐步扩大树中所含顶点的数目,直到遍及连通图的所有顶点。

  1. 输入:一个加权连通图,其中顶点集合为V,边集合为E;
  2. 初始化:Vnew = {x},其中x为集合V中的任一节点(起始点),Enew = {};
  3. 重复下列操作,直到Vnew = V:
    1. 在集合E中选取权值最小的边(u, v),其中u为集合Vnew中的元素,而v则不是(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);
    2. 将v加入集合Vnew中,将(u, v)加入集合Enew中;
  4. 输出:使用集合Vnew和Enew来描述所得到的最小生成树。

代码如下:

#include <iostream>
#include <queue>

#define MAX_VERTEX 15
#define MAX_EDGE 25
#define AL_END -1

using namespace std;

struct Edge
{
	int next;
	int vertex;
	int cost;
};

struct Vertex 
{
	int cost;
	int vertex;
};

bool operator <(const Vertex &a, const Vertex &b)
{
	return a.cost > b.cost;
}

class AlGraph
{
public:
	int smallestCost;
	void prim();

private:
	int vertexNum;
	int edgeNum;
	int AlVertex[MAX_VERTEX];
	Edge edge[MAX_EDGE];
	bool vertexDealed[MAX_VERTEX];
	priority_queue<Vertex> primQueue;

	void initialize();
	void getData();
};

void AlGraph::initialize()
{
	smallestCost = 0;

	memset(AlVertex, AL_END,sizeof(AlVertex));
	memset(vertexDealed, 0, sizeof(vertexDealed));

	while (!primQueue.empty())
	{
		primQueue.pop();
	}
}

void AlGraph::getData()
{
	initialize();

	cout << "Please input the vertex number: ";
	cin >> vertexNum;

	cout << "Please input the edge number: ";
	cin >> edgeNum;

	int source, destination, cost;
	int ip = 0;
	cout << "Please input the edges(source, destination, cost)." << endl;
	for (int i = 0; i < edgeNum; i++)
	{
		cin >> source >> destination >> cost;
		edge[ip].next = AlVertex[source];
		edge[ip].cost = cost;
		edge[ip].vertex = destination;
		AlVertex[source] = ip++;

		swap(source, destination);

		edge[ip].next = AlVertex[source];
		edge[ip].cost = cost;
		edge[ip].vertex = destination;
		AlVertex[source] = ip++;
	}
}

void AlGraph::prim()
{
	getData();

	int gotNum = 0;

	Vertex firstVertex;
	firstVertex.cost = 0;
	firstVertex.vertex = 0;
	primQueue.push(firstVertex);

	while (gotNum < vertexNum)
	{
		if (primQueue.empty())
		{
			cout << "Islet discovered!" << endl;
			break;
		}

		Vertex nowvertex = primQueue.top();
		primQueue.pop();

		if (vertexDealed[nowvertex.vertex])
		{
			continue;
		}

		gotNum++;
		smallestCost += nowvertex.cost;
		vertexDealed[nowvertex.vertex] = true;

		for (int i = AlVertex[nowvertex.vertex]; i != AL_END; i = edge[i].next)
		{
			if (!vertexDealed[edge[i].vertex])
			{
				nowvertex.cost = edge[i].cost;
				nowvertex.vertex = edge[i].vertex;
				primQueue.push(nowvertex);
			}
		}
	}
}

int main()
{
	AlGraph test;
	
	test.prim();

	cout << "The smallest cost is: " << test.smallestCost << endl;

	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值