最小生成樹算法——kruskal

如圖,輸出最小生成樹的生成過程

在這裏插入圖片描述

算法思想:

  1. 每個邊的權值進行從小到大排序
  2. 然後從小到大添加到最小生成樹中,若添加一個邊後構成環路,則此邊不能添加。直到每個頂點都加入到最小生成樹中。
  3. 需要一個結構體來存儲 每個邊的權值與始末頂點。再進行排序。
struct 
{
	VexType head;
	VexType tail;
	ArcType lowcost;
}Edge[MAXSIZE];  //存入每條邊的首尾以及權值

通過無向圖寫出鄰接矩陣,調用函數創建鄰接矩陣

在這裏插入圖片描述

VexType vexs[7] = {'0','1','2','3','4','5','6'};
ArcType arcs[7][7] = {{0,17,MAXNUM,MAXNUM,MAXNUM,10,MAXNUM},
					  {17,0,16,MAXNUM,MAXNUM,MAXNUM,14},
					  {MAXNUM,16,0,12,MAXNUM,MAXNUM,MAXNUM},
					  {MAXNUM,MAXNUM,12,0,19,MAXNUM,18},
					  {MAXNUM,MAXNUM,MAXNUM,19,0,25,24},
					  {10,MAXNUM,MAXNUM,MAXNUM,25,0,MAXNUM},
				      {MAXNUM,14,MAXNUM,18,24,MAXNUM,0}};
CreateMGraph(G,vexs,arcs,7); //建表

克魯斯卡爾圖表法

在這裏插入圖片描述

代碼

#ifndef _MGraph_H_
#define _MGraph_H_

#include <iostream>
using namespace std;

#define OK 1
#define ERROR -1
#define OVERFLOW -2
#define MAXSIZE 100
#define MAXNUM 99999 //無窮大

typedef int Status;
typedef char VexType;
typedef int ArcType;
typedef struct
{
	VexType Vexs[MAXSIZE];  //點表
	ArcType Arcs[MAXSIZE][MAXSIZE];  //邊表
	int Vexnum;  //頂點個數
	int Arcnum;  //邊數
}MGraph;

Status initMGraph(MGraph &G)
{
	G.Vexnum = G.Arcnum = 0;
	return OK;
}

Status CreateMGraph(MGraph &G,VexType vexs[],ArcType arcs[][7],int n) //n爲頂點個數
{
	for (int i = 0; i < n; i++)
		G.Vexs[i] = vexs[i];
	G.Vexnum = n;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
		{	
			if (arcs[i][j] != 0 && arcs[i][j] != MAXNUM)
				G.Arcnum++;  //對於無向圖 除以二即可
			G.Arcs[i][j] = arcs[i][j];
		}
	return OK;
}

Status LocateVex(MGraph G,VexType e)
{
	for (int i = 0; i < G.Vexnum; i++)
		if (G.Vexs[i] == e)
			return i;
	return -1;
}

struct 
{
	VexType head;
	VexType tail;
	ArcType lowcost;
}Edge[MAXSIZE];  //存入每條邊的首尾以及權值

int Vexset[MAXSIZE]; //每個頂點所屬的連通分量的編號

void CreateEdge(MGraph G)
{
	int k = 0;  //Edge數組的下標
	for (int i = 0; i < G.Vexnum; i++)
		for (int j = i; j < G.Vexnum; j++)  //無向圖只需在上三角遍歷即可
			if (G.Arcs[i][j] != 0 && G.Arcs[i][j] != MAXNUM)
			{	
				Edge[k].head = G.Vexs[i];
				Edge[k].tail = G.Vexs[j];
				Edge[k].lowcost = G.Arcs[i][j];
				k++;  //最終k的值爲G.Arcnum / 2;
			}
}

void Sort(MGraph G) //直接插入排序
{
	CreateEdge(G);
	int i, j;
	for (int i = 1; i < G.Arcnum / 2; i++)
	{
		if (Edge[i].lowcost < Edge[i - 1].lowcost)
		{
			VexType head = Edge[i].head;
			VexType tail = Edge[i].tail;
			ArcType lowcost = Edge[i].lowcost;
			for (j = i - 1; lowcost < Edge[j].lowcost; j--)
				Edge[j + 1] = Edge[j];
			Edge[j + 1].head = head;
			Edge[j + 1].tail = tail;
			Edge[j + 1].lowcost = lowcost;
		}
	}
}
void Kruskal(MGraph G)  //核心算法
{
	Sort(G); //選出Edge中的一個最小邊
	for (int i = 0; i < G.Vexnum; i++) //初始化每個頂點爲一個連通分量
		Vexset[i] = i;  
	for (int i = 0; i < G.Arcnum / 2; i++)
	{
		int v1 = LocateVex(G,Edge[i].head);
		int v2 = LocateVex(G,Edge[i].tail);
		int vs1 = Vexset[v1];
		int vs2 = Vexset[v2];
		if (vs1 != vs2)  //說明兩者不會構成環路,加入到最小生成樹
		{
			cout << Edge[i].head << "," << Edge[i].tail << " "<<endl;  //輸出邊
			for (int j = 0; j < G.Vexnum; j++)  
				if (Vexset[j] == vs2) Vexset[j] = vs1;  //將連通分量vs2的改爲vs1
		}
	}
}

#endif

結果

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章