C#實現最小生成樹
阿新 • • 發佈:2019-01-06
第一種:
//求最小生成樹,普里姆演算法(Prim)
//先給定一個初始點,然後找到離它最近的點,並加入找的點序列,將其對應的距離設為0
//然後找其它頂點距離新的找到點集合最小的點,再加入找到的點序列
//重複以上過程
public static void Prim_MiniTree(Graph g)
{
//存放找到的點
string[] label_checked = new string[g.nums];
//存放最短距離,是動態變化的,第n個位置記錄的是第n個點到當前點的最短距離
int[] lowest_length = new int[g.nums];
//設定初始點,設定初始點到其他的距離
label_checked[0] = g.ver[0].label;
lowest_length[0] = 0;
for (int j = 1; j < g.nums; j++)
{
lowest_length[j] = g.adjMatrix[0, j];
label_checked[j] = " ";
}
Console.WriteLine(label_checked[0].ToString() + " 0 0");
//迴圈找其他點的最短距離
int sum = 0;
for (int i = 1; i < g.nums; i++)
{
int min = 100000, k = 0;
//先找此點到其他點的最短距離,並記錄下是哪個點
for (int j = 0; j < g.nums; j++)
{
if (lowest_length[j] != 0 && lowest_length[j] < min)
{
min = lowest_length[j];//得到距離向量中的最短值
k = j;//第幾個最短
label_checked[j] = g.ver[j].label;
}
}
//列印節點
sum += min;
Console.WriteLine(label_checked[k].ToString()+" "+k.ToString()+" "+min.ToString());
lowest_length[k] = 0;//代表這個點已經找到了
//再次迴圈,更新其他點到已經找到點距離
for (int j = 1; j < g.nums;j++ )
{
if(lowest_length[j]!=0&&lowest_length[j]>g.adjMatrix[k,j])
{
lowest_length[j]=g.adjMatrix[k,j];//更新值
}
}
}
Console.WriteLine("\n最小生成樹的最短距離為:"+sum.ToString());
}
第二種:克魯斯卡爾演算法:
1.將鄰接矩陣初始化為;起點、終點、邊的型別,並且將其按照邊的由小到大的順序排序;
2.初始化一個一維陣列,下邊表示起點,對應值表示終點,並寫一個用於判斷是否有環的函式,就是根據這個一維陣列,不斷變換起始點,看看是否有環;
3.遍歷邊的集合,滿足時輸出
//返回:起點、終點、權重矩陣
public static int[,] Get_Metrix(Graph g, int nums){
int[,] a = new int[nums, 3];
int index = 0;
for (int i = 0; i < g.nums - 1; i++)
{
for (int j = i; j < g.nums; j++)
{
if (g.adjMatrix[i, j] != 0 && g.adjMatrix[i, j] != 10000)
{
a[index, 0] = i;
a[index, 1] = j;
a[index, 2] = g.adjMatrix[i, j];
index++;
}
}
}
//氣泡排序
for (int i = 0; i < 15; i++)
{
for (int j = 0; j < 15 - 1 - i; j++)
{
if (a[j, 2] > a[j + 1, 2])
{
int tmp = a[j, 2];
a[j, 2] = a[j + 1, 2];
a[j + 1, 2] = tmp;
tmp = a[j, 0];
a[j, 0] = a[j + 1, 0];
a[j + 1, 0] = tmp;
tmp = a[j, 1];
a[j, 1] = a[j + 1, 1];
a[j + 1, 1] = tmp;
}
}
}
return a;
}
public static int Find_YesOrNo_Circle(int[] m, int a)
{
while (m[a] > 0)
{
a = m[a];
}
return a;
}
//克魯斯卡爾(Kruskal)演算法
public static void Kruskal(Graph g, int nums)
{
int[,] Start_End_Weights = Get_Metrix(g, nums);//將鄰接矩陣轉化一下
int[] Labels = new int[g.nums];
for (int i = 0; i < Labels.Length; i++) //賦上初始值
{
Labels[i] = 0;
}
for (int i = 0; i < nums; i++) //遍歷每一條邊
{
int start = Find_YesOrNo_Circle(Labels, Start_End_Weights[i, 0]);//找到這個起點最遠連通到哪個點
int end = Find_YesOrNo_Circle(Labels, Start_End_Weights[i, 1]);//找到這個終點最遠連通到哪個頂點
if (start != end) //若兩個點的終點不同
{
Labels[start] = end; //將其記入標記中
Console.WriteLine(Start_End_Weights[i, 0].ToString() + "-》" + Start_End_Weights[i, 1].ToString() + " : " + Start_End_Weights[i, 2]);
}
}
}