数据结构之最小生成树-prim+Kruskal

采用c++来实现prim算法和Kruskal算法

#include <stdio.h>
#include <iostream>
#include<algorithm>

using namespace std;
#define MaxInt 32767
#define MVNum 100
typedef char VerTexType;
typedef int ArcType;//假设边的权值类型为整型
typedef struct {
    VerTexType vexs[MVNum];//顶点表
    ArcType arcType[MVNum][MVNum];//邻接矩阵
    int vexnum, arcnum;//图的当前点数和边数
} AMGraph;

//辅助数组的定义,用来记录从顶点集U到V-U的权值最小的边
typedef struct {
    VerTexType adjvex; //最小边在U中的那个顶点
    ArcType lowcost;// 最小边上的权值
} closedge[MVNum];

//申明函数
void MiniSpanTree_Prim(AMGraph G, VerTexType u);

int LocateVex(AMGraph G, char v);

int MinArc(closedge closedge);

void CreateUDN(AMGraph &G);

void MiniSpanTree_Kruskal(AMGraph G);

int main() {
    AMGraph G;
    CreateUDN(G);
    MiniSpanTree_Prim(G, 'a');
    printf("这是Kruskal的最小生成树算法:\n");
    MiniSpanTree_Kruskal(G);
    return 0;
}

void CreateUDN(AMGraph &G) {
    cout << "请输入当前的点数和边数:\n";
    cin >> G.vexnum >> G.arcnum;
    cout << "依次输入点的信息:";
    for (int i = 0; i < G.vexnum; i++) {
        cin >> G.vexs[i];
    }
    //初始化邻接矩阵,均置为极大值MaxInt
    for (int i = 0; i < G.vexnum; i++) {
        for (int j = 0; j < G.vexnum; j++) {
            G.arcType[i][j] = MaxInt;
        }
    }
    cout << "构造邻接矩阵:\n";
    char v1, v2;
    int w;
    for (int k = 0; k < G.arcnum; k++) {
        cout << "输入两个相邻的顶点,及其权值:\n";
        cin >> v1 >> v2 >> w;
        int i = LocateVex(G, v1); //确定V1,V2在G中的位置
        int j = LocateVex(G, v2);
        printf("%d %d %d\n", i, j, w);
        G.arcType[i][j] = w;
        G.arcType[j][i] = G.arcType[i][j];
    }
    cout << "邻接矩阵为:\n";
    for (int i = 0; i < G.vexnum; i++) {
        for (int j = 0; j < G.vexnum; j++) {
            printf(" %d ", G.arcType[i][j]);
        }
        printf("\n");
    }
}

int LocateVex(AMGraph G, char v) {
    for (int i = 0; i < G.vexnum; i++) {
        if (v == G.vexs[i]) {
            return i;
        }
    }
    printf("没有找到索引\n");
    return -1;
}

//辅助数组Edges的定义
typedef struct {
    VerTexType Head;//边的起始点
    VerTexType Tail;//边的终点
    ArcType lowcost;//边上的权值
} Edge;
//辅助数组Vexset的定义
int Vexset[MVNum];

bool cmp(Edge x, Edge y);

void MiniSpanTree_Kruskal(AMGraph G) {
    Edge edge[MVNum];
    int index = 0;
    //对辅助数组进行排序
    for (int i = 0; i < G.vexnum - 1; i++) {
        for (int j = i + 1; j < G.vexnum; j++) {
            if (G.arcType[i][j] != MaxInt) {
                edge[index].lowcost = G.arcType[i][j];
                edge[index].Head = G.vexs[i];
                edge[index].Tail = G.vexs[j];
                index++;
            }
        }
    }
    sort(edge, edge + index, cmp);
    for(int i =0;i<index;i++){
        printf("%c %c %d\n",edge[i].Head,edge[i].Tail,edge[i].lowcost);
    }
    //辅助数组,表示各顶点自成一个连通分量
    for (int i = 0; i < G.vexnum; i++) {
        Vexset[i]=i;
    }
    //依次查看数组Edge中的边
    for(int i =0;i<G.arcnum;i++){
        int v1 = LocateVex(G,edge[i].Head);//为边的起始点Head的下标
        int v2 = LocateVex(G,edge[i].Tail);//为边的终点Tail的下标
        int vs1 = Vexset[v1];//获取edge[i]的起始点所在的连通分量vs1
        int vs2 = Vexset[v2];//获取edge[i]的终点点所在的连通分量vs2
        if(vs1!=vs2){//边的两个顶点分属于不同的连通分量
            cout<<edge[i].Head<<" "<<edge[i].Tail<<endl;//输出此边
            //合并vs1和vs2两个分量,即两个集合统一编号
            for(int j =0;j<G.vexnum;j++){
                if(Vexset[j]==vs2){
                    Vexset[j]=vs1;//集合编号为vs2的都改为vs1
                }
            }

        }
    }
}

bool cmp(Edge x, Edge y) {
    return (x.lowcost) < (y.lowcost);
}

void MiniSpanTree_Prim(AMGraph G, VerTexType u) {
    //无向图G以邻接矩阵形式存储,从顶点u出发构造G的最小生成树T,输出T的各条边
    int k = LocateVex(G, u);//k为顶点u的下标
//    printf("  %d\n",k);
    closedge closedge;
    //初始化closedge[i]
    for (int j = 0; j < G.vexnum; j++) {
        if (j != k) {
            closedge[j].adjvex = u;
            closedge[j].lowcost = G.arcType[k][j];
        }
    }
    cout << u << " ";
    closedge[k].lowcost = 0;//初始化,U={u}
    for (int i = 1; i < G.vexnum; i++) {
        //选择其余n-1个顶点,生成n-1条边
        int k = MinArc(closedge);
        int u0 = closedge[k].adjvex;
        char v0 = G.vexs[k];
//       printf("k: %d \n",k);
//       printf("u0:%d\n ",u0);
        printf("%c ", v0);
        closedge[k].lowcost = 0;//将第k个顶点并入U集
        //更新closedge
        for (int j = 0; j < G.vexnum; j++) {
            if (G.arcType[k][j] < closedge[j].lowcost) {
                closedge[j].lowcost = G.arcType[k][j];
                closedge[j].adjvex = G.vexs[k];
            }
        }
    }
}

int MinArc(closedge closedge1) {
    //找出closedge中最小边上权值所对应的顶点编号
    int minValue = MaxInt;
    int k = -1;
    for (int i = 0; i < sizeof(closedge1); i++) {
        if (minValue > closedge1[i].lowcost && closedge1[i].lowcost != 0) {
            minValue = closedge1[i].lowcost;
            k = i;
        }
    }
    return k;
}

 

posted on 2019-11-19 16:16  我想静静_zjf  阅读(365)  评论(0)    收藏  举报

导航