Kruskal最小生成树(最小堆 + 并查集)

伪代码
在这里插入图片描述

邻接表储存MST

/*图的邻接表结构定义*/
typedef struct ENode{
	int v1, v2;
	int Weight;
} * Edge;
struct AdjVNode{
	int AdjV;
	int Weight;
	AdjVNode *Next;
};
typedef struct VNode{
	AdjVNode *EdgeFirst;
	string Data;
} AdjList[MaxV];
typedef struct LGNode{
	int Nv, Ne;
	AdjList L;
	int Data;
} * LGraph;
LGraph CreateGraph(int Nv)
{
	LGraph G = new LGNode();
	G->Nv = Nv;
	return G;
}
void InsertEdge(LGraph G, Edge E)
{
	AdjVNode *A = new AdjVNode;
	A->AdjV = E->v2; A->Weight = E->Weight;
	A->Next = G->L[E->v1].EdgeFirst;
	G->L[E->v1].EdgeFirst = A;

	A = new AdjVNode;
	A->AdjV = E->v1; A->Weight = E->Weight;
	A->Next = G->L[E->v2].EdgeFirst;
	G->L[E->v2].EdgeFirst = A;
}
void PrintMST(LGraph MST)
{
	AdjVNode *A;
	for (int i = 0; i < MST->Nv; i++)
	{
		A = MST->L[i].EdgeFirst;
		cout << i << "->";
		while (A)
		{
			cout << A->AdjV << "->";
			A = A->Next;
		}
		cout << "NULL" << endl;
	}
}
void DeleteGraph(LGraph MST)
{
	AdjVNode *A;
	for (int i = 0; i < MST->Nv; i++)
	{
		while (MST->L[i].EdgeFirst)
		{
			A = MST->L[i].EdgeFirst;
			MST->L[i].EdgeFirst = A->Next;
			delete A;
		}
	}
	delete MST;
}

最小堆及其操作

/*最小优先队列*/
typedef struct MinHeapNode{
	Edge *Data;		//最小堆存的数据是边
	int Size;
	int Capacity;
} * MinHeap;
MinHeap CreateMinHeap(int MaxSize)
{
	MinHeap H = new MinHeapNode;
	H->Size = 0;
	H->Capacity = MaxSize;
	H->Data = new Edge[MaxSize + 1];
	H->Data[0] = new ENode;
	H->Data[0]->Weight = -1;
	return H;
}
void InsertMinHeap(MinHeap H, Edge E)
{
	if(H->Size == H->Capacity)
		return;
	Edge AddE = new ENode;
	AddE->Weight = E->Weight;
	AddE->v1 = E->v1;
	AddE->v2 = E->v2;
	int x = AddE->Weight;
	int child;
	for (child = ++H->Size; x < H->Data[child / 2]->Weight; child /= 2)
		H->Data[child] = H->Data[child / 2];
	H->Data[child] = AddE;
}
Edge DeleteMinHeap(MinHeap H)
{
	if(H->Size == 0)
		return H->Data[0];
	Edge DelE = H->Data[1];
	int x = H->Data[H->Size--]->Weight;
	int parent, child;
	for ( parent = 1; parent * 2 <= H->Size; parent = child )
	{
		child = 2 * parent;
		if(H->Data[child + 1]->Weight < H->Data[child]->Weight && child != H->Size)
			child++;
		if(x > H->Data[child]->Weight)
			H->Data[parent] = H->Data[child];
		else
			break;
	}
	H->Data[parent] = H->Data[H->Size + 1];
	return DelE;
}
void DeleteHeap(MinHeap H)
{
	for (int i = 0; i <= H->Size; i++)
		delete H->Data[i];
	delete[] H->Data;
	delete H;
}

Find + Union

int FindSet(int Set[], int v)
{
	if(Set[v] < 0)
		return v;
	else
		return FindSet(Set, Set[v]);
}
void UnionSet(int Set[], int R1, int R2)	//合并集合
{
	if(Set[R1] < Set[R2])	//R1集合更多
	{
		Set[R1] += Set[R2];
		Set[R2] = R1;
	}
	else
	{
		Set[R2] += Set[R1];
		Set[R1] = R2;
	}
}

Kruskal算法

LGraph Kruskal()
{
	int Nv, Ne;
	cin >> Nv >> Ne;
	LGraph MST = CreateGraph(Nv);
	MinHeap H = CreateMinHeap(Ne);
	Edge E = new ENode;
	for (int i = 0; i < Ne; i++)
	{
		cin >> E->v1 >> E->v2 >> E->Weight;
		InsertMinHeap(H, E);
	}
	delete E;
	int *Set = new int[Nv];
	memset(Set, -1, Nv * sizeof(int));

	Edge MinE;
	while (MST->Ne < MST->Nv - 1)	//相等时,刚好所有顶点都加入生成树
	{
		MinE = DeleteMinHeap(H);
		int R1 = FindSet(Set, MinE->v1);
		int R2 = FindSet(Set, MinE->v2);
		if(R1 != R2)
		{
			UnionSet(Set, R1, R2);
			InsertEdge(MST, MinE);
			MST->Ne++;
			MST->Data += MinE->Weight;
			delete MinE;
		}
	}
	delete[] Set;
	DeleteHeap(H);
	return MST;
}

int main()
{
	LGraph MST = Kruskal();
	PrintMST(MST);
	cout << MST->Data << endl;
	DeleteGraph(MST);
	system("pause");
	return 0;
}

程序运行

input:
10 17
0 2 5
0 1 8
1 4 5
1 2 5
1 5 4
4 5 4
2 3 8
2 6 4
5 6 4
5 8 2
3 6 7
6 8 3
3 7 5
6 7 5
6 9 6
8 9 7
7 9 6
output:
0->2->NULL
1->5->NULL
2->0->6->NULL
3->7->NULL
4->5->NULL
5->4->1->8->NULL
6->7->2->8->NULL
7->9->6->3->NULL
8->6->5->NULL
9->7->NULL
38
请按任意键继续. . .

完整代码

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int MaxV = 100;

/*图的邻接表结构定义*/
typedef struct ENode{
	int v1, v2;
	int Weight;
} * Edge;
struct AdjVNode{
	int AdjV;
	int Weight;
	AdjVNode *Next;
};
typedef struct VNode{
	AdjVNode *EdgeFirst;
	string Data;
} AdjList[MaxV];
typedef struct LGNode{
	int Nv, Ne;
	AdjList L;
	int Data;
} * LGraph;
LGraph CreateGraph(int Nv)
{
	LGraph G = new LGNode();
	G->Nv = Nv;
	return G;
}
void InsertEdge(LGraph G, Edge E)
{
	AdjVNode *A = new AdjVNode;
	A->AdjV = E->v2; A->Weight = E->Weight;
	A->Next = G->L[E->v1].EdgeFirst;
	G->L[E->v1].EdgeFirst = A;

	A = new AdjVNode;
	A->AdjV = E->v1; A->Weight = E->Weight;
	A->Next = G->L[E->v2].EdgeFirst;
	G->L[E->v2].EdgeFirst = A;
}
void PrintMST(LGraph MST)
{
	AdjVNode *A;
	for (int i = 0; i < MST->Nv; i++)
	{
		A = MST->L[i].EdgeFirst;
		cout << i << "->";
		while (A)
		{
			cout << A->AdjV << "->";
			A = A->Next;
		}
		cout << "NULL" << endl;
	}
}
void DeleteGraph(LGraph MST)
{
	AdjVNode *A;
	for (int i = 0; i < MST->Nv; i++)
	{
		while (MST->L[i].EdgeFirst)
		{
			A = MST->L[i].EdgeFirst;
			MST->L[i].EdgeFirst = A->Next;
			delete A;
		}
	}
	delete MST;
}
/*最小优先队列*/
typedef struct MinHeapNode{
	Edge *Data;		//最小堆存的数据是边
	int Size;
	int Capacity;
} * MinHeap;
MinHeap CreateMinHeap(int MaxSize)
{
	MinHeap H = new MinHeapNode;
	H->Size = 0;
	H->Capacity = MaxSize;
	H->Data = new Edge[MaxSize + 1];
	H->Data[0] = new ENode;
	H->Data[0]->Weight = -1;
	return H;
}
void InsertMinHeap(MinHeap H, Edge E)
{
	if(H->Size == H->Capacity)
		return;
	Edge AddE = new ENode;
	AddE->Weight = E->Weight;
	AddE->v1 = E->v1;
	AddE->v2 = E->v2;
	int x = AddE->Weight;
	int child;
	for (child = ++H->Size; x < H->Data[child / 2]->Weight; child /= 2)
		H->Data[child] = H->Data[child / 2];
	H->Data[child] = AddE;
}
Edge DeleteMinHeap(MinHeap H)
{
	if(H->Size == 0)
		return H->Data[0];
	Edge DelE = H->Data[1];
	int x = H->Data[H->Size--]->Weight;
	int parent, child;
	for ( parent = 1; parent * 2 <= H->Size; parent = child )
	{
		child = 2 * parent;
		if(H->Data[child + 1]->Weight < H->Data[child]->Weight && child != H->Size)
			child++;
		if(x > H->Data[child]->Weight)
			H->Data[parent] = H->Data[child];
		else
			break;
	}
	H->Data[parent] = H->Data[H->Size + 1];
	return DelE;
}
void DeleteHeap(MinHeap H)
{
	for (int i = 0; i <= H->Size; i++)
		delete H->Data[i];
	delete[] H->Data;
	delete H;
}
int FindSet(int Set[], int v)
{
	if(Set[v] < 0)
		return v;
	else
		return FindSet(Set, Set[v]);
}
void UnionSet(int Set[], int R1, int R2)	//合并集合
{
	if(Set[R1] < Set[R2])	//R1集合更多
	{
		Set[R1] += Set[R2];
		Set[R2] = R1;
	}
	else
	{
		Set[R2] += Set[R1];
		Set[R1] = R2;
	}
}

LGraph Kruskal()
{
	int Nv, Ne;
	cin >> Nv >> Ne;
	LGraph MST = CreateGraph(Nv);
	MinHeap H = CreateMinHeap(Ne);
	Edge E = new ENode;
	for (int i = 0; i < Ne; i++)
	{
		cin >> E->v1 >> E->v2 >> E->Weight;
		InsertMinHeap(H, E);
	}
	delete E;
	int *Set = new int[Nv];
	memset(Set, -1, Nv * sizeof(int));

	Edge MinE;
	while (MST->Ne < MST->Nv - 1)	//相等时,刚好所有顶点都加入生成树
	{
		MinE = DeleteMinHeap(H);
		int R1 = FindSet(Set, MinE->v1);
		int R2 = FindSet(Set, MinE->v2);
		if(R1 != R2)
		{
			UnionSet(Set, R1, R2);
			InsertEdge(MST, MinE);
			MST->Ne++;
			MST->Data += MinE->Weight;
			delete MinE;
		}
	}
	delete[] Set;
	DeleteHeap(H);
	return MST;
}

int main()
{
	LGraph MST = Kruskal();
	PrintMST(MST);
	cout << MST->Data << endl;
	DeleteGraph(MST);
	system("pause");
	return 0;
}

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值