最小生成树问题(数据结构与算法课设)(C语言版)

        本文为数据结构与算法课设-《最小生成树问题》课题的一个分享与讨论。采用树和图的数据结构。数据存储采用邻接矩阵

        1.设计内容和要求

设计内容:

        在n个城市(n>=5)之间建设网络,只需保证连通即可,求最经济的架设方法。存储结构采用(邻接表和邻接矩阵)两种,采用课本上的两种求解算法。

设计要求:

        (1) 符合课题要求,实现相应功能;

        (2) 要求界面友好美观,操作方便易行;

        (3) 注意程序的实用性、安全性。

2.实现思路和程序调试

        程序就是在输入数据到一个邻接矩阵中,然后根据两种算法去输出最小生成树。

(1)prim 算法

        Prim算法是一种用于在加权无向图中找到最小生成树的贪心算法。最小生成树是图中的一个子图,它包含了图中所有顶点,并且边的权重和最小。Prim算法从一个顶点开始,逐步增加边和顶点,直到形成最小生成树。

void prim(int graph[MAX][MAX], int n) {  
	// 父节点数组,用于记录最小生成树中每个节点的父节点  
	int parent[MAX];  
	// key数组用于存储从源点到每个顶点的当前最小距离估计  
	int key[MAX];  
	// mstSet用于标记顶点是否已经被包括在最小生成树中  
	bool mstSet[MAX];  
  
	// 初始化所有距离为无穷大,并标记所有顶点都未被包括在MST中  
	for (int i = 0; i < n; i++) {  
		key[i] = INT_MAX; // 假设所有距离都是无穷大  
		mstSet[i] = false; // 标记所有顶点都未被选中  
	}  
  
	// 将第一个顶点加入到MST中,并将其距离设置为0(因为它到自身的距离是0)  
	key[0] = 0;  
	parent[0] = -1; // 第一个顶点没有父节点  
  
	// 重复n-1次,每次找到一个新的顶点加入到MST中  
	for (int count = 0; count < n - 1; count++) {  
		// 寻找当前未被包括在MST中,且距离源点最近的顶点u  
		int u = -1;  
		for (int v = 0; v < n; v++) {  
			if (!mstSet[v] && (u == -1 || key[v] < key[u])) {  
				u = v;  
			}  
		}  
  
		// 将顶点u加入到MST中  
		mstSet[u] = true;  
  
		// 更新与顶点u相邻的顶点的距离估计  
		for (int v = 0; v < n; v++) {  
			// 如果顶点v未被包括在MST中,并且存在一条从u到v的边,且这条边的权重小于v当前的key值  
			if (graph[u][v] && !mstSet[v] && graph[u][v] < key[v]) {  
				parent[v] = u; // 更新v的父节点为u  
				key[v] = graph[u][v]; // 更新v的key值为u到v的权重  
			}  
		}  
	}  
  
	// 打印最小生成树中的边  
	printf("使用 Prim 算法的最小生成树中的边:\n");  
	for (int i = 1; i < n; i++) {  
		printf("%d - %d\n", parent[i], i);  
	}  
}

          Prim算法的关键在于逐步构建最小生成树,每次选择一个与当前MST中顶点集距离最小的顶点,并将其加入到MST中。这个过程中,需要不断地更新与已选顶点集相邻的未选顶点的距离估计,以便在下一轮选择时能够找到距离最小的顶点。通过这种方式,Prim算法能够确保最终得到的树是所有可能树中权重和最小的。

(2)Kruskal算法

        这段代码实现的是Kruskal算法,它是一种用于在加权无向图中找到最小生成树的算法。最小生成树是图中的一个子图,它包含了图中所有顶点,并且边的权重和最小。Kruskal算法通过逐步添加边来构建最小生成树,但每次添加边时都会检查是否会形成环。      

// 查找根节点的函数,实现路径压缩  
int find(int parent[], int i) {  
    if (parent[i] != i) {  
        parent[i] = find(parent, parent[i]); // 路径压缩,将路径上的所有节点都直接指向根节点  
    }  
    return parent[i];  
}  
  
// 合并两个集合,按秩合并(根据树的深度或节点数来合并)  
void unionSet(int parent[], int rank[], int x, int y) {  
    int xroot = find(parent, x);  
    int yroot = find(
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
最小生成树(Minimum Spanning Tree,简称MST)是图论中的一个重要概念,用于解决连通图的最小权重生成树问题。在C语言中,可以通过使用邻接矩阵或邻接表来表示图,并使用适当的算法来计算最小生成树。 以下是一个简单的C语言实现最小生成树的示例: ```c #include <stdio.h> #include <stdbool.h> #define MAX_VERTICES 100 #define INF 9999 // 邻接矩阵表示图 typedef struct { int vertices[MAX_VERTICES][MAX_VERTICES]; int numVertices; } Graph; // 初始化图 void initGraph(Graph* graph, int numVertices) { graph->numVertices = numVertices; for (int i = 0; i < numVertices; i++) { for (int j = 0; j < numVertices; j++) { graph->vertices[i][j] = INF; } } } // 添加边 void addEdge(Graph* graph, int src, int dest, int weight) { graph->vertices[src][dest] = weight; graph->vertices[dest][src] = weight; } // 寻找最小生成树 void primMST(Graph* graph) { int parent[MAX_VERTICES]; // 记录最小生成树的父节点 int key[MAX_VERTICES]; // 记录顶点的权重 bool mstSet[MAX_VERTICES]; // 记录顶点是否已经加入最小生成树 // 初始化key和mstSet for (int i = 0; i < graph->numVertices; i++) { key[i] = INF; mstSet[i] = false; } // 第一个顶点作为起始点 key[0] = 0; parent[0] = -1; for (int count = 0; count < graph->numVertices - 1; count++) { int minKey = INF; int minIndex; // 选择权重最小的顶点 for (int v = 0; v < graph->numVertices; v++) { if (mstSet[v] == false && key[v] < minKey) { minKey = key[v]; minIndex = v; } } mstSet[minIndex] = true; // 更新相邻顶点的权重和父节点 for (int v = 0; v < graph->numVertices; v++) { if (graph->vertices[minIndex][v] != INF && mstSet[v] == false && graph->vertices[minIndex][v] < key[v]) { parent[v] = minIndex; key[v] = graph->vertices[minIndex][v]; } } } // 打印最小生成树 printf("Edge \tWeight\n"); for (int i = 1; i < graph->numVertices; i++) { printf("%d - %d \t%d\n", parent[i], i, graph->vertices[i][parent[i]]); } } int main() { Graph graph; int numVertices, numEdges; printf("Enter the number of vertices: "); scanf("%d", &numVertices); initGraph(&graph, numVertices); printf("Enter the number of edges: "); scanf("%d", &numEdges); for (int i = 0; i < numEdges; i++) { int src, dest, weight; printf("Enter edge %d (source, destination, weight): ", i + 1); scanf("%d %d %d", &src, &dest, &weight); addEdge(&graph, src, dest, weight); } primMST(&graph); return 0; } ``` 这个示例使用了Prim算法来计算最小生成树。用户需要输入图的顶点数和边数,以及每条边的起始顶点、目标顶点和权重。程序将输出最小生成树的边及其权重。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值