最小生成树K氏法

K氏法

K氏法也叫Kruskal算法,是将各边按照权值从小到大排列,接着从权值最低的边开始建立最小成本生成树,如果加入的边造成了贿赂,则舍弃不用,直到加入n-1个边为止。

示例

                                                

 

        把所有边的成本列出,按照从小到大排列。

起始 终止 成本
B C 3
B D 5
A B 6
C D 7
B F 8
D E 9
A E 10
D F 11
A F 12
E F 16

        1.选择成本最低的一条边作为建立最小成本生成树的起点。

                                B----C   3

        2.按照建立的表格,按序加入边

                                B-----C  3                 B----D 5

        直到完成所有的生成树,结果为:

                              

                代码:                           

    public class Node
    {
        const int MAXLENGTH = 20;   //链表的最大长度
        public int[] from = new int[MAXLENGTH];
        public int[] to = new int[MAXLENGTH];
        public int[] find = new int[MAXLENGTH];
        public int[] val = new int[MAXLENGTH];

        public int[] next = new int[MAXLENGTH];   //链表的一个节点位置

        public Node()
        {
            for(int i = 0; i < MAXLENGTH; i++)
            {
                next[i] = -2;   //-2表示未用节点
            }
        }

        //查找可用节点
        public int FindFree()
        {
            int i;
            for(i = 0; i < MAXLENGTH; i++)
            {
                if (next[i] == -2)
                    break;
            }
            return i;
        }
        //建立链表
        public void Create(int header,int freeNode,int dataNum,int fromNum,int toNum,int findNum)
        {
            int point;   //现在的节点位置
            if (header == freeNode)     //新的链表
            {
                val[header] = dataNum;    //设置数据编号
                from[header] = fromNum;
                find[header] = findNum;
                to[header] = toNum;
                next[header] = -1;    //将下个节点的位置 ,-1表示空节点
            }
            else
            {
                point = header;
                val[freeNode] = dataNum;
                from[freeNode] = fromNum;
                find[freeNode] = findNum;
                to[freeNode] = toNum;

                //设置数据名称
                next[freeNode] = -1;
                //寻找链表的尾端
                while (next[point] != -1)
                {
                    point = next[point];
                }
                //将新节点串联在原链表的尾端
                next[point] = freeNode;
            }
        }

        public void Print(int header)
        {
            int point;
            point = header;
            while (point != -1)
            {
                Console.Write($"起始顶点 [{from[point]}]   终止顶点[");
                Console.Write($"{to[point]} ]   路径长度[{val[point]}]");
                Console.WriteLine();
                point = next[point];
            }
        }
    }

                   

class Program
    {
        static int verts = 6;
        static int[] v = new int[verts + 1];
        static Node newlist = new Node();

        static void Main(string[] args)
        {
            int[,] data = { { 1, 2, 6 }, { 1, 6, 12 }, { 1, 5, 10 }, { 2, 3, 3 }, { 2, 4, 5 }, { 2, 6, 8 }, { 3, 4, 7 }, { 4, 6, 11 }, { 4, 5, 9 }, { 5, 6, 16 } };
            int dataNum;
            int fromNum;
            int toNum;
            int findNum;
            int header = 0;
            int freeNode;
            for(int i = 0; i < 10; i++)
            {
                for(int j = 1; j <= verts; j++)
                {
                    if (data[i, 0] == j)
                    {
                        fromNum = data[i, 0];
                        toNum = data[i, 1];
                        dataNum = data[i, 2];
                        findNum = 0;
                        freeNode = newlist.FindFree();
                        newlist.Create(header, freeNode, dataNum, fromNum, toNum, findNum);
                    }
                }
            }
            newlist.Print(header);
            Console.WriteLine("建立最小成本的生成树:");
            MinTree();

            Console.ReadLine();
        }

        //找出剩下最小的
        static int FindMinCost()
        {
            int minVal = 100;
            int retPtr = 0;
            int a = 0;

            while (newlist.next[a] != -1)
            {
                if (newlist.val[a] < minVal && newlist.find[a] == 0)
                {
                    minVal = newlist.val[a];
                    retPtr = a;
                }
                a++;
            }
            newlist.find[retPtr] = 1;
            return retPtr;
        }

        static void MinTree()
        {
            int result = 0;
            int mcePtr;
            int a = 0;
            for(int i = 0; i <= verts; i++)
            {
                v[i] = 0;
            }
            while (newlist.next[a] != -1)   //next表示的是有几条边
            {
                mcePtr = FindMinCost();
                v[newlist.from[mcePtr]]++;
                v[newlist.to[mcePtr]]++;
                if (v[newlist.from[mcePtr]] > 1 && v[newlist.to[mcePtr]] > 1)
                {
                    v[newlist.from[mcePtr]]--;
                    v[newlist.to[mcePtr]]--;
                    result = 1;
                }
                else
                    result = 0;

                if (result == 0)
                {
                    Console.Write($"起始顶点[{newlist.from[mcePtr]}]  终止顶点[{newlist.to[mcePtr]}]  路径长度[{newlist.val[mcePtr]}");
                    Console.WriteLine();
                }
                a++;
            }
        }
    }
原文地址:https://www.cnblogs.com/xiaowangzi1987/p/15193726.html