最小生成樹-Prim演算法和Kruskal演算法

yinghualeihenmei發表於2024-03-28

原文連結:https://blog.csdn.net/lsgo_myp/article/details/91435589

Prim演算法

加點法

1.演算法簡單描述

1).輸入:一個加權連通圖,其中頂點集合為V,邊集合為E;

2).初始化:Vnew = {x},其中x為集合V中的任一節點(起始點),Enew = {},為空;

3).重複下列操作,直到Vnew = V:

a.在集合E中選取權值最小的邊<u, v>,其中u為集合Vnew中的元素,而v不在Vnew集合當中,並且v∈V(如果存在有多條滿足前述條件即具有相同權值的邊,則可任意選取其中之一);

b.將v加入集合Vnew中,將<u, v>邊加入集合Enew中;

4).輸出:使用集合Vnew和Enew來描述所得到的最小生成樹。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace ConsoleApp1
{
    class Program
    {
        //結點初始狀態
        static int N = -1;
        //結點已加入狀態
        static int Y = 1;
        static void Main(string[] args)
        {           
            //起始點  頂點以0開始 A頂點為0,B為1
            int start = 3;
            //無向圖鄰接矩陣
            int[,] map = new int[7, 7] {
                {0,7,N,5,N,N,N }, //A頂點的邊
                {7,0,8,9,7,N,N }, //B頂點的邊
                {N,8,0,N,5,N,N }, //C頂點的邊
                {5,9,N,0,N,6,N }, //D頂點的邊
                {N,7,5,N,0,8,9 }, //E 頂點的邊
                {N,N,N,6,8,0,11 }, //F 頂點的邊
                {N,N,N,N,9,11,0 },  //G頂點的邊
            };

  

	     
            //已選的點集合
            int[] vNew = new int[map.GetLength(0)];
            //置為初始狀態 ,此時未加入任何結點
            for (int i = 0; i < vNew.Length; i++)
            {
                //N代表為加入結點
                vNew[i] = N;
            }
            //加入初始結點
            vNew[start] = Y;
 
            int len = GetMST(vNew, map);
 
            Console.WriteLine("最小生成樹權值為:"+len);
            Console.ReadKey();
        }
 
        /// <summary>
        ///   普里姆演算法
        /// </summary>
        /// <param name="vNew">已加入的結點,初始值需設定</param>
        /// <param name="map">無向圖的鄰接矩陣</param>
        /// <returns></returns>
        private static int GetMST(int[] vNew,int[,]map)
        {
            //找出vNew點中與未選擇的邊組成的最小值
            int length = 0;
            while(vNew.Count(temp=>temp==Y)<map.GetLength(0))
            {
                int minLength = int.MaxValue;
                int minNewNode = N;
                int minStartNode = N;
                for (int i = 0; i < vNew.Length; i++)
                {
                    if (vNew[i] == Y)
                    {
                        for (int j = 0; j < map.GetLength(1); j++)
                        {
                            //未選擇的結點已vNew中的結點組成的邊
                            if (vNew[j] == N)
                            {
                                if (map[i, j] != N)
                                {
                                   
 
                                    if (map[i, j] < minLength)
                                    {
                                       // Console.WriteLine("邊{0}{1}", i, j);
                                        minLength = map[i, j];
 
                                        minNewNode = j;
                                        minStartNode = i;
                                    }
 
                                }
 
                            }
                        }
                    }
 
                }
                if (minNewNode==N)
                {

  

		    //此處圖的鄰接矩陣資料不正確
                    throw new Exception("圖的鄰接矩陣資料不正確");
                }
                else
                {
                    vNew[minNewNode] = Y;
                    Console.WriteLine("頂點{0}加入", ConvertToChar( minNewNode));
                    Console.WriteLine("邊{0}--{1}加入", ConvertToChar(minStartNode), ConvertToChar(minNewNode));
                    length += minLength;
                }
            }
            return length;
        }
 
        /// <summary>
        /// 轉換成字元,方便檢視
        /// </summary>
        /// <param name="charValue"></param>
        /// <returns></returns>
        private static char ConvertToChar(int charValue)
        {
 
            int k = charValue + 65;
            return (char)k;
        }
    }
}

  

Kruskal演算法

加邊法

相關文章