C语言实现最小生成树算法:Prim和Kruskal

这篇具有很好参考价值的文章主要介绍了C语言实现最小生成树算法:Prim和Kruskal。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

以下是使用C语言实现Prim算法生成最小生成树的代码:

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

#define V 5 // 图中顶点的个数

// 找到顶点集合中未访问的顶点中距离最小的顶点
int minDistance(int dist[], int visited[]) {
    int min = INT_MAX, min_index;

    for (int v = 0; v < V; v++) {
        if (!visited[v] && dist[v] < min) {
            min = dist[v];
            min_index = v;
        }
    }

    return min_index;
}

// 打印生成的最小生成树
void printMST(int parent[], int graph[V][V]) {
    printf("Edge \tWeight\n");
    for (int i = 1; i < V; i++)
        printf("%d - %d \t%d \n", parent[i], i, graph[i][parent[i]]);
}

// 使用Prim算法生成最小生成树
void primMST(int graph[V][V]) {
    int parent[V]; // 用于存储最小生成树中的父节点
    int dist[V]; // 用于存储顶点到最小生成树的距离
    int visited[V]; // 用于存储顶点是否已被访问

    for (int i = 0; i < V; i++) {
        dist[i] = INT_MAX;
        visited[i] = 0;
    }

    dist[0] = 0; // 选定第一个顶点作为根节点
    parent[0] = -1; // 根节点没有父节点

    for (int count = 0; count < V-1; count++) { // 需要选择V-1个边
        int u = minDistance(dist, visited); // 找到距离最小的顶点
        visited[u] = 1; // 标记已访问

        for (int v = 0; v < V; v++) {
            if (graph[u][v] && !visited[v] && graph[u][v] < dist[v]) {
                // 如果顶点未访问过且与u相邻的边的权重小于dist[v]
                parent[v] = u; // 将u作为v的父节点
                dist[v] = graph[u][v]; // 更新dist[v]
            }
        }
    }

    printMST(parent, graph); // 打印生成的最小生成树
}

int main() {
    int graph[V][V] = {{0, 2, 0, 6, 0},
                       {2, 0, 3, 8, 5},
                       {0, 3, 0, 0, 7},
                       {6, 8, 0, 0, 9},
                       {0, 5, 7, 9, 0}};
    // 以邻接矩阵的形式表示图

    primMST(graph); // 生成最小生成树

    return 0;
}

注释如下:

  1. #include <stdio.h> 和 `#include
  2. #define V 5 定义了图中顶点的个数为5。
  3. int minDistance(int dist[], int visited[]) 函数用于找到顶点集合中未访问的顶点中距离最小的顶点。输入参数 dist 用于存储顶点到最小生成树的距离,输入参数 visited 用于存储顶点是否已被访问。
  4. int min = INT_MAX, min_index; 定义 min 和 min_index 用于存储距离最小的顶点。
  5. for (int v = 0; v < V; v++) 循环遍历所有顶点。
  6. if (!visited[v] && dist[v] < min) 如果顶点未访问过且距离小于 min。
  7. min = dist[v]; min_index = v; 更新距离最小的顶点。
  8. return min_index; 返回距离最小的顶点。
  9. void printMST(int parent[], int graph[V][V]) 函数用于打印生成的最小生成树。输入参数 parent 用于存储最小生成树中的父节点,输入参数 graph 用于表示图。
  10. printf(“Edge \tWeight\n”); 打印表头。
  11. for (int i = 1; i < V; i++) 循环遍历所有顶点,从第二个顶点开始。
  12. printf(“%d - %d \t%d \n”, parent[i], i, graph[i][parent[i]]); 打印边的信息。
  13. void primMST(int graph[V][V]) 函数用于使用Prim算法生成最小生成树。输入参数 graph 用于表示图。
  14. int parent[V], dist[V], visited[V]; 定义 parent,dist 和 visited 数组用于存储最小生成树中的父节点、顶点到最小生成树的距离和顶点是否已被访问。
  15. for (int i = 0; i < V; i++) 初始化 dist 和 visited 数组。
  16. dist[0] = 0; parent[0] = -1; 选定第一个顶点作为根节点,根节点没有父节点。
  17. for (int count = 0; count < V-1; count++) 需要选择V-1个边。
  18. int u = minDistance(dist, visited); visited[u] = 1; 找到距离最小的顶点,并标记已访问。
  19. for (int v = 0; v < V; v++) 循环遍历所有顶点。
  20. if (graph[u][v] && !visited[v] && graph[u][v] < dist[v]) 如果顶点未访问过且与u相邻的边的权重小于dist[v]。
  21. parent[v] = u; dist[v] = graph[u][v]; 更新最小生成树中的父节点和顶点到最小生成树的距离。
  22. printMST(parent, graph); 打印最小生成树。
  23. int main() 主函数。
  24. int graph[V][V] = {{0, 2, 0, 6, 0}, 定义图。
  25. primMST(graph); 使用Prim算法生成最小生成树。

以上是Prim算法的C语言代码和相关讲解和注释,希望能对你有所帮助。




以下是Kruskal算法的C语言代码和注释:文章来源地址https://www.toymoban.com/news/detail-769501.html

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_VERTEX_NUM 100 // 最大顶点数
#define MAX_EDGE_NUM 100   // 最大边数

// 边的结构体,包含起点、终点和边权重值
typedef struct {
  int u, v;   // 边的起点和终点
  int weight; // 边的权重值
} Edge;

// 图的结构体,包含顶点数、边数和边的集合
typedef struct {
  int vexnum, edgenum; // 图的顶点数和边数
  Edge edges[MAX_EDGE_NUM]; // 图的边的集合
} Graph;

// 并查集的结构体
typedef struct {
  int *parent; // 并查集的父节点数组
  int size;    // 并查集的大小
} UnionFind;

// 初始化并查集
void initUnionFind(UnionFind *uf, int size) {
  uf->size = size;
  uf->parent = (int *)malloc(sizeof(int) * size);

  // 将每个节点的父节点初始化为自身
  for (int i = 0; i < size; i++) {
    uf->parent[i] = i;
  }
}

// 查找节点的祖先节点
int find(UnionFind *uf, int x) {
  if (uf->parent[x] == x) {
    return x;
  } else {
    // 路径压缩
    uf->parent[x] = find(uf, uf->parent[x]);
    return uf->parent[x];
  }
}

// 合并两个集合
void unionSet(UnionFind *uf, int x, int y) {
  int x_root = find(uf, x);
  int y_root = find(uf, y);

  if (x_root != y_root) {
    uf->parent[x_root] = y_root;
  }
}

// 比较两个边的权重值,用于排序
int cmp(const void *a, const void *b) {
  Edge *e1 = (Edge *)a;
  Edge *e2 = (Edge *)b;
  return e1->weight - e2->weight;
}

// Kruskal算法生成最小生成树
void kruskal(Graph *graph) {
  UnionFind uf;
  initUnionFind(&uf, graph->vexnum); // 初始化并查集

  int count = 0;
  Edge result[MAX_EDGE_NUM]; // 保存最小生成树的边集合

  // 对边进行排序
  qsort(graph->edges, graph->edgenum, sizeof(Edge), cmp);

  // 依次选择每一条边,如果两个端点不在同一个集合中,则将它们合并,并将边加入最小生成树的边集合中
  for (int i = 0; i < graph->edgenum; i++) {
	Edge e = graph->edges[i];
	if (find(&uf, e.u) != find(&uf, e.v)) {
  unionSet(&uf, e.u, e.v);
  result[count++] = e;
}

// 如果已经找到了n-1条边,就可以停止了
if (count == graph->vexnum - 1) {
  break;
}
}

// 输出最小生成树的边集合
printf("The minimum spanning tree:\n");
for (int i = 0; i < count; i++) {
printf("(%d, %d): %d\n", result[i].u, result[i].v, result[i].weight);
}
}

int main() {
Graph graph;
printf("Please input the number of vertices and edges:\n");
scanf("%d%d", &graph.vexnum, &graph.edgenum);

// 读入每一条边的起点、终点和权重值
printf("Please input each edge's start vertex, end vertex and weight:\n");
for (int i = 0; i < graph.edgenum; i++) {
scanf("%d%d%d", &graph.edges[i].u, &graph.edges[i].v, &graph.edges[i].weight);
}

kruskal(&graph); // 生成最小生成树

return 0;
}

到了这里,关于C语言实现最小生成树算法:Prim和Kruskal的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Prim算法实现最小生成树

    例如:要在n个城市之间铺设光缆,主要目标是要使这n个城市的任意两个之间都可以通信,但铺设光缆的费用很高,且各个城市之间铺设光缆的费用不同,因此另一个目标是要使铺设光缆的总费用最低。这就需要找到带权的最小生成树。 将图中所有顶点分为两类:树顶点(已

    2024年02月11日
    浏览(42)
  • 用prim和kruskal算法求最小生成树问题

    题目 http://ybt.ssoier.cn:8088/problem_show.php?pid=1350 信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn) http://ybt.ssoier.cn:8088/problem_show.php?pid=1391 相当于一个图中求最小生成树的问题 prim解决 kruskal解法 信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn) http://ybt.ssoier.cn:8088/problem_show.ph

    2024年02月09日
    浏览(37)
  • 使用邻接矩阵实现最小生成树Prim算法 题目编号:1135

    用邻接矩阵存储无向图,实现最小生成树Prim算法,图中边的权值为整型,顶点个数少于10个。 部分代码提示: #include using namespace std; const int MaxSize = 10; const int INF = 32767; class MGraph { public: MGraph(char a[], int n, int e); private: char vertex[MaxSize]; int arc[MaxSize][MaxSize]; int vertexNum, arcNum; }

    2024年02月06日
    浏览(39)
  • 考研算法复试刷题19天:Prim算法求最小生成树 【prim,最小生成树】

    参考博客:图解:什么是最小生成树? - 知乎 (zhihu.com)  总结下来的过程就是,一张图,我们将他化为树的形式,也就是生成树。那么最小生成树有是啥呢? 所谓一个 带权图 的最小生成树,就是原图中边的权值最小的生成树 ,所谓最小是指边的权值之和小于或者等于其它

    2024年02月07日
    浏览(63)
  • 最小生成树—Prim算法

    我们要讨论的问题是如何在一个 无向图 中找到它的最小生成树,虽然这个问题对有向图也有意义,但是处理起来更麻烦。 一个无向图 G 的最小生成树就是连接 G 上所有顶点的边构成的树,且这些边的总权值最低。当且仅当图是 连通的 才有最小生成树。 在无向图的最小生成

    2024年02月09日
    浏览(48)
  • Prim算法求最小生成树

    给定一张边带无权的无向图G = (V, E), n = |V|, m = |E|。由V中全部n个顶点和E中n - 1条边构成的无向连通子图被称为G的一课生成树。边的权值之和最小的生成树被称为无向图的最小生成树。 Prim算法总是维护最小生成树的一部分。最初,Prim算法仅确定1号节点属于最小生成树

    2024年02月12日
    浏览(42)
  • 最小生成树(Prim算法,Kruskal算法)

    (1)生成树: 如果在一个无向连通图不包含回路(连通图中不存在环),则为一个树 (2)最小生成树(minimal spanning tree): 在一个图所有生成树中,代价最小的生成树称为最小生成树 (3)生成树的代价: 在一个无向连通网中,生成树各边的权值之和称为该生成树的代价

    2024年02月08日
    浏览(43)
  • 最小生成树——Prim算法(详细图解)

    目录  最小生成树的概念   经典题目 prim算法简介  prim算法解析 (详细图解)  代码实现  代码实战 在一给定的无向图G = (V, E) 中,(u, v) 代表连接顶点 u 与顶点 v 的边,而 w(u, v) 代表此的边权重,若存在 T 为 E 的子集(即)且为无循环图,使得的 w(T) 最小,则此 T 为 G 的

    2023年04月09日
    浏览(39)
  • 图的最小生成树-Prim算法

    目录 问题引入  程序设计  程序分析 本节文章 【问题描述】 编写程序,利用带权无向图的邻接矩阵存储,实现图的最小生成树Prim算法。 【输入形式】 输入图的顶点序列及图的边的情况。如样例所示。边的输入以输入-1,-1,-1,作为结束。 0,1,6 表示对应的顶点及边是:

    2024年02月08日
    浏览(51)
  • 最小生成树——普利姆(Prim)算法

    构成连通网的最小代价生成树称为最小生成树(Minimun Cost Spanning Tree). 最小生成树可以运用到生活中,假如你是一位工程师,需要为一个镇的九个村庄架设通信网络做设计,村庄位置大值如下图:  其中 V0~V8 是村庄,之间连线的数字表示村与村间的可通达的直线距离,比如

    2024年02月04日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包