C语言实现最小生成树构造算法

C语言实现最小生成树构造算法攻略

最小生成树(Minimum Spanning Tree,MST)是一种求加权无向连通图的生成树的算法,其可以将连通图的n个顶点连接起来,形成一个权值最小的树。本文将介绍使用C语言实现最小生成树构造算法的攻略。

算法简介

其中,Kruskal算法和Prim算法是最常用的两个求解最小生成树的算法。

  • Kruskal算法

Kruskal算法首先需要把图中所有的边从小到大排序,依次取出每一条边,检查该边的两个顶点是否在同一个连通分量内,若不在,则将这条边放入生成树中,并将这两个顶点之间连通。

  • Prim算法

Prim算法则需要选取一个任意的顶点作为根节点,每次向生成树中添加一条从树中已有节点到不在树上的节点的最短边,直到所有节点都在生成树中。

Kruskal算法实现

下面是使用C语言实现Kruskal算法的示例代码:

#include <stdio.h>
#include <stdlib.h>

#define MAX 1000

typedef struct {
    int u, v, w;
}Edge;

int cmp(const void *a, const void *b)
{
    return ((Edge*)a)->w - ((Edge*)b)->w;
}

int Kruskal(Edge *edges, int n, int m, Edge *tree)
{
    int i, j, k;
    int set[MAX];

    for (i = 0; i < n; ++i)
        set[i] = i;

    qsort(edges, m, sizeof(edges[0]), cmp);  // 对边按权值进行排序

    for (i = j = 0; i < m && j < n - 1; ++i) {
        int u = edges[i].u, v = edges[i].v, w = edges[i].w;
        while (u != set[u]) u = set[u];
        while (v != set[v]) v = set[v];
        if (u != v) {
            set[u] = v;
            tree[j++] = edges[i];
        }
    }

    return (j == n - 1);  // 如果生成树边数为n-1则返回1,否则返回0
}

int main()
{
    int n, m;
    Edge edges[MAX], tree[MAX];
    scanf("%d %d", &n, &m);

    for (int i = 0; i < m; ++i)
        scanf("%d %d %d", &edges[i].u, &edges[i].v, &edges[i].w);

    if (!Kruskal(edges, n, m, tree)) {
        printf("No MST!\n");  // 如果生成树不存在则输出No MST!
    }
    else {
        int w = 0;
        for (int i = 0; i < n - 1; ++i)
            w += tree[i].w;
        printf("MST weight=%d\n", w);
        for (int i = 0; i < n - 1; ++i)
            printf("(%d,%d) ", tree[i].u, tree[i].v);
    }

    return 0;
}

Prim算法实现

下面是使用C语言实现Prim算法的示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <stdbool.h>

#define MAX 1000

int adj[MAX][MAX];

int Prim(int n, int **edges)
{
    int i, j, k;
    int dist[MAX], parent[MAX];
    bool visited[MAX];

    for (i = 0; i < n; ++i) {
        dist[i] = INT_MAX;
        visited[i] = false;
    }
    dist[0] = 0;
    parent[0] = -1;

    for (i = 0; i < n - 1; ++i) {
        int u = -1;
        for (j = 0; j < n; ++j) {
            if (!visited[j] && (u == -1 || dist[u] > dist[j]))
                u = j;
        }
        visited[u] = true;
        for (v = 0; v < n; ++v) {
            if (adj[u][v] && !visited[v] && dist[v] > adj[u][v]) {
                dist[v] = adj[u][v];
                parent[v] = u;
            }
        }
    }

    for (i = 1, k = 0; i < n; ++i) {
        if (parent[i] != -1) {
            edges[k][0] = parent[i];
            edges[k++][1] = i;
        }
    }

    return k;
}

int main()
{
    int n, m;
    scanf("%d %d", &n, &m);

    for (int i = 0; i < m; ++i) {
        int u, v, w;
        scanf("%d %d %d", &u, &v, &w);
        adj[u][v] = w;
        adj[v][u] = w;
    }

    int **tree = (int**)malloc((n - 1) * sizeof(int*));
    for (int i = 0; i < n - 1; ++i) {
        tree[i] = (int*)malloc(2 * sizeof(int));
    }

    int k = Prim(n, tree);  // k为生成树的边数

    int w = 0;
    for (int i = 0; i < k; ++i)
        w += adj[tree[i][0]][tree[i][1]];
    printf("MST weight=%d\n", w);
    for (int i = 0; i < k; ++i)
        printf("(%d,%d) ", tree[i][0], tree[i][1]);

    return 0;
}

结束语

以上就是C语言实现最小生成树构造算法的详细攻略,希望对大家有所帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言实现最小生成树构造算法 - Python技术站

(0)
上一篇 2023年5月22日
下一篇 2023年5月22日

相关文章

  • 如何判断一个数是否为2的幂次方?若是,并判断出来是多少次方?

    判断一个数是否为2的幂次方: 一个数如果是2的幂次方,那么它的二进制表示中只有最高位是1,其他各位都是0。比如2的1次方是2,写成二进制就是10;2的2次方是4,写成二进制是100;2的3次方是8,写成二进制是1000。 根据这个规律,我们可以用位运算来判断一个数是否为2的幂次方,具体方法如下: 首先判断这个数是否大于0,如果为0则不是2的幂次方; 然后判断…

    C 2023年5月23日
    00
  • 详解C++中基类与派生类的转换以及虚基类

    让我们来详解C++中基类与派生类的转换以及虚基类。 基类与派生类的转换 向上转型 在C++中,基类和派生类之间可以相互转换。向上转型是指将一个派生类对象转换为其基类对象,这种转换是自动进行的,因为派生类包含了基类的所有成员,而且这些成员在内存中的布局顺序是相同的。例如: class Animal { public: virtual void voice() …

    C 2023年5月22日
    00
  • C 程序 查找给定范围内的素数

    下面是C程序查找给定范围内素数的完整使用攻略。 程序简介 这个C程序的主要功能是查找给定范围内的素数。用户需要输入一个起始数值和一个结束数值,程序会输出这个范围内的所有素数。程序的具体实现方式是使用了一个嵌套的for循环进行遍历,逐个判断每个数是否是素数。 使用方法 克隆或下载程序的源代码; 打开终端或命令提示符; 切换到程序的源代码目录; 使用C编译器编译…

    C 2023年5月9日
    00
  • C语言中静态和动态内存分配的区别

    C语言中的静态和动态内存分配是两种不同的方式,下面我们就来详细讲解一下静态和动态内存分配的区别。 静态内存分配 静态内存分配是指在程序编译阶段就已经确定了变量的内存空间,并在程序运行时一直存在的内存空间。静态内存分配只会在程序启动时进行一次,并在整个程序运行期间都存在。静态内存分配的变量通常包括全局变量、静态变量和局部静态变量。静态内存分配的变量在程序启动时…

    C 2023年5月10日
    00
  • PowerShell时间记录脚本

    关于“PowerShell时间记录脚本”的完整攻略,我可以为您进行详细讲解。 简介 首先,让我们来了解一下“PowerShell时间记录脚本”的简介。该脚本可以帮助用户记录电脑运行的时间,并输出到指定的文本文件中。用户可以使用该脚本来记录自己在电脑上的时间消耗,从而更好地管理时间和提高工作效率。 前置条件 在运行“PowerShell时间记录脚本”之前,用户…

    C 2023年5月22日
    00
  • C语言 坐标移动详解及实例代码

    C语言 坐标移动详解及实例代码攻略 坐标移动的概念 在计算机中,坐标移动是指移动一个对象或点的位置以改变其在屏幕上显示的位置。在C语言中,使用结构体来表示坐标,并利用操作结构体的函数来实现坐标移动的功能。 坐标移动的实现步骤 定义结构体 首先,需要定义表示坐标的结构体。一般来说,坐标结构体包含两个变量:x坐标和y坐标。以下是一个示例程序: typedef s…

    C 2023年5月24日
    00
  • vscode 配置 C/C++编译环境(完整教程)

    下面是“vscode配置C/C++编译环境(完整教程)”的完整攻略: 一、安装vscode和MinGW-w64 1.安装vscode vscode是一款非常流行的编辑器,使用非常方便,可以在官网 https://code.visualstudio.com/ 下载最新版的安装包进行安装。安装完成后,打开vscode,在左侧菜单栏中搜索并安装“C/C++”插件。…

    C 2023年5月23日
    00
  • Visual Studio Code运行程序时输出中文成乱码问题及解决方法

    当在Visual Studio Code中运行程序时输出中文出现乱码问题,通常是由于命令行终端的默认字符集与程序输出字符集不一致导致的。下面就详细讲解解决此问题的步骤。 步骤一:查看当前终端默认字符集 运行以下命令查看当前终端默认字符集 chcp 下面是命令输出的结果: 活动代码页: 936 以上结果表示当前终端的默认字符集是“GB2312”。 步骤二:修改…

    C 2023年5月22日
    00
合作推广
合作推广
分享本页
返回顶部