Kruskal算法和prim算法的C++简单实现

本文深入探讨了图论中的两种最小生成树算法——Kruskal算法与Prim算法。Kruskal算法通过贪心策略,按边的权重从小到大选择不形成环的边,构造最小生成树。Prim算法则从任意一点开始,逐步将未加入的最轻边纳入,最终形成最小生成树。文章提供了详细的算法实现与代码示例。

 模仿算法导论P366 和 P 367 简单实现的一个Kruskal算法和prim算法。

图的模型使用的是无向图,仅标注两点和之间的权重,prim算法处理起来还是邻接矩阵方便。

Kruskal算法的基本原理:利用贪心思想,依次选择权重最小的边插入不相交集合中,不是一个森林的则合并,可得最小生成树。

时间复杂度:O(ElgV)   E:边的数量  V:节点数量     使用的数据结构 ‘不相交集合‘在P329页。

P368 prim算法的简单实现:

prim算法:同样利用贪心思想,集合A中保存最小生成树的点。 每次寻找除集合A外的结点且和集合A中某个点相连的轻量边,加入A。

时间复杂度: 利用二叉最小优先队列,同上。

代码过程:

1.建立一个包含自身节点变量、父节点变量、父节点和自己之间的权重的结构。

2.选择首节点,令其结构中权重为0,父节点为空,值为自己的节点变量。

其他节点的父节点为空,值为自己的节点变量,权重为无穷大。

3.针对权重建立起始最小堆。

3.循环这个队列:首先取出堆顶,然后找这个堆顶节点的邻接点,邻接点若不在A中在堆中且权重大于堆顶结点到它的权重,修改该节点的权重和父亲,重新建造堆。 往复循环。

4.输出结果。

Kruskal:

#include <bits/stdc++.h>
//#include <unordered_map>
using namespace std;
class solution
{
	typedef struct treeset
	{
		char key;
		int rank;
		treeset* parent;
		treeset (char x):key(x),rank(0), parent(NULL){};

	}treeset;
	treeset* make_set (char x)
	{
		treeset* ts = new treeset (x);
		ts->parent = ts;
		return ts;
	}
	treeset* find_set (treeset* x)
	{
		if (x->parent!=x)
		{
			x->parent = find_set (x->parent);
		}
		return x->parent;
	}
	void link (treeset* x, treeset* y)
	{
		if (x->rank>y->rank)
		{
			y->parent = x;
		}
		else
		{
			x->parent = y;
			if (x->rank==y->rank)
			{
				y->rank += 1;
			}
		}
	}
	void ubion (treeset* x, treeset* y)
	{
		link (find_set(x), find_set(y));
	}
public:
	vector<pair<pair<char, char>, int>> jihe (vector<pair<pair<char, char>, int>>& pro)
	{
		vector<pair<pair<char, char>, int>> tem; //A
		map<char, treeset*> mm;
		for (char i = 'a'; i < 'j'; i++)
		{
			mm[i] = make_set (i);
		}
		std::sort (pro.begin (), pro.end (), [](pair<pair<char, char>, int>& x, pair<pair<char, char>, int>& y)->bool { return x.second< y.second; });
		int a = 1;
		for (size_t i = 0; i < pro.size(); i++)
		{
			if (find_set(mm[pro[i].first.first]) != find_set (mm[pro[i].first.second]))
			{
				tem.push_back (pro[i]);
				ubion (mm[pro[i].first.first], mm[pro[i].first.second]);
			}
		}
		return tem;
	}
};

prim算法:

template<class T1>
class solution
{
	
	typedef struct jiebian
	{
		jiebian* m_parent;
		int m_key;
		T1 m_self;
		jiebian (T1 self) :m_key(INT_MAX),m_self(self),m_parent(nullptr){};
		jiebian (T1 self,int key) :m_key (key), m_self (self), m_parent (nullptr) {};
	}jiebian;

	void make_min_heap (deque<jiebian*>& d)
	{
		int len = d.size ();
		for (int i = len / 2; i >=0; --i)
		{
			this->make_min_heapfy (d, i);
		}
	}
	void make_min_heapfy (deque<jiebian*>& d,int n )
	{
		int l = (n+1) * 2 - 1;
		int r = (n + 1) * 2;
		int minest = n;
		int heapsize = d.size ();
		minest = l < int(d.size ()) && d[l]->m_key < d[n]->m_key ? l : n;
		minest = r < int(d.size ()) && d[r]->m_key < d[minest]->m_key ? r : minest;
		while (minest != n)
		{
			swap (d[n], d[minest]); //注意变量之间的关系
			n = minest;
			l = 2 * minest + 1;
			r = 2 * (minest + 1);
			minest = l < heapsize && d[l]->m_key < d[n]->m_key ? l : minest;
			minest = r < heapsize && d[r]->m_key < d[minest]->m_key ? r : minest;
		}
	}
	void insert(deque<jiebian*>& d, jiebian* key)   ////
	{ 
		d.emplace_back (key);
		decrease_key (d, d.size () - 1);

	}
	jiebian* minimum (deque<jiebian*>& A)
	{
		return A[0];
	}
	jiebian* exart_min (deque<jiebian*>& A)
	{
		if (A.size()<1)
		{
			cout << "error" << endl;
		}
		jiebian* min1 = A.front();
		A[0] = A[A.size () - 1];
		A.pop_back ();
		make_min_heapfy (A, 0);
		return  min1;
	}
	void decrease_key (deque<jiebian*>& A,int n)
	{
		while (n>=0 && A[(n+1)/2-1]>A[n])
		{
			swap (A[(n + 1) / 2 - 1], A[n]);
			n = (n + 1) / 2 - 1;
		}
	}
public:
	void prim (vector<pair<pair<char, char>, int>>& pro)
	{
		deque<jiebian*> duilie;
		map<char, jiebian*> yinshe;
		jiebian* jb1 = new jiebian ('a',0);
		duilie.emplace_back (jb1);
		yinshe['a'] = jb1;
		
		for (char i = 'b'; i < 'j'; i++)
		{
			jiebian* jb = new jiebian (i);
			yinshe[i] = jb;
			duilie.emplace_back (jb);
		}
		this->make_min_heap(duilie);
		
		while (!duilie.empty())
		{
			jiebian* u = this->exart_min (duilie);
			for (size_t i = 0; i < pro.size(); i++)
			{
				auto v = yinshe[pro[i].first.second];
				auto v1 = yinshe[pro[i].first.first];
				if (pro[i].first.first==u->m_self&& find(duilie.begin(),duilie.end(),v)!=duilie.end()) // && v->m_keypro[i].second  && pro[i].second< yinshe[pro[i].first.second]->m_key
				{
					if (v->m_key > pro[i].second)
					{
						v->m_key = pro[i].second;
						v->m_parent = u;
					}
				}
				if (pro[i].first.second == u->m_self && find (duilie.begin (), duilie.end (), v1) != duilie.end ()) // && v->m_keypro[i].second  && pro[i].second< yinshe[pro[i].first.second]->m_key
				{
					if (v1->m_key > pro[i].second)
					{	 
						v1->m_key = pro[i].second;
						v1->m_parent = u;
					}
				}
			}
			make_min_heap (duilie);
		}
		vector<pair<char, jiebian*>> cc1(yinshe.begin(),yinshe.end());
		std::sort (cc1.begin (), cc1.end (), [](pair<char, jiebian*>& x, pair<char, jiebian*>& y)->bool { return x.second->m_key < y.second->m_key; });
		for (size_t i = 0; i <cc1.size(); i++)
		{
			if (cc1[i].second->m_parent!=nullptr)
			{
				cout << cc1[i].second->m_parent->m_self << ' ' << cc1[i].second->m_self <<' '<< cc1[i].second->m_key << endl;;
			}
		}
		return;
	}
};

测试主函数:

int main ()
{
	vector<pair<pair<char,char>,int>> pro
	{
		{{'a','b'},4},
		{{'a','h'},5},
		{{'b','c'},3},
		{{'b','h'},11},
		{{'c','f'},2},
		{{'c','i'},4},
		{{'i','g'},7},
		{{'i','h'},6},
		{{'g','h'},12},
		{{'g','f'},2},
		{{'c','d'},6},
		{{'d','f'},11},
		{{'d','e'},9},
		{{'e','f'},10}
	};
	solution<char> sl;
	cout << "prim 算法输出:" << endl;
	sl.prim (pro);
	cout << "kruskal 算法输出:"<<endl;
	solution1 sl1;
	auto cc = sl1.jihe (pro);
	for (auto& i : cc)
	{
		cout << i.first.first << ' ' << i.first.second << ' ' << i.second << endl;
	}
	
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值