数据结构_最小生成树Kruskal算法(C语言)

数据结构总目录

最小生成树Kruskal算法

Kruska(克鲁斯卡尔)算法用于求解的问题是如何用最小代价的边来连通图中的所有顶点,所生成的树称为最小生成树

1. 图文解析

已知存在邻接矩阵G,存在两个辅助数组edge和vexset
(1)edge数组用于存储图的所有边信息(头顶点、权值、尾顶点)
(2)verset用于存储每个顶点所处在的集合(每个下标代表一个集合)

则有如下最小生成树的遍历过程:
(1)根据边的权值从小到大排序edge边数组
(2)顺序遍历排序好的edge数组,如果头、尾顶点不在一个集合中,则合并到一个集合中
(3)重复第二步依次推导,直到所有顶点都在一个集合中。
数据结构_最小生成树Kruskal算法(C语言)_第1张图片
数据结构_最小生成树Kruskal算法(C语言)_第2张图片数据结构_最小生成树Kruskal算法(C语言)_第3张图片
数据结构_最小生成树Kruskal算法(C语言)_第4张图片

2. 源代码

#include
#include
#define MaxVex 10
#define INF 65535

typedef char VertexType;    // 顶点的数据类型
typedef int EdgeType;       // 边的数据类型
typedef struct
{
    VertexType *vertexs;    // 一维数组存放顶点数据
    EdgeType **edges;       // 二维数组存放边的数据
    int numVertexs, numEdges;//顶点数、边数
}AMGraph;

// 边结构
typedef struct Edge
{
    EdgeType edgeData;
    int headVertex, tailVertex;
}Edge;

// 初始化领接矩阵
void InitAMGraph(AMGraph *G)
{
    // 初始化顶点一维数组
    G->vertexs = (VertexType *)malloc(MaxVex*sizeof(VertexType));
    // 初始化边的二维数组
    int i, j;
    G->edges = (EdgeType **)malloc(MaxVex*sizeof(EdgeType *));
    for (i = 0; i < MaxVex; i++)
    {
        G->edges[i] = (EdgeType *)malloc(MaxVex*sizeof(EdgeType));
        // 初始化每条边都为INF(无穷大)
        for ( j = 0; j < MaxVex; j++)
        {
            if (i == j)
            {
                G->edges[i][j] = 0;     // 对角线初始位为0
            }
            else
            {
                G->edges[i][j] = INF;   // 初始化为无穷大
            }
        }
    }
    // 初始化顶点和边的数量
    G->numVertexs = 0;
    G->numEdges = 0;
    printf("已初始化邻接矩阵!\n");
}   

// 创建领接矩阵
void CreateAMGraph(AMGraph *G)
{
    printf("请输入顶点数和边数:");
    scanf("%d %d", &G->numVertexs, &G->numEdges);

    int i, j, k, weight;
    // 输入顶点数据
    for (i = 0; i < G->numVertexs; i++)
    {
        fflush(stdin);
        printf("请输入第%d个顶点数据:", i + 1);
        scanf("%c", &G->vertexs[i]);
    }
    // 输入边的权值
    for (k = 0; k < G->numEdges; k++)
    {
        printf("请输入第%d条边的两顶点及其权值:", k + 1);
        scanf("%d %d %d", &i, &j, &weight);
        G->edges[i - 1][j - 1] = weight;
        // 无向图中,边的两个方向权值相同
        G->edges[j - 1][i - 1] = weight;
    }
    printf("已完成邻接矩阵的创建!\n");
}

int cmp(const void *a, const void *b)
{
    Edge *e1 = (Edge *)a;
    Edge *e2 = (Edge *)b;
    return e1->edgeData - e2->edgeData;
}

void MiniSpanTree_Kruskal(AMGraph G)
{
    int i, j, k = 0;
    // 定义边辅助数组
    Edge *edge;
    edge = (Edge *)malloc(MaxVex * sizeof(Edge));  
    // 获取取所有的边(无向图只需要遍历对角线的一边即可)
    for (i = 1; i < MaxVex; i++)
    {
        for (j = 0; j < i; j++)
        {
            if (G.edges[i][j] != 0 && G.edges[i][j] != INF)
            {
                edge[k].edgeData = G.edges[i][j];
                edge[k].headVertex = i;
                edge[k].tailVertex = j;
                k++;
            }
        }
    }
    // 对边辅助数组进行排序
    qsort(edge, G.numEdges, sizeof(Edge), cmp);
    /* for (i = 0; i < G.numEdges; i++)
    {
        j = edge[i].headVertex;
        k = edge[i].tailVertex;
        printf("%c---%d---%c\n",G.vertexs[j] , edge[i].edgeData, G.vertexs[k]);
    } */

    // 定义顶点集合辅助数组
    int *vexset;
    vexset = (int *)malloc(G.numVertexs * sizeof(int)); 
    // 初始化顶点集合数组
    for (i = 0; i < G.numVertexs; i++)
    {   
        vexset[i] = i;  // 每个顶点都处于独自的集合中
    }
    
    // 依次选择最小边
    int v1, v2, head, tail;
    for (i = 0; i < G.numEdges; i++)
    {
        v1 = edge[i].headVertex;    // 边的头顶点下标
        v2 = edge[i].tailVertex;    // 边的尾顶点下标
        head = vexset[v1];          // 头顶点所在的集合标识
        tail = vexset[v2];          // 尾顶点所在的集合标识

        // 如果头、尾顶点不在一个集合中,则合并顶点到集合中
        if (vexset[head] != vexset[tail])
        {
            printf("%c---(%d)---%c\n", G.vertexs[head], G.edges[head][tail], G.vertexs[tail]);
            // 合并头、尾顶点到一个集合中
            for (j = 0; j < G.numVertexs; j++)
            {
                if (vexset[j] == tail)
                {
                    vexset[j] = head;
                }
            }
        }
    }
}

int main()
{
    AMGraph G;
    InitAMGraph(&G);
    CreateAMGraph(&G);
    MiniSpanTree_Kruskal(G);
    system("pause");
    return 0;
}

3. 测试结果

数据结构_最小生成树Kruskal算法(C语言)_第5张图片

你可能感兴趣的:(数据结构与算法(C语言),数据结构,图,c语言,Kruskal)