• kruskal算法


    4克鲁斯卡尔算法—集合运算应用

     

    上图表述了生成树的算法过程

    (选最短边,不构成回路)

    只要有交集就合并

    “原图”的数据对象可以使用邻接表来表达:

    IntgData[7][7]

    “边长排序图”的数据可以用线性表保存,数据结构:

    算法描术:

    算法过程,本质上是集合操作,集合的初始状态是空集,然后:

    1)点对(1,3)进入集合Vertex[ ]={ {1,3}  }   集合里有一个子集,将对应的边选入线性表(  Vertex[7 ]={ 0,0,0,0,0,0,0})

    2) 点对(4,6)进入集合Vertex={ {1,3},{4,6} }   集合里有两个子集,将对应的边选入线性表。

    3)点对(2,5)进入集合Vertex={ {1,3},{4,6},{2,5} }   集合里有三个子集,将对应的边选入线性表。

    4)点对(3,6)进入集合Vertex={ {1,3},{4,6},{2,5},{3,6} },点对(3,6)与两个集合{1,3},{4,6}有交集,这时需要将它们变为一个集合,即进行集合并运算。最后集合变为Vertex={ {1,3,4,6},{2,5} },将对应的边选入线性表。

    5)点对(1,4)不能进入集合,因为它是集合Vertex的子集,点对(1,4)的边会使生成树构成回路。

    6)…依据上述规则,不断选入点对,对于有N个顶点的图,选N-1个点对(N-1条边)即可

    总结:点对入选规则

    1)不是子集且无交集,入选; 2)有交集,入选;合并相关集合;3)是子集,不入选。

    从程序的观点看:

    可以使用数组Vertex[]作为集合来描述顶点选入情况。Vertex[]的下标为顶点编号,值为该顶点是否被选。例Vertex[1]=0,表示顶点1不在集合中;Vertex[1]≠0表示顶点1在集合中。另外还需要一个集合编号,对应上述步骤,Vertex的值为:

    1)Vertex[]={0,1,0,1,0,0,0}   下标——顶点编号

    2)Vertex[]={0,1,0,1,2,0,2}

    3)Vertex[]={0,1,3,1,2,3,2}

    4)Vertex[]={0,1,3,1,1,3,1}

    ……

    typedefstruct

    {

        int  vtx1;   //点对与边长

        int  vtx2;

        int  length;

    } dataSet;

    typedefstruct

    {

        dataSetVEdge[50];

        int count;

    } sVEList, *LPListVE;

    Vertex[N ]={ 0,0,0,0,0,0,0})

    intgData[][N]={ { 0,0,0,0,0,0,0},

    ;

    sVEList  LA={0},LB={0};

    原始数据读入LA中

    Int n=0;

    For(i=1;i<=6;i++)

    For(j=1;j<=6;j++)

    {       if(gdata[i][j] && i<j)

       {   LA.VEdge[n].vtx1=I;

    LA.VEdge[n].vtx1=j;

         LA.VEdge[n].length=gdata[i][j]

    LA.count++

    }

    }

    对LA排序

    Int k=0   -指向LA头部+1

    Int  m=1     集合标号

    第一条边进入(1,3)

    Vertex[N ]={ 0,1,0,1,0,0,0})

    第一条边信息进入LB={0}

    Vertex[N ]={ 0,1,0,1,2,0,2})  {Vertex[x1]== Vertex[x2]==0}

    (通过m++实现)

    第2条边信息进入LB={0}

    // 克鲁斯卡尔2.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include<functional>
    #include<iostream>
    #include<algorithm>
    #include<vector>
    using namespace std;
    
    typedef struct
    {
        unsigned v1;
        unsigned v2;
        unsigned weight;
    }Edges;
    typedef struct//顺序表定义
    {
        vector<Edges> vec;
    }Sqlist;
    
    void initList(Sqlist &list, const vector<vector<int>> &a)//将顶点对、边长数据读入线性表
    {
        size_t i, j;
        Edges temp_edges;
        for (i = 1;i<a.size();i++)
            for (j = 1;j<i;j++)
            {
                if (a[i][j])
                {
                    if (i<j)       //保证(x,y)中x存放小的顶点数
                    {
                        temp_edges.v1 = i;
                        temp_edges.v2 = j;
                    }
                    else
                    {
                        temp_edges.v1 = j;
                        temp_edges.v2 = i;
                    }
                    temp_edges.weight = a[i][j];
                    list.vec.push_back(temp_edges);
                }
            }
    }
    
    bool isShorter(const Edges &r_edg, const Edges &l_edg)
    {
        return r_edg.weight < l_edg.weight;
    }
    
    void listSort(Sqlist &s)  //线性表按边长排序
    {
        sort(s.vec.begin(), s.vec.end(), isShorter);
    }
    
    void printList(const Sqlist &s)//打印线性表
    {
    
        for (size_t i = 0;i<s.vec.size();i++)
        {
            cout << "(" << s.vec[i].v1 << "-->" << s.vec[i].v2 << ",weight is " << s.vec[i].weight << ")" << '	';
            if ((i + 1) % 2 == 0)
                cout << '
    ';
        }
        cout << endl;
    }
    void kruskal()
    {
        vector<vector<int>> IntgData= { { 0,0,0,0,0,0,0 },    //邻接矩阵创建初始化
        { 0,0,6,1,5,0,0 },
        { 0,6,0,5,0,3,0 },
        { 0,1,5,0,5,6,4 },
        { 0,5,0,5,0,0,2 },
        { 0,0,3,6,0,0,6 },
        { 0,0,0,4,2,6,0 }
        };
        int Vertex[7] = { 0 };    //初始化顶点集Vertex为空集
    
        int setNum = 1;        //集合编号
    
        int selectlocation = 0;    //所选点对在线性表A位置
    
        size_t seletarc = 1;//选择边的个数;
        Sqlist A;
        Sqlist B;
        //将顶点对、边长数据读入线性表A
        initList(A, IntgData);
    
        //线性表A按边长排序
        listSort(A);
        //printList(A);
        Edges temp_edges;
        while (seletarc<IntgData.size()-1)
        {
            //A中选一条边,根据他的两个顶点判断该边是否为生成树的边
            int x = A.vec[selectlocation].v1;
            int y = A.vec[selectlocation].v2;
    
            //顶点对是Vertex子集,取A中下一个点
            if (Vertex[x] == Vertex[y] && Vertex[x] != 0)
            {
                selectlocation++;
            }
            else
            {
                //顶点对与Vertex无交集,进入集合
                if (Vertex[x] == 0 && Vertex[y] == 0)
                {
                    Vertex[x] = setNum;
                    Vertex[y] = setNum;
                    setNum++;
                }
                else if (Vertex[x] == 0 && Vertex[y] != 0)//顶点对与一个子集相交,没有交的进入到vertex中
                {
                    Vertex[x] = Vertex[y];
                }
                else if (Vertex[x] != 0 && Vertex[y] == 0)
                {
                    Vertex[y] = Vertex[x];
                }
                else if (Vertex[x] != 0 && Vertex[y] != 0)//顶点对与两个子集相交,相交的两个子集并运算
                {
                    for (int i = 1;i<IntgData.size();i++)
                    {
                        int temp = Vertex[y];
                        if (Vertex[i] == temp)
                            Vertex[i] = Vertex[x];//相邻点复制,取Vertex[y]的值覆盖所有Vertex[x]
                    }
                }
                //所选的边进入线性表B
                temp_edges.v1 = x;
                temp_edges.v2 = y;
                temp_edges.weight = A.vec[selectlocation].weight;
                B.vec.push_back(temp_edges);
                seletarc++;
            }//else
        }//while
         //最后打印B集合
        cout << "最小生成树边为:" << endl;
        printList(B);
    }
    int main()
    {
        kruskal();
        return 0;
    }
  • 相关阅读:
    dfssvc.exe
    我左边的公告
    再做了一个LOGO
    做一个调查,请大家帮忙
    如果年三十没有人陪我
    我喜欢这个模版
    cisvc.exe是什么服务
    IIS与SQL服务器安全加固
    终于申请到了blogs
    重发LOGO
  • 原文地址:https://www.cnblogs.com/csudanli/p/5943574.html
Copyright © 2020-2023  润新知