數據結構與算法:最小生成樹算法Krustal(C/C++)

一、算法描述

    1.遍歷圖結構並初始化邊集合

    2.初始化連通分支集合。每個連通分支集合初始化標誌元素指向自己

    3.對邊集合從小到大排序

    4.遍歷邊集合,判斷節點所屬連通分支是否相同。

    5.如果4中判斷的連通分支不相同,輸出這條邊。執行4

 

    說明:這裏採用鄰接矩陣方法儲存圖結構。


二、算法實現

void calculate_in_kruskal(MatGraph*gf)//Calculate minimum spanning tree 
{
	printf("\nKruskal:\n");
	ENode edge[MAXMUM];//Edge set to selete the minimun edge
	int ver[MAXMUM];//Vertex set pointing to the precurser
	int k=0;
	for(int i=0;i<gf->n;i++)//Go through all the elements in matgraph
		for (int j = 0; j < gf->n; j++)
		{
			if (gf->edge[i][j] != -1)//Initialise all the edges in the graph
			{
				edge[k].n1 = i;
				edge[k].n2 = j;
				edge[k++].weight = gf->edge[i][j];
			}
		}
	quicksort(edge,0,k);//Sort the edge set to select the minimum edge
	for (int i = 0; i < gf->n; i++)//Initialise the vertex set and point it to itself
		ver[i] = i;
	int n1,n2;
	for (int k = 0; k < 2*gf->e; k++)//Select the minimum edge in sequence
	{
		n1 = edge[k].n1;//n1 is the precurser of the kth edge
		while (ver[n1] != n1)
			n1 = ver[n1];
		n2 = edge[k].n2;//n2 is the next vertex of the kth edge
		while (ver[n2] != n2)
			n2 = ver[n2];
		if (n1 != n2)//If the kth edge has different vertexs
		{
			ver[n1] = n2;
			printf("<%d,%d,%d>", edge[k].n1, edge[k].n2,edge[k].weight);
		}
	}
}

 

三、算法分析

 

 

   首先分析Krustal算法的基本思路。算法採用貪心法的設計思想,從最小的邊開始,逐步依次選取更大的邊,直到遍歷完成所有的邊。每選一條邊,都要判斷邊的兩個鄰接點是否屬於同一個連通分支,換一句話說,判斷這條邊是否具有切分性質。如果屬於一個連通分支,那麼捨棄這條邊。算法的實現中採用並查集的策略判斷不同節點的集合標誌是否一樣。(算法正確性證明略去)

   下面分析Krustal算法的時間複雜度。由算法描述可知,遍歷鄰接矩陣需要花費O(n^2)的漸進時間複雜度,把這一時間複雜度當做初始化過程不加以考慮。下面對邊集合的排序使用快速排序算法,軸點構造選用三者取中法,因此平均意義下時間複雜度爲O(e*loge)。當然,在這裏的排序算法是任意的,更常用的算法取的是堆排序,因爲堆排序更不容易退化爲O(n^2)的最壞時間複雜度。下面我們遍歷邊集合,需要O(e)的時間複雜度。因此,算法的時間複雜度爲O(e*loge).是一個複雜度僅與邊的數量有關的算法,適合於稀疏圖。

參考文獻

[1]曲婉玲等,算法設計與分析(第2版),2016.2

[2]李春葆,數據結構教程(第5版),2017.5

 

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