图——最小生成树

“test.cpp”

#include<iostream>
using namespace std;
#include<vector>
#include<string>
#include<assert.h>
#include "Heap.h"
#include "UnionFindFet.h"

template<class V,class W>
class GraphLink
{
public:
	struct Node
	{
		W _w;
		size_t _src;
		size_t _dst;
		Node* _next;

		Node(size_t src,size_t dst,const W& w)
			:_src(src)
			,_dst(dst)
			,_w(w)
			,_next(NULL)
		{}
	};
	GraphLink(V* vertexs,size_t size,bool isDirected = false)
		:_vertexs(vertexs,vertexs+size)
		,_isDirected(isDirected)
	{
		_table.resize(size);
	}
	GraphLink(bool isDirected)
		:_isDirected(isDirected)
	{}
public:
	void AddEdge(const V& src,const V& dst,const W& w)
	{
		size_t newsrc = _GetIndex(src);
		size_t newdst = _GetIndex(dst);

		if(_isDirected)
			_AddEdge(newsrc,newdst,w);
		else
		{
			_AddEdge(newsrc,newdst,w);
			_AddEdge(newdst,newsrc,w);
		}
	}
	void Display()
	{
		for(size_t i = 0;i < _vertexs.size();++i)
		{
			cout<<_vertexs[i]<<"["<<i<<"]->";
			Node* cur = _table[i];
			while(cur)
			{
				cout<<cur->_w<<"["<<cur->_dst<<"]->";
				cur = cur->_next;
			}
			cout<<"NULL"<<endl;
		}
	}
	//克鲁斯卡尔算法
	bool Kruskal(GraphLink<V,W>& mintree)
	{
		assert(_isDirected == false);
		mintree._vertexs = _vertexs;
		mintree._isDirected = _isDirected;
		mintree._table.resize(_vertexs.size());

		//仿函数,用权值来对堆进行建小堆
		struct Compare
		{
			bool operator()(Node* L,Node* R)
			{
				return L->_w < R->_w;
			}
		};

		Heap<Node*,Compare> minheap;
		for (size_t i = 0;i < _table.size();i++)
		{
			Node* cur = _table[i];
			while (cur)
			{
				//对无向图进行过滤,不让相同的边重复进入
				if (cur->_src < cur->_dst)
				{
					minheap.Push(cur);
				}
				
				cur = cur->_next;
			}
		}

		size_t n = 0;
		//使用并查集高效的判断是否成环
		UnionSet ufs(_vertexs.size());

		while (n < (_vertexs.size() - 1))
		{
			if(minheap.Empty())
				return false;

			Node* edge = minheap.Top();
			minheap.Pop();

			int root1 = ufs.FindRoot(edge->_src);
			int root2 = ufs.FindRoot(edge->_dst);

			if (root1 != root2)
			{
				ufs.UnionSetFrient(root1,root2);
				mintree._AddEdge(edge->_src,edge->_dst,edge->_w);
				++n;
			}
		}
		//打印最小生成树的顶点之间的边
		mintree._KruskalDisplay();
		return true;
	}
private:
	void _KruskalDisplay()
	{
		for (size_t i = 0;i < _table.size();++i)
		{
			Node* cur = _table[i];

			while (cur)
			{
				cout<<cur->_src<<"--"<<cur->_dst<<",";
				cur = cur->_next;
			}
		}
	}
	void _AddEdge(size_t src,size_t dst,const W& w)
	{
		Node* tmp = new Node(src,dst,w);

		tmp->_next = _table[src];
		_table[src] = tmp;
	}
	size_t _GetIndex(const V& v)
	{
		for(size_t i = 0;i < _vertexs.size();++i)
			if(_vertexs[i] == v)
				return i;

		assert(false);
	}
private:
	vector<V> _vertexs;
	vector<Node*> _table;
	bool _isDirected;
};

void test()
{
	string arr[] = {"A","B","C","D","E"};
	int size = sizeof(arr)/sizeof(arr[0]);

	GraphLink<string,int> gl(arr,size);
	gl.AddEdge("A","D",10);
	gl.AddEdge("D","B",20);
	gl.AddEdge("B","C",10);
	gl.AddEdge("C","E",40);
	gl.AddEdge("E","B",30);
	gl.AddEdge("E","A",20);
	gl.Display();

	GraphLink<string,int> g2(false);
	//最小生成树
	gl.Kruskal(g2);
}

int main()
{
	test();
	system("pause");
	return 0;
}

“Heap.h”

#pragma once  
#include <vector>  
#include <assert.h>  

template<class T>  
struct Less  
{  
	bool operator()(const T& left,const T& Right)  
	{  
		return left < Right;  
	}  
};  

template<class T>  
struct Greater  
{  
	bool operator()(const T& left,const T& Right)  
	{  
		return left > Right;  
	}  
};  

template<class T,class Compare = Greater<T>>//缺省值给大堆  
class Heap  
{  
public:  
	Heap(){}
	Heap(const T* arr,const size_t size)  
	{  
		for (int i = 0;i < size;i++)  
		{  
			_arr.push_back(arr[i]);  
		}  

		//建堆  
		for (int i = (_arr.size() - 2) / 2;i >= 0;i--)  
		{  
			//寻找非叶子结点,向下调整;  
			AdjustDown(i);  
		}  
	}  
	void Push(const T& data)  
	{  
		_arr.push_back(data);  
		AdjustUp(_arr.size()-1);  
	}  
	void Pop()  
	{  
		assert(_arr.empty() != true);  
		swap(_arr[0],_arr[_arr.size()-1]);  
		_arr.pop_back();  
		AdjustDown(0);  
	}  
	T Top()  
	{  
		return _arr[0];  
	}  
	bool Empty()  
	{  
		return _arr.empty();  
	}  
	int Size()  
	{  
		return _arr.size();  
	}  
	void Cout()  
	{  
		for (int i = 0; i < _arr.size();i++)  
		{  
			cout<<_arr[i]<<" ";  
		}  
		cout<<endl;  
	}  
private:  
	void AdjustDown(int parent)  
	{  
		int child = 2 * parent + 1;//左孩子  
		Compare com;  
		while (child < _arr.size())  
		{  
			if (((child+1) < _arr.size())&&(com(_arr[child + 1],_arr[child])))  
			{  
				++child;  
			}  
			if (com(_arr[child],_arr[parent]))  
			{  
				swap(_arr[child],_arr[parent]);  
				parent = child;  
				child = parent * 2 + 1;  
			}   
			else  
			{  
				break;  
			}  
		}  
	}  
	void AdjustUp(int child)  
	{  
		int parent = (child - 1) / 2;  
		Compare com;  
		while (child > 0)  
		{  
			if (com(_arr[child],_arr[parent]))  
			{  
				swap(_arr[child],_arr[parent]);  
				child = parent;  
				parent = (child - 1) / 2;  
			}   
			else  
			{  
				break;  
			}  
		}  
	}  
private:  
	vector<T> _arr;  
};  

“UnionFindSet.h”

#pragma once
#include<vector>

class UnionSet
{
public:
	UnionSet(int n)
		:_n(n)
	{
		_set.resize(n+1,-1);
		for(size_t i = 0;i < _set.size();++i)
		{
			_set[i] = -1;
		}
	}

	void UnionSetFrient(int root1,int root2)
	{
		int newroot1 = FindRoot(root1);
		int newroot2 = FindRoot(root2);

		if(newroot1 != newroot2)
		{
			_set[newroot1] += _set[newroot2];
			_set[newroot2] = newroot1;
		}
	}

	int Count()
	{
		int count = 0;
		for(size_t i = 0;i < _set.size();++i)
		{
			if(_set[i] < 0)
				++count;
		}

		//初始化时0位置的下标为-1,0位置下标不参与计算
		return (count - 1);
	}
	int FindRoot(int x)
	{
		if(_set[x] >= 0)//不是根
		{
			x = _set[x];
		}

		return x;
	}
private:
	//int* _set;
	vector<int> _set;
	int _n;
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值