最小生成数kruskal算法和prim算法

定义

连通图:在无向图中,若任意两个顶点vivi与vjvj都有路径相通,则称该无向图为连通图。

强连通图:在有向图中,若任意两个顶点vivi与vjvj都有路径相通,则称该有向图为强连通图。

连通网:在连通图中,若图的边具有一定的意义,每一条边都对应着一个数,称为权;权代表着连接连个顶点的代价,称这种连通图叫做连通网。

生成树:一个连通图的生成树是指一个连通子图,它含有图中全部n个顶点,但只有足以构成一棵树的n-1条边。一颗有n个顶点的生成树有且仅有n-1条边,如果生成树中再添加一条边,则必定成环。

最小生成树:在连通网的所有生成树中,所有边的代价和最小的生成树,称为最小生成树。 

kruskal算法

此算法可以称为“加边法”,初始最小生成树边数为0,每迭代一次就选择一条满足条件的最小代价边,加入到最小生成树的边集合里。

1. 把图中的所有边按代价从小到大排序;

2. 把图中的n个顶点看成独立的n棵树组成的森林;

3. 按权值从小到大选择边,所选的边连接的两个顶点ui,viui,vi,应属于两颗不同的树,则成为最小生成树的一条边,并将这两颗树合并作为一颗树。

4. 重复(3),直到所有顶点都在一颗树内或者有n-1条边为止。

最小生成数kruskal算法和prim算法_第1张图片

prim算法

此算法可以称为“加点法”,每次迭代选择代价最小的边对应的点,加入到最小生成树中。算法从某一个顶点s开始,逐渐长大覆盖整个连通网的所有顶点。

1. 图的所有顶点集合为VV;初始令集合u={s},v=V−uu={s},v=V−u;

2. 在两个集合u,vu,v能够组成的边中,选择一条代价最小的边(u0,v0)(u0,v0),加入到最小生成树中,并把v0v0并入到集合u中。

3. 重复上述步骤,直到最小生成树有n-1条边或者n个顶点为止。

最小生成数kruskal算法和prim算法_第2张图片

 

kruskal算法:

#include 
#include 
#include 
#include 

const int   INFINITE  = 0x7FFFFFFF;
const int   VERTEX    = 6;
const char  szVertex[] = { 'A', 'B', 'C', 'D', 'E', 'F' };

struct stEdge
{
    int u;
    int v;
    int weight;

    stEdge(int iu, int iv, int iweight):u(iu),v(iv),weight(iweight) {}
    
    friend bool operator<(const stEdge &a, const stEdge &b) { return a.weight < b.weight; }
};

void createGraph(int (*g)[VERTEX])
{
    for (int i = 0; i < VERTEX; i++)
    {
        for (int j = 0; j < VERTEX; j++)
        {
            g[i][j] = INFINITE;
        }
    }
    g[0][1] = 6; g[0][2] = 1; g[0][3] = 5;
    g[1][0] = 6; g[1][2] = 5; g[1][4] = 3;
    g[2][0] = 1; g[2][1] = 5; g[2][3] = 5; g[2][4] = 6; g[2][5] = 4;
    g[3][0] = 5; g[3][2] = 5; g[3][5] = 2;
    g[4][1] = 3; g[4][2] = 6; g[4][5] = 6;
    g[5][2] = 4; g[5][3] = 2; g[5][4] = 6;
}

void initEdges(std::vector &edges, const int (*g)[VERTEX])
{
    for (int i = 0; i < VERTEX; ++i)
    {
        for (int j = i+1; j < VERTEX; ++j)
        {
            edges.push_back(stEdge(i,j,g[i][j]));
        }
    }
    std::sort(edges.begin(), edges.end(), std::less());
}

bool notSameTree(int u, int v, std::vectorint> > &trees)
{
    int uindex = -1, vindex = -1;

    for (int i = 0; i < VERTEX; ++i)
    {
        if (std::find(trees[i].begin(), trees[i].end(), u) != trees[i].end())
        {
            uindex = i;
        }
        if (std::find(trees[i].begin(), trees[i].end(), v) != trees[i].end())
        {
            vindex = i;
        }
    }

    if (uindex != vindex)
    {
        trees[uindex].splice(trees[uindex].end(), trees[vindex]);
        return true;
    }

    return false;
}

void kruskal(const int (*g)[VERTEX])
{
    std::vector edges;
    initEdges(edges, g);

    std::vectorint> > trees(VERTEX);
    for (int i = 0; i < VERTEX; ++i)
    {
        trees[i].push_back(i);
    }

    for (auto e : edges)
    {
        if (notSameTree(e.u, e.v, trees))
        {
            std::cout << szVertex[e.u] << "---" << szVertex[e.v] << std::endl;
        }
    }
}

int main()
{
    int g[VERTEX][VERTEX] = {0};

    createGraph(g);

    kruskal(g);

    return 0;
}

 

prim算法:

#include 
#include 
#include 
#include 

const int   INFINITE  = 0x7FFFFFFF;
const int   VERTEX    = 6;
const char  szVertex[] = { 'A', 'B', 'C', 'D', 'E', 'F' };


struct stEdge
{
    int index;
    int weight;
};

void createGraph(int (*g)[VERTEX])
{
    for (int i = 0; i < VERTEX; i++)
    {
        for (int j = 0; j < VERTEX; j++)
        {
            g[i][j] = INFINITE;
        }
    }
    g[0][1] = 6; g[0][2] = 1; g[0][3] = 5;
    g[1][0] = 6; g[1][2] = 5; g[1][4] = 3;
    g[2][0] = 1; g[2][1] = 5; g[2][3] = 5; g[2][4] = 6; g[2][5] = 4;
    g[3][0] = 5; g[3][2] = 5; g[3][5] = 2;
    g[4][1] = 3; g[4][2] = 6; g[4][5] = 6;
    g[5][2] = 4; g[5][3] = 2; g[5][4] = 6;
}

int minIndex(const stEdge *weightArr, int len)
{
    int min = INFINITE;
    int idx = -1;

    for (int i = 0; i < len; ++i)
    {
        if (weightArr[i].weight != 0 && min > weightArr[i].weight)
        {
            min = weightArr[i].weight;
            idx = i;
        }
    }

    return idx;
}

void prim(const int (*g)[VERTEX], int index)
{
    stEdge weightArr[VERTEX];

    weightArr[index].weight = 0;
    weightArr[index].index = index;
    for (int i = 0; i < VERTEX; ++i)
    {
        if (i != index)
        {
            weightArr[i].index = index;
            weightArr[i].weight = g[index][i];
        }
    }

    for (int i = 1; i < VERTEX; ++i)
    {
        int nextIndex = minIndex(weightArr, VERTEX);
        if (nextIndex != -1)
        {
            std::cout << szVertex[weightArr[nextIndex].index] << "---" << szVertex[nextIndex] << std::endl;

            weightArr[nextIndex].weight = 0;
            weightArr[nextIndex].index = nextIndex;
            for (int j = 0; j < VERTEX; ++j)
            {
                if (weightArr[j].weight != 0 && g[nextIndex][j] < weightArr[j].weight)
                {
                    weightArr[j].index = nextIndex;
                    weightArr[j].weight = g[nextIndex][j];
                }
            }
        }
    }
}

int main()
{
    int g[VERTEX][VERTEX] = {0};

    createGraph(g);

    prim(g, 0);

    return 0;
}

 

转载自:https://blog.csdn.net/luoshixian099/article/details/51908175

转载于:https://www.cnblogs.com/zuofaqi/p/9966540.html

你可能感兴趣的:(最小生成数kruskal算法和prim算法)