最小生成树kruskal算法适合稀疏图(网络整理)8.1.3
来源:互联网 发布:淘宝上小提琴教学视频 编辑:程序博客网 时间:2024/06/07 03:04
上一篇实现了prim算法,适合稠密图,这次来实现另一种算法KRUSKAL算法
#include<stdio.h>#include<stdlib.h>#include<stdbool.h>#define MAXSIZE 100typedef int Weight;typedef char Datatype; typedef struct AdjVNode{Weight weight;int adjv;struct AdjVNode *Next;}*PtrToAdjVNode;typedef struct Vnode{Datatype data;PtrToAdjVNode FirstEdge;/* 边表头指针 */ }AdjList[MAXSIZE];typedef struct Lnode{int Nv;int Ne;AdjList G;}*LGraph;typedef struct Enode{int v1;int v2;Weight weight;//bool flag;//true -> false ->}Edge;LGraph CreateGraph(int n){LGraph Graph=(LGraph)malloc(sizeof(struct Lnode));Graph->Nv=n;Graph->Ne=0;for(int i=0;i<n;i++){Graph->G[i].FirstEdge=NULL;}return Graph;}void InsertEdge(LGraph Graph,const Edge *ptre){PtrToAdjVNode Newnode=(PtrToAdjVNode)malloc(sizeof(struct AdjVNode));Newnode->weight=ptre->weight;Newnode->adjv=ptre->v2;Newnode->Next=Graph->G[ptre->v1].FirstEdge;Graph->G[ptre->v1].FirstEdge=Newnode;//若是无向边Newnode=(PtrToAdjVNode)malloc(sizeof(struct AdjVNode));Newnode->weight=ptre->weight;Newnode->adjv=ptre->v1;Newnode->Next=Graph->G[ptre->v2].FirstEdge;Graph->G[ptre->v2].FirstEdge=Newnode;}LGraph buildGraph(){LGraph Graph; Edge E; int V; int Nv, i; scanf("%d", &Nv); /* 读入顶点个数 */ Graph = CreateGraph(Nv); /* 初始化有Nv个顶点但没有边的图 */ scanf("%d", &(Graph->Ne)); /* 读入边数 */ if ( Graph->Ne != 0 ) { /* 如果有边 */ /* 读入边,格式为"起点 终点 权重",插入邻接矩阵 */ for (i=0; i<Graph->Ne; i++) { scanf("%d %d %d", &E.v1, &E.v2, &E.weight); /* 注意:如果权重不是整型,Weight的读入格式要改 */ InsertEdge( Graph, &E ); } } /* 如果顶点有数据的话,读入数据 */ for (V=0; V<Graph->Nv; V++) scanf(" %c", &(Graph->G[V].data)); return Graph; }/*-------------------- 边的最小堆定义 --------------------*/typedef Edge Ele;const Ele ERROR={-1,-1,-1};typedef struct heap{Ele *data;int size;int maxsize;}*MinHeap;MinHeap createMinHeap(int n){MinHeap minheap=(MinHeap)malloc(sizeof(struct heap));minheap->data=(Ele*)malloc(sizeof(Ele)*(n+1));minheap->size=0;minheap->maxsize=n;return minheap;}bool isfull(MinHeap heap){ return heap->size>=heap->maxsize;}bool isempty(MinHeap heap){if(heap==NULL)heap->size =5; return heap->size<=0;}void InsertMinHeap(MinHeap heap,Ele e){if(isfull(heap)) return;heap->size++;int i;for(i=heap->size;i>1&&e.weight<heap->data[i/2].weight;i/=2)heap->data[i]=heap->data[i/2];heap->data[i]=e;}Ele DelMinHeap(MinHeap heap){if(isempty(heap))return ERROR;Ele min=heap->data[1];Ele tmp=heap->data[heap->size--];int i=0,childmin;for(i=1;2*i<=heap->size;i=childmin){childmin=2*i;if(childmin!=heap->size&&heap->data[childmin].weight>heap->data[childmin+1].weight)childmin++;if(tmp.weight<=heap->data[childmin].weight)break; heap->data[i]=heap->data[childmin]; }heap->data[i]=tmp;return min;}void PercDown(MinHeap heap, int p){ Ele tmp = heap->data[p]; /* 取出根结点存放的值 */ int i=p,childmin;for(;2*i<=heap->size;i=childmin){childmin=2*i;if(childmin!=heap->size&&heap->data[childmin].weight>heap->data[childmin+1].weight)childmin++;if(tmp.weight<=heap->data[childmin].weight)break; heap->data[i]=heap->data[childmin]; }heap->data[i]=tmp;}MinHeap buildMinHeap(Ele e[],int n){MinHeap heap=createMinHeap(n);heap->size=n;for(int i=0;i<n;i++)heap->data[i]=e[i];for(int i=n/2;i>0;i--) PercDown(heap,i);return heap;}/*-------------------- 边的最小堆定义end --------------------*//*-------------------- 顶点并查集定义 --------------------*/typedef int ElementType; /* 默认元素可以用非负整数表示 */typedef int SetName; /* 默认用根结点的下标作为集合名称 */typedef ElementType SetType[MAXSIZE]; /* 假设集合元素下标从0开始 */ void InitializeVSet( SetType S, int N ){ /* 初始化并查集 */ int X; for ( X=0; X<N; X++ ) S[X] = -1;} void Union( SetType S, SetName Root1, SetName Root2 ){ /* 这里默认Root1和Root2是不同集合的根结点 */ /* 保证小集合并入大集合 */ //if ( S[Root2] < S[Root1] ) { /* 如果集合2比较大 */ // S[Root2] += S[Root1]; /* 集合1并入集合2 */ //S[Root1] = Root2; //} //else { /* 如果集合1比较大 */ // S[Root1] += S[Root2]; /* 集合2并入集合1 */ //S[Root2] = Root1; //}S[Root2]=Root1;} SetName Find( SetType S, ElementType X ){ /* 默认集合元素全部初始化为-1 */ if ( S[X] < 0 ) /* 找到集合的根 */ return X; else return Find( S, S[X] ); /* 路径压缩 */} bool CheckCycle( SetType VSet, int V1, int V2 ){ /* 检查连接V1和V2的边是否在现有的最小生成树子集中构成回路 */ int Root1, Root2; Root1 = Find( VSet, V1 ); /* 得到V1所属的连通集名称 */ Root2 = Find( VSet, V2 ); /* 得到V2所属的连通集名称 */ if( Root1==Root2 ) /* 若V1和V2已经连通,则该边不能要 */ return false; else { /* 否则该边可以被收集,同时将V1和V2并入同一连通集 */ Union( VSet, Root1, Root2 ); return true; }}MinHeap InitializeESet(LGraph Graph){ PtrToAdjVNode W; Edge edge;MinHeap edgeheap=createMinHeap(Graph->Ne);for (int V=0; V<Graph->Nv; V++ ) for ( W=Graph->G[V].FirstEdge; W; W=W->Next ) if ( V<W->adjv) { /* 避免重复录入无向图的边,只收V1<V2的边 */ edge.v1 = V; edge.v2 = W->adjv; edge.weight=W->weight; //printf("abc %d\n",edge.weight ); InsertMinHeap(edgeheap,edge); }return edgeheap;}Edge GetEdge( MinHeap edgeheap){ return DelMinHeap(edgeheap);}/*-------------------- 并查集定义结束 --------------------*/ int Kruskal( LGraph Graph, LGraph MST ) { /* 将最小生成树保存为邻接表存储的图MST,返回最小权重和 */ Weight TotalWeight; int ECount; SetType VSet; /* 顶点并查集 */ MinHeap edgeheap=NULL; /* 边的最小堆 */ // printf("%p\n",edgeheap );exit(0); Edge NextEdge; InitializeVSet( VSet, Graph->Nv ); /* 初始化顶点并查集 */ edgeheap=InitializeESet( Graph ); /* 初始化边的最小堆 */ /* 创建包含所有顶点但没有边的图。注意用邻接表版本 */ MST = CreateGraph(Graph->Nv); TotalWeight = 0; /* 初始化权重和 */ ECount = 0; /* 初始化收录的边数 */ while ( ECount < Graph->Nv-1 ) { /* 当收集的边不足以构成树时 */ NextEdge = GetEdge( edgeheap ); /* 从边的最小堆de到最小边 */ //printf("%d\n", NextEdge.weight); if (NextEdge.v1==-1) /* 边集已空 */ break; /* 如果该边的加入不构成回路,即两端结点不属于同一连通集 */ if ( CheckCycle( VSet, NextEdge.v1, NextEdge.v2 )==true ) { /* 将该边插入MST */ InsertEdge( MST, &NextEdge); printf("%d<->%d weight:%d collected\n",NextEdge.v1,NextEdge.v2,NextEdge.weight); TotalWeight += NextEdge.weight; /* 累计权重 */ ECount++; /* 生成树中边数加1 */ } } if ( ECount < Graph->Nv-1 ) TotalWeight = -1; /* 设置错误标记,表示生成树不存在 */ return TotalWeight; }int main(){LGraph Graph=buildGraph();LGraph MST;printf("-------------------------------------------\n");printf("TotalWeight %d",Kruskal(Graph,MST)); return 0;}
0 0
- 最小生成树kruskal算法适合稀疏图(网络整理)8.1.3
- (1.2.6.3)最小生成树--Kruskal算法:O(elog2e) 适合稀疏图
- 最小生成树prim算法适合稠密图(网络整理)8.12
- 算法整理:最小生成树(mst)-Prim+Kruskal
- 图的最小生成树Kruskal算法
- 图算法之最小生成树(Kruskal)
- 图之 最小生成树 Kruskal算法
- 图-最小生成树-kruskal算法
- 最小生成树算法(prim&kruskal)
- poj1251最小生成树(kruskal算法)
- 最小生成树 kruskal(算法)
- 最小生成树(Kruskal算法)--poj2421
- 最小生成树(kruskal算法)
- 最小生成树(Kruskal算法)
- Kruskal算法(求最小生成树)
- 最小生成树2(Kruskal算法)
- 最小生成树算法(2)------------Kruskal
- Kruskal 算法(最小生成树)
- 量化浅谈——读懂自己,然后才能写出量化
- 死变态的跳台阶——爬楼梯进阶版本
- 第五单元
- 二值网络——开启小而快神经网络时代
- Spring@Autowired注解与自动装配
- 最小生成树kruskal算法适合稀疏图(网络整理)8.1.3
- html --CSS的盒子模型
- 常量整理
- 面向对象与C++程序设计-函数模板与类模板学习笔记
- 2017 第十四届浙江acm省赛总结(退役???)
- java-jar包关联源文件
- web-xml
- linux Makefile(二)
- Angular第一天学习