Prim算法
来源:互联网 发布:东北师大网络教育2018 编辑:程序博客网 时间:2024/06/09 17:55
普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树。意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (graph theory)),且其所有边的权值之和亦为最小。
它是从点的方面考虑构建一颗MST,大致思想是:设图G顶点集合为U,首先任意选择图G中的一点作为起始点a,将该点加入集合V,再从集合U-V中找到另一点b使得点b到V中任意一点的权值最小,此时将b点也加入集合V;以此类推,现在的集合V={a,b},再从集合U-V中找到另一点c使得点c到V中任意一点的权值最小,此时将c点加入集合V,直至所有顶点全部被加入V,此时就构建出了一颗MST。因为有N个顶点,所以该MST就有N-1条边,每一次向集合V中加入一个点,就意味着找到一条MST的边。
如下图:
过程示意图:
(1)
(2)
(3)
(4)
(5)
(6)
(7)
(8)
即,首先选择一个结点作为起始点,在起始点附近寻找一个没有被收录的、距离最小的点,记录dist等信息,之后将其收录到另一个图中,dist[] =0表示已经收录,更新原来的图的dist,一直循环知道遍历所有结点。
代码如下:
// Prim.cpp : 定义控制台应用程序的入口点。#include "stdafx.h"#include "stdio.h"#include "stdlib.h"#define INFINITY 65535#define MaxVertexNum 100typedef int Vertex;typedef int WeightType;typedef char DataType;Vertex path[MaxVertexNum];/*邻接矩阵图(结点)的定义*/typedef struct GNode *PtrToGNode;struct GNode { int Nv; int Ne; WeightType G[MaxVertexNum][MaxVertexNum]; DataType Data[MaxVertexNum];};typedef PtrToGNode MGraph;/*边的定义*/typedef struct ENode *PtrToENode;struct ENode { Vertex V1, V2; WeightType Weight;};typedef PtrToENode Edge;/* 邻接点的定义 */typedef struct AdjVNode *PtrToAdjVNode;struct AdjVNode { Vertex AdjV; /* 邻接点下标 */ WeightType Weight; PtrToAdjVNode Next;};/*定点表头结点的定义*/typedef struct VNode { PtrToAdjVNode FirstEdge; /*边表头指针*/ DataType Data; /* 存顶点的数据 */}AdjList[MaxVertexNum]; /* AdjList是邻接表类型 */ /*邻接表图定义*/typedef struct G_Node *PtrToG_Node;struct G_Node { int Nv; int Ne; AdjList G;};typedef PtrToG_Node LGraph;/*初始化生成图*/MGraph CreateGraph(int Num_Vertex){ MGraph Graph; Vertex V, W; Graph = (MGraph)malloc(sizeof(struct GNode)); Graph->Nv = Num_Vertex; Graph->Ne = 0; for (V = 0; V < Graph->Nv; V++) { for (W = 0; W < Graph->Nv; W++) { Graph->G[V][W] = INFINITY; } } return Graph;}/*将得到的边数据保存到图*/void InsertEdge(MGraph Graph, Edge E){ Graph->G[E->V1][E->V2] = E->Weight; Graph->G[E->V2][E->V1] = E->Weight;}/*生成完整图*/MGraph BuildGraph(){ MGraph Graph; Edge E; int Nv, i; //Vertex V; printf("Input the number of Vertex\n"); scanf_s("%d", &Nv); Graph = CreateGraph(Nv); printf("Input the number of Edge\n"); scanf_s("%d", &Graph->Ne); if (Graph->Ne != 0) { E = (Edge)malloc(sizeof(struct ENode)); for (i = 0; i < Graph->Ne; i++) { printf("input E->V1,E->V2,E->Weight\n"); scanf_s("%d %d %d", &E->V1, &E->V2, &E->Weight); InsertEdge(Graph, E); } } for (Vertex i = 0; i < Graph->Nv; i++) { for (Vertex j = 0; j < Graph->Nv; j++) { if (Graph->G[i][j] < INFINITY) { printf("Graph->G[%d][%d] = %d\n", i, j,Graph->G[i][j]); } } } /*printf("input the DataType\n"); for (V = 0; V<Graph->Nv; V++) { scanf_s(" %c", &Graph->Data[V]); }*/ return Graph;}Vertex FindMinDist(MGraph Graph, WeightType dist[]){ Vertex MinV, V; WeightType MinDist = INFINITY; for (V = 0; V < Graph->Nv; V++) { if (dist[V] != 0 && dist[V] < MinDist) { MinDist = dist[V]; MinV = V; } } if (MinDist < INFINITY) { return MinV; } else return -1;}int Prim(MGraph Graph, MGraph &MST)/*这里传引用,为了确保传进来的MST里面的东西同步更新,最好传引用*/{ WeightType dist[MaxVertexNum], TotalWeight; Vertex parent[MaxVertexNum], V, W; Vertex i_position = 0; int VCount; Edge E; /* 初始化,默认初始点下标是0 */ for (V = 0; V < Graph->Nv; V++) { /* 这里假设若V到W没有直接的边,则Graph->G[V][W]定义为INFINITY */ dist[V] = Graph->G[0][V]; parent[V] = 0; /* 暂且定义所有顶点的父结点都是初始点0 */ } TotalWeight = 0; VCount = 0; //MST = CreateGraph(Graph->Nv); /*如果这里再定义一次,相当于将指针指向别处, 类似于传进函数的一级指针指向别的地方,MST在函数内修改,而出了函数体, 相当于没有对MST做修改,如果传引用则无需考虑这些,因为他们是捆绑在一起的*/ E = (Edge)malloc(sizeof(struct ENode)); dist[0] = 0; parent[0] = -1; VCount++; path[i_position] = 0; i_position++; for (Vertex i = 1; i < Graph->Nv; i++) { /*Vertex从1开始,因为最开始的结点(0结点)已经被收录,故只需再收录Nv-1个结点*/ V = FindMinDist(Graph, dist); if (V == -1) break; E->V1 = parent[V]; E->V2 = V; E->Weight = dist[V]; InsertEdge(MST, E); for (int m = 0; m < MST->Nv; m++) { for (int n = 0; n < MST->Nv; n++) { printf("MST->G[%d][%d] = %d\n", m, n, MST->G[m][n]); /*if (MST->G[W][V] < INFINITY) { printf("MST->G[%d][%d] = %d\n", V, W, MST->G[V][W]); }*/ } } TotalWeight += dist[V]; dist[V] = 0; VCount++; path[i_position] = V; i_position++; for (W = 0; W < Graph->Nv; W++) { if (dist[W] != 0 && Graph->G[V][W] < INFINITY) { /* 若W是V的邻接点并且未被收录 */ if (Graph->G[V][W] < dist[W]) { /* 若收录V使得dist[W]变小 */ dist[W] = Graph->G[V][W]; /* 更新dist[W] */ parent[W] = V; /* 更新树 */ } } } } if (VCount < Graph->Nv) { TotalWeight = -1; } return TotalWeight;}void PrintPath(int Nv){ for (Vertex V = 0; V < Nv; V++) printf("%d ", path[V]);}int main(){ Vertex V,W; MGraph Graph = BuildGraph(); MGraph MST = CreateGraph(Graph->Nv); int Weight = Prim(Graph, MST); /*上面函数调用传引用是为了保证传进去的MST能够同步跟新*/ printf("%d\n", Weight); PrintPath(MST->Nv); printf("\n"); printf("Vertex's number of Graph MST %d\n", MST->Nv); for (V = 0; V < MST->Nv; V++) { for (W = 0; W < MST->Nv; W++) { printf("MST->G[%d][%d] = %d\n", V, W, MST->G[V][W]); /*if (MST->G[W][V] < INFINITY) { printf("MST->G[%d][%d] = %d\n", V, W, MST->G[V][W]); }*/ } } return 0;}
阅读全文
0 0
- prim 算法
- Prim算法
- Prim算法
- prim算法
- Prim算法
- Prim算法。
- Prim 算法
- Prim算法
- prim算法
- Prim算法
- Prim算法
- Prim算法
- prim算法
- prim算法
- Prim算法
- Prim算法
- prim算法
- prim算法
- 【ZOJ3778】【C++心路历程40】【厨师】【贪心】【思路题】
- 欢迎使用CSDN-markdown编辑器
- python 初探状态机transitions库
- 初识Mybatis
- Java Socket总结
- Prim算法
- 【温故知新-Java虚拟机篇】5.字节码执行引擎
- 左值、右值、变量类型
- 使用链表将阿拉伯数字转化为中文大写数字
- String to Integer (atoi)(算法分析week6)
- 线程的基础概念
- 音乐播放上一首下一首 //借鉴
- SDUT 2144 图结构练习——最小生成树
- java swing 界面设计-复选框