最小生成樹問題學習總結

kruskal算法思想:

對圖中的所有邊按升序排列,依次檢驗圖中的權值最小的邊,若此邊加入後不形成迴路,則選取此邊加入生成樹,直至選取n-1條邊。

算法實現:

對圖的信息中所需數據元素只有邊的兩端頂點及權值,選取的生成樹的邊存儲結構與之相同。

是否形成迴路的判斷需要用到待選邊表,這裏用vset數組,若兩頂點在同一集合中(vset[i]==vset[j]),則不能選取邊L<i,j>,不然會形成迴路。

這裏推薦MOOC中國大學網上的--解放軍理工大學的數據結構課程,講解特別詳細。

#include <iostream>
#include <algorithm>
using namespace std;
struct linknode
{
	int vex1,vex2;
	int weight;
};
struct elgraph
{
	int vexnum,edgenum;
};
linknode *kruskal_MST(elgraph *G)
{
	linknode *edgelist=new linknode[G->edgenum];//這裏是輸入G圖中的都有邊
	for(int i=0;i<G->edgenum;i++)
		cin>>edgelist[i].vex1>>edgelist[i].vex2>>edgelist[i].weight;
	linknode *TE=new linknode[G->vexnum-1];//TE數組存放最小生成樹的邊
	int j,k,v,s1,s2;
	int *vset=new int[G->vexnum];//用待選邊表vset來判斷是否形成迴路
	int w;
	for(j=0;j<G->vexnum;j++)//vset初始化
		vset[j]=j;
	sort(edgelist[0],edgelist[G->edgenum+1]);//按照權值大小給圖中的邊排序
	j=0;k=0;//k表示遍歷的頂點數,j表示遍歷的邊的數目
	while(k<G->vexnum-1&&j<G->edgenum)
	{
		s1=vset[edgelist[j].vex1];
		s2=vset[edgelist[j].vex2];
		if(s1!=s2)//生成樹中加入邊L<s1,s2>後不會生成迴路
		{
			TE[k].vex1=edgelist[j].vex1;//加入此邊
			TE[k].vex2=edgelist[j].vex2;
			TE[k].weight=edgelist[j].weight;
			k++;
			for(v=0;v<G->vexnum;v++)//修改待選邊表
				if(vset[v]==s2) vset[v]=s1;
		}
		j++;
	}
	return TE;
}

prim算法

//最小生成樹之prim算法
#include <iostream>
using namespace std;
const int  M=100;
struct edgenode
{
	int incrvert,vertex;
	int weight;
};
void prim(int G[M][M],int n)
{
	int v,i,j,k;
	edgenode t,wait[M-1];//wait爲待選邊表
	for(v=0;v<n-1;n++)//以數組標號0的頂點爲初始生長點初始化待選邊表
	{
		wait[v].incrvert=0;
		wait[v].vertex=v+1;
		wait[v].weight=G[0][v+1];
	}
	for(i=0;i<n-2;i++)
	{
		k=i;
		for(j=i+1;j<n-1;j++)
		{
			if(wait[j].weight<wait[k].weight)
			k=j;
			t=wait[k];
			wait[k]=wait[i];
			wait[i]=t;
			v=wait[i].vertex;
			for(j=i+1;j<n-1;j++)
				if(wait[j].weight>G[v][wait[j].vertex])
				{
					wait[j].weight=G[v][wait[j].vertex];
					wait[j].incrvert=v;
				}
		}
		for(i=0;i<n-1;i++)
		cout<<wait[i].vertex<<wait[i].incrvert<<wait[i].weight;	     

}


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