最小生成树 prim和Kruskal

prim算法

有两个集合,第一个集合,存放最小生成树,第二个集合,用来存放还没有进入最小生成树的结点。但这两个集合实际上是用同一个数组表示的。
我们用closedge[100]来表示这个数组,每个单元由“string Data;”和“int lowcost;”两部分组成。其中closedge[1]表示图中的第一个结点v1,closedge【1】.Data表示v1到最小生成树最短路径的结点(假设为v2),closedge【1】.lowcost就是v1到v2的距离。如果closedge【1】.lowcoat为0,就说明它已经在最小生成树中了。
prim算法的核心思想,就是以最小生成树为研究对象,每次在还没有进入最小生成树的结点中,找到路径最小的那个。

  • 假设目前的最小生成树为v2,v1是所有结点中,到它最短的一个,那么我们就把v1加入到最小生成树中;
  • 过程为:closedge【1】.lowcoat赋为0;把closedge【1】.Data赋为v1;
  • 在剩下的结点中,寻找是否有结点到v1的距离,小于此几点到v2的距离,如果有,那么此时此节点到最小生成树的距离,就是到v1的距离。总共n个结点,就重复此步骤n-1次。
struct Node
{
    string Data;
    int lowcost;
}closedge[100];
int Get_Location(Graph T,string name)
{
    for(int i = 1; i <= T.Vex_num; i++)
    {
        if(T.Name[i] == name)
            return i;
    }
    cout<<"Error!Not found!"<<endl;
    exit(1);
}
int Get_Min(Node closedge[],int n)
{
    int Min = 100;int index;
    for(int i = 1; i <= n; i++)
    {
        if(closedge[i].lowcost < Min && closedge[i].lowcost != 0)
        {
            Min = closedge[i].lowcost;
            index = i;
        }
    }
    return index;
}
void MiniSpanTree_prim(Graph T,string name)
{
    int k = Get_Location(T,name);    //确认开始点位置
    closedge[k].lowcost = 0;        //开始点此时就是最小生成树
    for(int i = 1; i <= T.Vex_num; i++)
    {
        if(i != k)                  //剩下的所有结点到最小生成树的距离
        closedge[i] = {name,T.Arr[k][i]};
    }
    string n1, n2;
    cout<<"最小生成树"<<endl<<"从\t"<<"到"<<endl;
    for(int i = 1; i < T.Vex_num; i++)
    {
        k = Get_Min(closedge,T.Vex_num);  //到最小生成树距离的最小结点位置
        n1 = closedge[k].Data;          //与次结点相连的最小成成树中的结点
        n2 = T.Name[k];                 //此结点
        cout<<n1<<"\t"<<n2<<endl;
        closedge[k].lowcost = 0;        //此节点进入最小生成树
        for(int j = 1; j <= T.Vex_num; j++)
        {
            if(T.Arr[j][k] < closedge[j].lowcost)
                closedge[j] = {T.Name[k],T.Arr[j][k]};
        }
    }
}

//测试数据
/*
6 10
v1 v2 v3 v4 v5 v6
v1 v2 6
v1 v4 5
v1 v3 1
v2 v3 5
v2 v5 3
v3 v4 5
v3 v5 6
v3 v6 4
v4 v6 2
v5 v6 6

*/


Kruskal算法

  1. 把所有的边都放到一个叫Edge的辅助数组中,并从小到大排序;
  2. 再设一个存放每个结点所在连通分量的辅助数组,初始每个结点都在自己的连通分量中:Vexset[v1]=1,Vexset[2]=2,Vexset[i]=i;
  3. 每次找到权重最小的边,如果此边的两个结点,没有在同一个连通分量中,就把这条边加入最小生成树;
#include<iostream>
#include<algorithm>
using namespace std;
struct Graph
{
    int Arr[100][100];
    string Name[100];
    int Vex_num, Edge_num;
};
struct Node
{
    string head;
    string tail;
    int weight;
}Edge[100];
int Vexset[100];
int Get_Location(Graph T,string name)
{
    for(int i = 1; i <= T.Vex_num; i++)
    {
        if(T.Name[i] == name)
            return i;
    }
}
void Create_Graph(Graph & T)
{
    cin>>T.Vex_num>>T.Edge_num;
    for(int i = 1; i <= T.Vex_num; i++)
    {
        cin>>T.Name[i];
    }
    int x, y, w; string n1, n2;
    for(int i = 1; i <= T.Edge_num; i++)
    {
        cin>>n1>>n2>>w;
        Edge[i].head = n1;Edge[i].tail = n2;
        Edge[i].weight = w;
        x = Get_Location(T,n1);
        y = Get_Location(T,n2);
        T.Arr[x][y] = w;T.Arr[y][x] = w;
    }
}
int comp(Node n1, Node n2)
{
    return n1.weight < n2.weight;
}
void MiniSpanTree_Kruskal(Graph T)
{
    sort(Edge,Edge + T.Edge_num + 1,comp);
    for(int i = 1; i <= T.Vex_num; i++)
        Vexset[i] = i;
    int x, y; int n1, n2;
    for(int i = 1; i <= T.Edge_num; i++)
    {
        x = Get_Location(T,Edge[i].head);
        y = Get_Location(T,Edge[i].tail);
        n1 = Vexset[x];n2 = Vexset[y];
        if(n1 != n2)
        {
            cout<<Edge[i].head<<"\t"<<Edge[i].tail<<endl;
            for(int j = 1; j <= T.Vex_num; j++)
            {
                if(Vexset[j] == n2)
                    Vexset[j] = n1;
            }
        }
    }
}
int main()
{
    Graph T;
    Create_Graph(T);
    MiniSpanTree_Kruskal(T);
}



/*
6 10
v1 v2 v3 v4 v5 v6
v1 v2 6
v1 v4 5
v1 v3 1
v2 v3 5
v2 v5 3
v3 v4 5
v3 v5 6
v3 v6 4
v4 v6 2
v5 v6 6

*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值