zoukankan      html  css  js  c++  java
  • 最小生成树之Prim算法和Kruskal算法

    本博客的代码的思想和图片参考:好大学慕课浙江大学陈越老师、何钦铭老师的《数据结构》

    1 最小生成树的概念

    最小生成树的概念:是由图生成而来的

    是一棵树

    1.无回路

    2.如果有V个定点就有V-1条边

    是生成树

    1.包含图中所有的节点V

    2.V-1条边都在图里面

    3.边的权重和最小。

    4.向生成树中添加任意一条边都构成回路。


    2 算法思想:贪心算法

    “贪”:每一步都要最好的。

    “好”:权重最小的边

    约束条件:

    1.只能使用图里面的边

    2.只能正好使用V-1条边

    3.不能有回路


    3 Prim算法—让一棵小树慢慢长大

    3.1算法思想:

    1.先选择一个顶点作为树的根节点,把这个根节点当成一棵树

    2.选择图中距离这棵树最近但是没有被树收录的一个顶点,把他收录在树中,并且保证不构成回路

    3.按照这样的方法,把所有的图的顶点一一收录进树中。

    4.如果没有顶点可以收录

    a.如果图中的顶点数量等于树的顶点数量-->最小生成树构造完成

    b. 如果图中的顶点数量不等于树的顶点数量-->此图不连通

    下面使用图片来具体描述此算法的算法思想:


     3.2Prim算法的伪代码描述

    通过我们对算法的描述,我们发现Prim算法和Dijkstra算法很类似

    void Prim()

    {

      MST = {s};

    while (1) {

    V = 未收录顶点中dist最小者;

    if ( 这样的V不存在 )

    break;

    V收录进MST: dist[V] = 0;

    for ( V 的每个邻接点 W )

    if ( dist[W]!=W未被收录 0 )

    if ( E (V,W) < dist[W] ){

    dist[W] = E (V,W) ;

    parent[W] = V;

    }

    }

    if ( MST中收的顶点不到|V|)

    Error ( “生成树不存在” );

    }

    对于Prim算法

    1.dist代表的是什么,应该如何被初始化

    dist代表距离当前生成树的最小距离。和根节点直接相邻的初始化为权重,其他的初始化为正无穷。等每插入一个树节点,对dist进行更新。对于已经收录的节点,更新其dist=0

    2.该算法的时间复杂度是多少

    该算法时间复杂度在于如何去 ”未收录顶点中dist最小者”如果是使用暴力搜索的方法,那么时间复杂的为T=O(n^2).此种算法对于稠密图比较适用。

    4 Kruskal 算法—将树合并成森林

    4.1 算法思想

    使用贪心算法,每次获取权重最小的边,但是不能让生成树构成回路。直到去到V-1条边为止。

    下面还是使用一个图来说明次算法

    伪代码描述



    void Kruskal ( Graph G )

    {

    MST = { } ;

    while ( MST 中不到 |V| 1 条边 && E 中还有边 ) {

    E 中取一条权重最小的边 E (v,w) ; /* 最小堆 */

    E (v,w) E 中删除;

    if ( E (V,W) 不在 MST 中构成回路) /* 并查集 */

    E (V,W) 加入 MST;

    else

    彻底无视 E (V,W) ;

    }

    }

    if ( MST 中不到 |V| 1 条边 )

    Error ( “生成树不存在” );

    }

    如何实现“从 E 中取一条权重最小的边 E (v,w) ”---->最小堆

    如何判断是否产生回路------>” 并查集”

    此算法的时间复杂的为T=O(ELogE),次算法对稀疏图比较友好. 如果改图是稠密图,那么E=v^2

    时间复杂度和Prim算法差不多



    5 习题

    下面通过一道练习题来比较Prim算法和Kruskal算法的优劣

    题目的PTA链接

    https://pta.patest.cn/pta/test/3512/exam/4/question/85491

    题目内容:

    5.1题目内容:

    现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本。

    输入格式:

    输入数据包括城镇数目正整数N(≤1000)和候选道路数目M(≤3N);随后的M行对应M条道路,每行给出3个正整数,分别是该条道路直接连通的两个城镇的编号以及该道路改建的预算成本。为简单起见,城镇从1N编号。

    输出格式:

    输出村村通需要的最低成本。如果输入数据不足以保证畅通,则输出−1,表示需要建设更多公路。

    输入样例:

    6 15
    1 2 5
    1 3 3
    1 4 7
    1 5 4
    1 6 2
    2 3 4
    2 4 6
    2 5 2
    2 6 6
    3 4 6
    3 5 1
    3 6 1
    4 5 10
    4 6 8
    5 6 3

    输出样例:

    12

    代码可以在最后的链接里面



    5.2 比较Prim算法和Kruskal算法

    上面的习题其实很简单,就是Prim算法和Kruskal算法的应用。很简单,只需要改一下输出即可。

    Prim算法在PTA的运行结果:



    Kruskal算法在PTA的运行结果:

    5.2.1空间复杂的比较

    从内存的使用情况来看,Prim算法使用的邻接矩阵来存储图,Kruskal算法使用邻接表来存储图,从图中可以看出,邻接矩阵在最N时内存由1M增长到8M,而邻接表的内存始终是在1M。由此可见在同等的数据量的情况下,邻接表比邻接矩阵更加节省内存空间。

    5.2.2 时间复杂的比较

    就本题的测试结果来看,Kruskal算法的时间复杂度是优于Prim算法的。本题的N最大为1000

    M(edge)最大为3N,远远比不上稠密图M=N^2,只能算是稀疏图。所以在稀疏图的情况下,Kruskal算法时间复杂的度较好。和理论的证明一致。

    Prim算法求最小生成树的权重和打印路径代码:

      1 /*
      2  * prim.c
      3  *
      4  *  Created on: 2017年5月15日
      5  *      Author: ygh
      6  */
      7 #include <stdio.h>
      8 #include <stdlib.h>
      9 
     10 #define MAX_VERTEX_NUM 100 /*define the max number of the vertex*/
     11 #define INFINITY 65535     /*define double byte no negitive integer max number is 65535*/
     12 #define ERROR -1
     13 
     14 typedef int vertex; /*define the data type of the vertex*/
     15 typedef int weightType; /*define the data type of the weight*/
     16 typedef char dataType; /*define the data type of the vertex value*/
     17 
     18 /*define the data structure of the Edge*/
     19 typedef struct eNode *ptrToENode;
     20 typedef struct eNode {
     21     vertex v1, v2; /*two vertex between the edge <v1,v2>*/
     22     weightType weight; /*the value of the edge's weight */
     23 };
     24 typedef ptrToENode edge;
     25 
     26 /*==================A adjacent matrix to describe a graph=========================================*/
     27 
     28 /*define the data structure of the graph*/
     29 typedef struct gMNode *ptrTogMNode;
     30 typedef struct gMNode {
     31     int vertex_number; /*the number of the vertex*/
     32     int edge_nunber; /*the number of the edge*/
     33     weightType g[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; /*define the adjacent matrix weight of graph*/
     34     dataType data[MAX_VERTEX_NUM]; /*define the dataType array to store the value of vertex*/
     35 };
     36 typedef ptrTogMNode adjacentMatrixGraph; /*a graph show by adjacent matrix*/
     37 
     38 /*
     39  create a graph given the vertex number.
     40  @param vertexNum The verter number of the graph
     41  @return a graph with vertex but no any egdgs
     42  */
     43 adjacentMatrixGraph createMGraph(int vertexNum) {
     44     vertex v, w;
     45     adjacentMatrixGraph graph;
     46     graph = (adjacentMatrixGraph) malloc(sizeof(struct gMNode));
     47     graph->vertex_number = vertexNum;
     48     graph->edge_nunber = 0;
     49     /*initialize the adjacent matrix*/
     50     for (v = 0; v < graph->vertex_number; v++) {
     51         for (w = 0; w < graph->vertex_number; w++) {
     52             graph->g[v][w] = INFINITY;
     53         }
     54     }
     55 
     56     return graph;
     57 }
     58 
     59 /*
     60  insert a edge to graph.We will distinct oriented graph and undirected graph
     61  @param graph The graph you want to insert edge
     62  @param e The edge you want to insert the graph
     63  @param isOriented Whether the graph is oriented graph.If the graph is oriented
     64  we will set adjacent matrix [n][m]=[m][n]=edge's weight,else we only set
     65  the adjacent matrix [n][m]=edge's weight
     66  */
     67 void inserEdgeToMatrix(adjacentMatrixGraph graph, edge e, int isOriented) {
     68     graph->g[e->v1][e->v2] = e->weight;
     69     if (!isOriented) {
     70         graph->g[e->v2][e->v1] = e->weight;
     71     }
     72 }
     73 
     74 /*
     75  construct a graph according user's input
     76 
     77  @return a graph has been filled good
     78  */
     79 adjacentMatrixGraph buildMGraph(int isOrdered) {
     80     adjacentMatrixGraph graph;
     81     edge e;
     82     vertex i;
     83     int vertex_num;
     84     scanf("%d", &vertex_num);
     85     graph = createMGraph(vertex_num);
     86     scanf("%d", &(graph->edge_nunber));
     87     if (graph->edge_nunber) {
     88         e = (edge) malloc(sizeof(struct eNode));
     89         for (i = 0; i < graph->edge_nunber; i++) {
     90             scanf("%d %d %d", &e->v1, &e->v2, &e->weight);
     91             e->v1--;
     92             e->v2--;
     93             inserEdgeToMatrix(graph, e, isOrdered);
     94         }
     95     }
     96     return graph;
     97 
     98 }
     99 
    100 /*==================A adjacent link to describe a graph=========================================*/
    101 /*define the data structure adjacent table node*/
    102 typedef struct adjNode *ptrToAdjNode;
    103 typedef struct adjNode {
    104     vertex adjVerx; /*the index of the vertex*/
    105     weightType weight; /*the value of the weight*/
    106     ptrToAdjNode next; /*the point to point the next node*/
    107 };
    108 
    109 /*define the data structure of the adjacent head*/
    110 typedef struct vNode *ptrToVNode;
    111 typedef struct vNode {
    112     ptrToAdjNode head; /*the point to point the adjacent table node*/
    113     dataType data; /*the space to store the name of the vertex,but some time the vertex has no names*/
    114 } adjList[MAX_VERTEX_NUM];
    115 
    116 /*define the data structure of graph*/
    117 typedef struct gLNode *ptrTogLNode;
    118 typedef struct gLNode {
    119     int vertex_number; /*the number of the vertex*/
    120     int edge_nunber; /*the number of the edge*/
    121     adjList g; /*adjacent table*/
    122 };
    123 typedef ptrTogLNode adjacentTableGraph; /*a graph show by adjacent table*/
    124 
    125 /*
    126  create a graph given the vertex number.
    127  @param vertexNum The verter number of the graph
    128  @return a graph with vertex but no any egdgs
    129  */
    130 adjacentTableGraph createLGraph(int vertexNum) {
    131     adjacentTableGraph graph;
    132 
    133     vertex v;
    134     graph = (adjacentTableGraph) malloc(sizeof(struct gLNode));
    135     graph->vertex_number = vertexNum;
    136     graph->edge_nunber = 0;
    137     /*initialize the adjacent table*/
    138     for (v = 0; v < graph->vertex_number; v++) {
    139         graph->g[v].head = NULL;
    140     }
    141     return graph;
    142 }
    143 
    144 /*
    145  insert a edge to graph.We will distinct oriented graph and undirected graph
    146  The e->v1 and e->v2 are the vertexs' indexs in the adjacent table
    147  @param graph The graph you want to insert edge
    148  @param e The edge you want to insert the graph
    149  @param isOriented Whether the graph is oriented graph.If the graph is oriented
    150  we will set adjacent table graph[v1]->head=v2 and set graph[v1].head=v2
    151  otherwise we only set graph[v1].head=v2
    152  */
    153 void insertEdgeToLink(adjacentTableGraph graph, edge e, int isOriented) {
    154     /*build node<v1,v2>*/
    155     ptrToAdjNode newNode;
    156     newNode = (ptrToAdjNode) malloc(sizeof(struct adjNode));
    157     newNode->adjVerx = e->v2;
    158     newNode->weight = e->weight;
    159     newNode->next = graph->g[e->v1].head;
    160     graph->g[e->v1].head = newNode;
    161     /*if the graph is directed graph*/
    162     if (!isOriented) {
    163         newNode = (ptrToAdjNode) malloc(sizeof(struct adjNode));
    164         newNode->adjVerx = e->v1;
    165         newNode->weight = e->weight;
    166         newNode->next = graph->g[e->v2].head;
    167         graph->g[e->v2].head = newNode;
    168     }
    169 }
    170 
    171 /*
    172  build a graph stored by adjacent table
    173  */
    174 adjacentTableGraph buildLGraph() {
    175     adjacentTableGraph graph;
    176     edge e;
    177     vertex i;
    178     int vertex_num;
    179 
    180     scanf("%d", &vertex_num);
    181     graph = createLGraph(vertex_num);
    182     scanf("%d", &(graph->edge_nunber));
    183     if (graph->edge_nunber) {
    184         e = (edge) malloc(sizeof(struct eNode));
    185         for (i = 0; i < graph->edge_nunber; i++) {
    186             scanf("%d %d %d", &e->v1, &e->v2, &e->weight);
    187             insertEdgeToLink(graph, e, 0);
    188         }
    189     }
    190 
    191     return graph;
    192 }
    193 
    194 /*
    195  * Find the minimal node closest to created tree
    196  */
    197 vertex findMinDist(adjacentMatrixGraph graph, weightType dist[]) {
    198     vertex minV, v;
    199     weightType minDist = INFINITY;
    200     for (v = 0; v < graph->vertex_number; v++) {
    201         if (dist[v] != 0 && dist[v] < minDist) {
    202             minDist = dist[v];
    203             minV = v;
    204         }
    205     }
    206     if (minDist < INFINITY) {
    207         return minV;
    208     } else {
    209         return ERROR;
    210     }
    211 }
    212 
    213 /*
    214  * Prim algorithms,we will store the minimal created tree with a adjacent
    215  * list table and return the minimal weight
    216  * @param mGraph The graph showed by adjacent matrix is to store graph
    217  * @param lGraph The graph showed by adjacent list is to store the minimal created tree
    218  * @return The weight of the minimal created tree if the graph is connected, otherwise return
    219  * <code>ERROR</code>
    220  */
    221 int prim(adjacentMatrixGraph mGraph, adjacentTableGraph lGraph) {
    222 
    223     weightType dist[mGraph->vertex_number], totalWeight;
    224     vertex parent[mGraph->vertex_number], v, w;
    225     int vCounter;
    226     edge e;
    227 
    228     /*
    229      * Initialize dist and parent,default the start point is 0 index
    230      */
    231     for (v = 0; v < mGraph->vertex_number; v++) {
    232         dist[v] = mGraph->g[0][v];
    233         parent[v] = 0;
    234     }
    235 
    236     /*
    237      * Initialize weight and vertex counter
    238      */
    239     totalWeight = 0;
    240     vCounter = 0;
    241     /*
    242      * Initialize a edge
    243      */
    244     e = (edge) malloc(sizeof(struct eNode));
    245 
    246     /*
    247      * Initialize dist[0] as the root of tree and set parent[0] to -1
    248      */
    249     dist[0] = 0;
    250     vCounter++;
    251     parent[0] = -1;
    252     /*
    253      * Execute Prim algorithms
    254      */
    255     while (1) {
    256         v = findMinDist(mGraph, dist);
    257         if (v == ERROR) {
    258             break;
    259         }
    260 
    261         /*
    262          * Put <v,parent[v]> to tree
    263          */
    264         e->v1 = parent[v];
    265         e->v2 = v;
    266         e->weight = dist[v];
    267         insertEdgeToLink(lGraph, e, 1);
    268         totalWeight += dist[v];
    269         vCounter++;
    270         dist[v] = 0;
    271 
    272         /*
    273          * Update the v adjacent vertex distance with minimal tree
    274          */
    275         for (w = 0; w < mGraph->vertex_number; w++) {
    276             /*
    277              * If w is v adjacent vetex and not be added to minimal tree
    278              */
    279             if (dist[w] != 0 && mGraph->g[v][w] < INFINITY) {
    280                 /*
    281                  * Update the distance to minimal created tree
    282                  */
    283                 if (mGraph->g[v][w] < dist[w]) {
    284                     dist[w] = mGraph->g[v][w];
    285                     parent[w] = v;
    286                 }
    287             }
    288         }
    289     }
    290     if (vCounter < mGraph->vertex_number) {
    291         return ERROR;
    292     } else {
    293         return totalWeight;
    294     }
    295 }
    296 
    297 /*========Use DFS to print the result of the minimal created tree==========*/
    298 /*
    299  * A method to access graph
    300  */
    301 void visit(adjacentTableGraph graph, vertex v) {
    302     printf("%d ", v);
    303 }
    304 
    305 /*
    306  Depth first search a graph
    307  @param graph The graph need to search
    308  @param startPoint The fisrt point we start search the graph
    309  @paran int *visited The array we use to tag the vertex we has accessed.
    310  */
    311 void DFS(adjacentTableGraph graph, vertex startPoint, int *visited) {
    312     ptrToAdjNode p;
    313     visit(graph, startPoint);
    314     p = graph->g[3].head;
    315     visited[startPoint] = 1;
    316     for (p = graph->g[startPoint].head; p; p = p->next) {
    317         if (visited[p->adjVerx] == 0) {
    318             DFS(graph, p->adjVerx, visited);
    319         }
    320     }
    321 }
    322 
    323 /*
    324  * Initialize a visited array that make them all to zero
    325  */
    326 void initVisited(int length, int *visited) {
    327     int i;
    328     for (i = 0; i < length; i++) {
    329         visited[i] = 0;
    330     }
    331 }
    332 
    333 int main() {
    334     adjacentTableGraph lGraph;
    335     adjacentMatrixGraph mGraph = buildMGraph(0);
    336     vertex visited[mGraph->vertex_number];
    337     lGraph = createLGraph(mGraph->vertex_number);
    338     weightType totalWeigt = prim(mGraph, lGraph);
    339     printf("totalWeigh:%d
    ", totalWeigt);
    340     initVisited(mGraph->vertex_number, visited);
    341     DFS(lGraph, 0, visited);
    342     return 0;
    343 }
    Prim_Base

    测试数据和运行结果:

     1 7 12
     2 1 2 2
     3 1 4 1
     4 2 5 10
     5 2 4 3
     6 3 1 4
     7 3 6 5
     8 4 3 2
     9 4 6 8
    10 4 7 4
    11 4 5 7
    12 5 7 6
    13 7 6 1
    14 
    15 Test result:
    16 totalWeigh:16
    17 0 1 3 6 4 5 2 
    Prime_Base_testData And result

    Kruskal算法求最小生成树的权重和打印路径代码:

      1 /*
      2  * kruskal.c
      3  *
      4  *  Created on: 2017年5月15日
      5  *      Author: ygh
      6  */
      7 
      8 #include <stdio.h>
      9 #include <stdlib.h>
     10 
     11 #define MAX_VERTEX_NUM 10001 /*define the max number of the vertex*/
     12 #define INFINITY 65535     /*define double byte no negitive integer max number is 65535*/
     13 #define ERROR -1
     14 
     15 typedef int vertex; /*define the data type of the vertex*/
     16 typedef int weightType; /*define the data type of the weight*/
     17 typedef char dataType; /*define the data type of the vertex value*/
     18 
     19 /*define the data structure of the Edge*/
     20 typedef struct eNode *ptrToENode;
     21 typedef struct eNode {
     22     vertex v1, v2; /*two vertex between the edge <v1,v2>*/
     23     weightType weight; /*the value of the edge's weight */
     24 };
     25 typedef ptrToENode edge;
     26 
     27 /*==================A adjacent link to describe a graph=========================================*/
     28 /*define the data structure adjacent table node*/
     29 typedef struct adjNode *ptrToAdjNode;
     30 typedef struct adjNode {
     31     vertex adjVerx; /*the index of the vertex*/
     32     weightType weight; /*the value of the weight*/
     33     ptrToAdjNode next; /*the point to point the next node*/
     34 };
     35 
     36 /*define the data structure of the adjacent head*/
     37 typedef struct vNode *ptrToVNode;
     38 typedef struct vNode {
     39     ptrToAdjNode head; /*the point to point the adjacent table node*/
     40     dataType data; /*the space to store the name of the vertex,but some time the vertex has no names*/
     41 } adjList[MAX_VERTEX_NUM];
     42 
     43 /*define the data structure of graph*/
     44 typedef struct gLNode *ptrTogLNode;
     45 typedef struct gLNode {
     46     int vertex_number; /*the number of the vertex*/
     47     int edge_nunber; /*the number of the edge*/
     48     adjList g; /*adjacent table*/
     49 };
     50 typedef ptrTogLNode adjacentTableGraph; /*a graph show by adjacent table*/
     51 
     52 /*
     53  create a graph given the vertex number.
     54  @param vertexNum The verter number of the graph
     55  @return a graph with vertex but no any egdgs
     56  */
     57 adjacentTableGraph createLGraph(int vertexNum) {
     58     adjacentTableGraph graph;
     59 
     60     vertex v;
     61     graph = (adjacentTableGraph) malloc(sizeof(struct gLNode));
     62     graph->vertex_number = vertexNum;
     63     graph->edge_nunber = 0;
     64     /*initialize the adjacent table*/
     65     for (v = 0; v < graph->vertex_number; v++) {
     66         graph->g[v].head = NULL;
     67     }
     68     return graph;
     69 }
     70 
     71 /*
     72  insert a edge to graph.We will distinct oriented graph and undirected graph
     73  The e->v1 and e->v2 are the vertexs' indexs in the adjacent table
     74  @param graph The graph you want to insert edge
     75  @param e The edge you want to insert the graph
     76  @param isOriented Whether the graph is oriented graph.If the graph is oriented
     77  we will set adjacent table graph[v1]->head=v2 and set graph[v1].head=v2
     78  otherwise we only set graph[v1].head=v2
     79  */
     80 void insertEdgeToLink(adjacentTableGraph graph, edge e, int isOriented) {
     81     /*build node<v1,v2>*/
     82     ptrToAdjNode newNode;
     83     newNode = (ptrToAdjNode) malloc(sizeof(struct adjNode));
     84     newNode->adjVerx = e->v2;
     85     newNode->weight = e->weight;
     86     newNode->next = graph->g[e->v1].head;
     87     graph->g[e->v1].head = newNode;
     88     /*if the graph is directed graph*/
     89     if (!isOriented) {
     90         newNode = (ptrToAdjNode) malloc(sizeof(struct adjNode));
     91         newNode->adjVerx = e->v1;
     92         newNode->weight = e->weight;
     93         newNode->next = graph->g[e->v2].head;
     94         graph->g[e->v2].head = newNode;
     95     }
     96 }
     97 
     98 /*
     99  build a graph stored by adjacent table
    100  */
    101 adjacentTableGraph buildLGraph(int isOrdered) {
    102     adjacentTableGraph graph;
    103     edge e;
    104     vertex i;
    105     int vertex_num;
    106 
    107     scanf("%d", &vertex_num);
    108     graph = createLGraph(vertex_num);
    109     scanf("%d", &(graph->edge_nunber));
    110     if (graph->edge_nunber) {
    111         e = (edge) malloc(sizeof(struct eNode));
    112         for (i = 0; i < graph->edge_nunber; i++) {
    113             scanf("%d %d %d", &e->v1, &e->v2, &e->weight);
    114             e->v1--;
    115             e->v2--;
    116             insertEdgeToLink(graph, e, isOrdered);
    117         }
    118     }
    119 
    120     return graph;
    121 }
    122 
    123 /*----------------------define collection and some operator of graph's nodes-----------------------------*/
    124 
    125 /*
    126  * The element of collection
    127  */
    128 typedef vertex elementType;
    129 
    130 /*
    131  * The index of root element,we use it as the collection name
    132  */
    133 typedef vertex setName;
    134 
    135 /*
    136  * A array to store the collection,we set the
    137  * first index is 0
    138  */
    139 typedef elementType setType[MAX_VERTEX_NUM];
    140 
    141 /*
    142  * Initialize collection
    143  * @param A <code>elementType</code> array to store the collections,maybe
    144  * many collection will be stored in this array
    145  * @param n The length of the collection
    146  */
    147 void initializeVSet(setType s, int n) {
    148     elementType x;
    149     for (x = 0; x < n; x++) {
    150         s[x] = -1;
    151     }
    152 }
    153 
    154 /*
    155  * Union two collections which is showed by root element.We will union smaller collection
    156  * to greater collection and we will update the quantity for greater collection
    157  * @param s A <code>elementType</code> array to store the collections,maybe
    158  * many collection will be stored in this array
    159  * @param root1 The root element of the first collection
    160  * @param root2 The root element of the second collection
    161  */
    162 void unionCollection(setType s, setName root1, setName root2) {
    163     /*
    164      * If root2's quantity greater than root1
    165      */
    166     if (s[root2] < s[root1]) {
    167         s[root2] += s[root1];
    168         s[root1] = root2;
    169     } else {
    170         s[root1] += s[root2];
    171         s[root2] = root1;
    172     }
    173 }
    174 
    175 /*
    176  * Find the element in which collection and use the root element
    177  * to represent this collection and return it.In this method,we will compress path
    178  * @param s A <code>elementType</code> array to store the collections,maybe
    179  * many collection will be stored in this array
    180  * @param x The element we find which collection it in.
    181  */
    182 setName find(setType s, elementType x) {
    183     if (s[x] < 0) {
    184         return x;
    185     } else {
    186         /*
    187          *compress path
    188          */
    189         return s[x] = find(s, s[x]);
    190     }
    191 }
    192 
    193 /*
    194  * Check v1 and v1 whether is belong to a same collection. If not union these
    195  * two collection,otherwise do nothing.
    196  * @param vSet A <code>elementType</code> array to store the collections,maybe
    197  * many collection will be stored in this array
    198  * @param v1 The index of node in the graph,also the element is the collection.
    199  * @param v2 The index of node in the graph,also the element is the collection.
    200  * @return If the two element is belong same collection,union them and return 1
    201  * else do nothing and return 0;
    202  */
    203 int checkCircle(setType vSet, vertex v1, vertex v2) {
    204     setName root1 = find(vSet, v1);
    205     setName root2 = find(vSet, v2);
    206     if (root1 == root2) {
    207         return 0;
    208     } else {
    209         unionCollection(vSet, root1, root2);
    210         return 1;
    211     }
    212 }
    213 
    214 /*-------------define the minimal heap of edge-------------------*/
    215 
    216 /*
    217  * Update the tree whose root element index is p into minimal heap,we use the edgs's
    218  * weight as the to construct the minimal heap.
    219  *
    220  * @param eset A array of edge to store the heap,because the edge is point variable
    221  * So the eSet is a edge type array,you can compare it with <code>int* arr</code>
    222  * @param The index of the root element.
    223  * @param n The length of the heap,the max index is n-1 in this case. And
    224  * this heap index is start from zero.
    225  */
    226 void percDowm(edge eSet, int p, int n) {
    227     int parent, child;
    228     struct eNode x;
    229 
    230     x = eSet[p];
    231     for (parent = p; (parent * 2 + 1) < n; parent = child) {
    232         /*
    233          * Because the first index if from zero,so the left child
    234          * is parent*2+1
    235          */
    236         child = parent * 2 + 1;
    237         /*
    238          * Find smaller weigh between the left child and right child
    239          */
    240         if ((child != n - 1) && eSet[child].weight > eSet[child + 1].weight) {
    241             child++;
    242         }
    243         if (x.weight <= eSet[child].weight) {
    244             break;
    245         } else {
    246             eSet[parent] = eSet[child];
    247         }
    248     }
    249     eSet[parent] = x;
    250 }
    251 
    252 /*
    253  * Initialize eSet heap and update it to be the minimal heap
    254  * @param graph A graph which is stored by adjacent list
    255  * @param eSet A array of the edge as the minimal heap
    256  */
    257 void initializeESet(adjacentTableGraph graph, edge eSet) {
    258     vertex v;
    259     ptrToAdjNode w;
    260     int counter = 0;
    261     for (v = 0; v < graph->vertex_number; v++) {
    262         for (w = graph->g[v].head; w; w = w->next) {
    263             /*
    264              * expect for put same edge to it,we only
    265              * put <v1,v2> to it.
    266              */
    267             if (v < w->adjVerx) {
    268                 eSet[counter].v1 = v;
    269                 eSet[counter].v2 = w->adjVerx;
    270                 eSet[counter].weight = w->weight;
    271                 counter++;
    272             }
    273 
    274         }
    275     }
    276     /*
    277      * Initialize the minimal heap
    278      */
    279     for (counter = graph->edge_nunber / 2; counter >= 0; counter--) {
    280         percDowm(eSet, counter, graph->edge_nunber);
    281     }
    282 }
    283 
    284 /*
    285  * Get minimal edge from the minimal weight heap
    286  * @param eset A array of edge to store the heap,because the edge is point variable
    287  * So the eSet is a edge type array,you can compare it with <code>int* arr</code>
    288  * @param The current size of the minimal heap
    289  * @return The index of the minimal edge in this heap(array)
    290  */
    291 int getEdge(edge eSet, int currentSize) {
    292     if (currentSize == 0) {
    293         return currentSize - 1;
    294     }
    295     struct eNode temp = eSet[currentSize - 1];
    296     eSet[currentSize - 1] = eSet[0];
    297     eSet[0] = temp;
    298     percDowm(eSet, 0, currentSize - 1);
    299     return currentSize - 1;
    300 }
    301 
    302 /*
    303  * Implement the kruskal algorithms to find the minimal created tree
    304  * Algorithms thought:we choose the minimal edge from graph but don't
    305  * construct a circle each time. Until we choose the V-1 edges. The V
    306  * is equal with the quantity of the graph's vertex
    307  * In this program,we will use a counter to record the quantity of edges
    308  * At last of this method,if we check the quantity of the edge is less than
    309  * V-1, it indicates the graph is not collected,so -1 will be return,otherwise we will return
    310  * the minimal created tree total weight.
    311  * @param graph A graph which is stored by adjacent list
    312  * @param mst A A graph which is stored by adjacent list to store the minimal created tree
    313  * @return If the graph is collected,the weight of the minimal created tree
    314  * will be return, otherwise return -1
    315  */
    316 int kruskal(adjacentTableGraph graph, adjacentTableGraph mst) {
    317     /*
    318      * totalWeight is to record the total weight
    319      * of the minimal created tree
    320      */
    321     weightType totalWeight;
    322     /*
    323      * eCounter is to record the quantity of edges which has been
    324      * insert the <code>mst<code>
    325      *
    326      * nextEdge is to record the next minimal edge in the minimal heap
    327      */
    328     int eCounter, nextEdge;
    329 
    330     /*
    331      *A set of the vertex to store the vertex and implement
    332      *some operation such as union find and so on
    333      */
    334     setType vSet;
    335 
    336     /*
    337      * A array of edge to as the minimal heap to store the egdes
    338      */
    339     edge eSet;
    340 
    341     /*
    342      * Initialize some variables
    343      */
    344     initializeVSet(vSet, graph->vertex_number);
    345     eSet = (edge) malloc((sizeof(struct eNode)) * (graph->edge_nunber));
    346     initializeESet(graph, eSet);
    347 //    mst = createLGraph(graph->vertex_number);
    348     totalWeight = 0;
    349     eCounter = 0;
    350     nextEdge = graph->edge_nunber;
    351     while (eCounter < graph->vertex_number - 1) {
    352         nextEdge = getEdge(eSet, nextEdge);
    353         if (nextEdge < 0) {
    354             break;
    355         }
    356         /*
    357          * Check whether a circle between two vertex
    358          */
    359         if (checkCircle(vSet, eSet[nextEdge].v1, eSet[nextEdge].v2)) {
    360             insertEdgeToLink(mst, eSet + nextEdge, 0);
    361             totalWeight += eSet[nextEdge].weight;
    362             eCounter++;
    363         }
    364     }
    365     if (eCounter < graph->vertex_number - 1) {
    366         totalWeight = -1;
    367     }
    368     return totalWeight;
    369 }
    370 
    371 /*========Use DFS to print the result of the minimal created tree==========*/
    372 /*
    373  * A method to access graph
    374  */
    375 void visit(adjacentTableGraph graph, vertex v) {
    376     printf("%d ", v);
    377 }
    378 
    379 /*
    380  Depth first search a graph
    381  @param graph The graph need to search
    382  @param startPoint The fisrt point we start search the graph
    383  @paran int *visited The array we use to tag the vertex we has accessed.
    384  */
    385 void DFS(adjacentTableGraph graph, vertex startPoint, int *visited) {
    386     ptrToAdjNode p;
    387     visit(graph, startPoint);
    388     p = graph->g[3].head;
    389     visited[startPoint] = 1;
    390     for (p = graph->g[startPoint].head; p; p = p->next) {
    391         if (visited[p->adjVerx] == 0) {
    392             DFS(graph, p->adjVerx, visited);
    393         }
    394     }
    395 }
    396 
    397 /*
    398  * Initialize a visited array that make them all to zero
    399  */
    400 void initVisited(int length, int *visited) {
    401     int i;
    402     for (i = 0; i < length; i++) {
    403         visited[i] = 0;
    404     }
    405 }
    406 
    407 int main() {
    408     adjacentTableGraph graph = buildLGraph(0);
    409     adjacentTableGraph mst = createLGraph(graph->vertex_number);
    410     vertex visited[graph->vertex_number];
    411     weightType totalWeight = kruskal(graph, mst);
    412     printf("totalWeight:%d
    ", totalWeight);
    413     initVisited(graph->vertex_number, visited);
    414     DFS(mst, 0, visited);
    415     return 0;
    416 }
    Kruska_Base

    测试数据和运行结果

     1 7 12
     2 1 2 2
     3 1 4 1
     4 2 5 10
     5 2 4 3
     6 3 1 4
     7 3 6 5
     8 4 3 2
     9 4 6 8
    10 4 7 4
    11 4 5 7
    12 5 7 6
    13 7 6 1
    14 
    15 Test result:
    16 totalWeigh:16
    17 0 1 3 6 4 5 2 
    Kruskal_Base_testData And result

    上面村村通习题的Prim代码

      1 /*
      2  * path.c
      3  *
      4  *  Created on: 2017年5月15日
      5  *      Author: ygh
      6  */
      7 #include <stdio.h>
      8 #include <stdlib.h>
      9 
     10 #define MAX_VERTEX_NUM 10001 /*define the max number of the vertex*/
     11 #define INFINITY 65535     /*define double byte no negitive integer max number is 65535*/
     12 #define ERROR -1
     13 
     14 typedef int vertex; /*define the data type of the vertex*/
     15 typedef int weightType; /*define the data type of the weight*/
     16 typedef char dataType; /*define the data type of the vertex value*/
     17 
     18 /*define the data structure of the Edge*/
     19 typedef struct eNode *ptrToENode;
     20 typedef struct eNode {
     21     vertex v1, v2; /*two vertex between the edge <v1,v2>*/
     22     weightType weight; /*the value of the edge's weight */
     23 };
     24 typedef ptrToENode edge;
     25 
     26 /*==================A adjacent matrix to describe a graph=========================================*/
     27 
     28 /*define the data structure of the graph*/
     29 typedef struct gMNode *ptrTogMNode;
     30 typedef struct gMNode {
     31     int vertex_number; /*the number of the vertex*/
     32     int edge_nunber; /*the number of the edge*/
     33     weightType g[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; /*define the adjacent matrix weight of graph*/
     34     dataType data[MAX_VERTEX_NUM]; /*define the dataType array to store the value of vertex*/
     35 };
     36 typedef ptrTogMNode adjacentMatrixGraph; /*a graph show by adjacent matrix*/
     37 
     38 /*
     39  create a graph given the vertex number.
     40  @param vertexNum The verter number of the graph
     41  @return a graph with vertex but no any egdgs
     42  */
     43 adjacentMatrixGraph createMGraph(int vertexNum) {
     44     vertex v, w;
     45     adjacentMatrixGraph graph;
     46     graph = (adjacentMatrixGraph) malloc(sizeof(struct gMNode));
     47     graph->vertex_number = vertexNum;
     48     graph->edge_nunber = 0;
     49     /*initialize the adjacent matrix*/
     50     for (v = 0; v < graph->vertex_number; v++) {
     51         for (w = 0; w < graph->vertex_number; w++) {
     52             graph->g[v][w] = INFINITY;
     53         }
     54     }
     55 
     56     return graph;
     57 }
     58 
     59 /*
     60  insert a edge to graph.We will distinct oriented graph and undirected graph
     61  @param graph The graph you want to insert edge
     62  @param e The edge you want to insert the graph
     63  @param isOriented Whether the graph is oriented graph.If the graph is oriented
     64  we will set adjacent matrix [n][m]=[m][n]=edge's weight,else we only set
     65  the adjacent matrix [n][m]=edge's weight
     66  */
     67 void inserEdgeToMatrix(adjacentMatrixGraph graph, edge e, int isOriented) {
     68     graph->g[e->v1][e->v2] = e->weight;
     69     if (!isOriented) {
     70         graph->g[e->v2][e->v1] = e->weight;
     71     }
     72 }
     73 
     74 /*
     75  construct a graph according user's input
     76 
     77  @return a graph has been filled good
     78  */
     79 adjacentMatrixGraph buildMGraph(int isOrdered) {
     80     adjacentMatrixGraph graph;
     81     edge e;
     82     vertex i;
     83     int vertex_num;
     84     scanf("%d", &vertex_num);
     85     graph = createMGraph(vertex_num);
     86     scanf("%d", &(graph->edge_nunber));
     87     if (graph->edge_nunber) {
     88         e = (edge) malloc(sizeof(struct eNode));
     89         for (i = 0; i < graph->edge_nunber; i++) {
     90             scanf("%d %d %d", &e->v1, &e->v2, &e->weight);
     91             e->v1--;
     92             e->v2--;
     93             inserEdgeToMatrix(graph, e, isOrdered);
     94         }
     95     }
     96     return graph;
     97 
     98 }
     99 
    100 /*==================A adjacent link to describe a graph=========================================*/
    101 /*define the data structure adjacent table node*/
    102 typedef struct adjNode *ptrToAdjNode;
    103 typedef struct adjNode {
    104     vertex adjVerx; /*the index of the vertex*/
    105     weightType weight; /*the value of the weight*/
    106     ptrToAdjNode next; /*the point to point the next node*/
    107 };
    108 
    109 /*define the data structure of the adjacent head*/
    110 typedef struct vNode *ptrToVNode;
    111 typedef struct vNode {
    112     ptrToAdjNode head; /*the point to point the adjacent table node*/
    113     dataType data; /*the space to store the name of the vertex,but some time the vertex has no names*/
    114 } adjList[MAX_VERTEX_NUM];
    115 
    116 /*define the data structure of graph*/
    117 typedef struct gLNode *ptrTogLNode;
    118 typedef struct gLNode {
    119     int vertex_number; /*the number of the vertex*/
    120     int edge_nunber; /*the number of the edge*/
    121     adjList g; /*adjacent table*/
    122 };
    123 typedef ptrTogLNode adjacentTableGraph; /*a graph show by adjacent table*/
    124 
    125 /*
    126  create a graph given the vertex number.
    127  @param vertexNum The verter number of the graph
    128  @return a graph with vertex but no any egdgs
    129  */
    130 adjacentTableGraph createLGraph(int vertexNum) {
    131     adjacentTableGraph graph;
    132 
    133     vertex v;
    134     graph = (adjacentTableGraph) malloc(sizeof(struct gLNode));
    135     graph->vertex_number = vertexNum;
    136     graph->edge_nunber = 0;
    137     /*initialize the adjacent table*/
    138     for (v = 0; v < graph->vertex_number; v++) {
    139         graph->g[v].head = NULL;
    140     }
    141     return graph;
    142 }
    143 
    144 /*
    145  insert a edge to graph.We will distinct oriented graph and undirected graph
    146  The e->v1 and e->v2 are the vertexs' indexs in the adjacent table
    147  @param graph The graph you want to insert edge
    148  @param e The edge you want to insert the graph
    149  @param isOriented Whether the graph is oriented graph.If the graph is oriented
    150  we will set adjacent table graph[v1]->head=v2 and set graph[v1].head=v2
    151  otherwise we only set graph[v1].head=v2
    152  */
    153 void insertEdgeToLink(adjacentTableGraph graph, edge e, int isOriented) {
    154     /*build node<v1,v2>*/
    155     ptrToAdjNode newNode;
    156     newNode = (ptrToAdjNode) malloc(sizeof(struct adjNode));
    157     newNode->adjVerx = e->v2;
    158     newNode->weight = e->weight;
    159     newNode->next = graph->g[e->v1].head;
    160     graph->g[e->v1].head = newNode;
    161     /*if the graph is directed graph*/
    162     if (!isOriented) {
    163         newNode = (ptrToAdjNode) malloc(sizeof(struct adjNode));
    164         newNode->adjVerx = e->v1;
    165         newNode->weight = e->weight;
    166         newNode->next = graph->g[e->v2].head;
    167         graph->g[e->v2].head = newNode;
    168     }
    169 }
    170 
    171 /*
    172  build a graph stored by adjacent table
    173  */
    174 adjacentTableGraph buildLGraph() {
    175     adjacentTableGraph graph;
    176     edge e;
    177     vertex i;
    178     int vertex_num;
    179 
    180     scanf("%d", &vertex_num);
    181     graph = createLGraph(vertex_num);
    182     scanf("%d", &(graph->edge_nunber));
    183     if (graph->edge_nunber) {
    184         e = (edge) malloc(sizeof(struct eNode));
    185         for (i = 0; i < graph->edge_nunber; i++) {
    186             scanf("%d %d %d", &e->v1, &e->v2, &e->weight);
    187             insertEdgeToLink(graph, e, 0);
    188         }
    189     }
    190 
    191     return graph;
    192 }
    193 
    194 /*
    195  * Find the minimal node closest to created tree
    196  */
    197 vertex findMinDist(adjacentMatrixGraph graph, weightType dist[]) {
    198     vertex minV, v;
    199     weightType minDist = INFINITY;
    200     for (v = 0; v < graph->vertex_number; v++) {
    201         if (dist[v] != 0 && dist[v] < minDist) {
    202             minDist = dist[v];
    203             minV = v;
    204         }
    205     }
    206     if (minDist < INFINITY) {
    207         return minV;
    208     } else {
    209         return ERROR;
    210     }
    211 }
    212 
    213 /*
    214  * Prim algorithms,we will store the minimal created tree with a adjacnet
    215  * list table and return the minimal weight
    216  * @param mGraph The graph showed by adjacent matrix is to store graph
    217  * @param lGraph The graph showed by adjacent list is to store the minimal created tree
    218  * @return The weight of the minimal created tree if the graph is connected, otherwise return
    219  * <code>ERROR</code>
    220  */
    221 int prim(adjacentMatrixGraph mGraph, adjacentTableGraph lGraph) {
    222 
    223     weightType dist[mGraph->vertex_number], totalWeight;
    224     vertex parent[mGraph->vertex_number], v, w;
    225     int vCounter;
    226     edge e;
    227 
    228     /*
    229      * Initialize dist and parent,default the start point is 0 index
    230      */
    231     for (v = 0; v < mGraph->vertex_number; v++) {
    232         dist[v] = mGraph->g[0][v];
    233         parent[v] = 0;
    234     }
    235 
    236     /*
    237      * Initialize weight and vertex counter
    238      */
    239     totalWeight = 0;
    240     vCounter = 0;
    241     /*
    242      * Initialize a edge
    243      */
    244     e = (edge) malloc(sizeof(struct eNode));
    245 
    246     /*
    247      * Initialize dist[0] as the root of tree and set parent[0] to -1
    248      */
    249     dist[0] = 0;
    250     vCounter++;
    251     parent[0] = -1;
    252     /*
    253      * Execute Prim algorithms
    254      */
    255     while (1) {
    256         v = findMinDist(mGraph, dist);
    257         if (v == ERROR) {
    258             break;
    259         }
    260 
    261         /*
    262          * Put <v,parent[v]> to tree
    263          */
    264         e->v1 = parent[v];
    265         e->v2 = v;
    266         e->weight = dist[v];
    267         insertEdgeToLink(lGraph, e, 1);
    268         totalWeight += dist[v];
    269         vCounter++;
    270         dist[v] = 0;
    271 
    272         /*
    273          * Update the v adjacent vertex distance with minimal tree
    274          */
    275         for (w = 0; w < mGraph->vertex_number; w++) {
    276             /*
    277              * If w is v adjacent vetex and not be added to minimal tree
    278              */
    279             if (dist[w] != 0 && mGraph->g[v][w] < INFINITY) {
    280                 /*
    281                  * Update the distance to minimal created tree
    282                  */
    283                 if (mGraph->g[v][w] < dist[w]) {
    284                     dist[w] = mGraph->g[v][w];
    285                     parent[w] = v;
    286                 }
    287             }
    288         }
    289     }
    290     if (vCounter < mGraph->vertex_number) {
    291         return ERROR;
    292     } else {
    293         return totalWeight;
    294     }
    295 }
    296 
    297 /*========Use DFS to print the result of the minimal created tree==========*/
    298 /*
    299  * A method to access graph
    300  */
    301 void visit(adjacentTableGraph graph, vertex v) {
    302     printf("%d ", v);
    303 }
    304 
    305 /*
    306  Depth first search a graph
    307  @param graph The graph need to search
    308  @param startPoint The fisrt point we start search the graph
    309  @paran int *visited The array we use to tag the vertex we has accessed.
    310  */
    311 void DFS(adjacentTableGraph graph, vertex startPoint, int *visited) {
    312     ptrToAdjNode p;
    313     visit(graph, startPoint);
    314     p = graph->g[3].head;
    315     visited[startPoint] = 1;
    316     for (p = graph->g[startPoint].head; p; p = p->next) {
    317         if (visited[p->adjVerx] == 0) {
    318             DFS(graph, p->adjVerx, visited);
    319         }
    320     }
    321 }
    322 
    323 /*
    324  * Initialize a visited array that make them all to zero
    325  */
    326 void initVisited(int length, int *visited) {
    327     int i;
    328     for (i = 0; i < length; i++) {
    329         visited[i] = 0;
    330     }
    331 }
    332 
    333 int main() {
    334     adjacentTableGraph lGraph;
    335     adjacentMatrixGraph mGraph = buildMGraph(0);
    336     vertex visited[mGraph->vertex_number];
    337     lGraph = createLGraph(mGraph->vertex_number);
    338     weightType totalWeigt = prim(mGraph, lGraph);
    339     printf("%d
    ", totalWeigt);
    340     return 0;
    341 }
    valige_path_peim

    上面村村通习题的Kruskal代码

      1 /*
      2  * kruskal.c
      3  *
      4  *  Created on: 2017年5月15日
      5  *      Author: ygh
      6  */
      7 
      8 #include <stdio.h>
      9 #include <stdlib.h>
     10 
     11 #define MAX_VERTEX_NUM 10001 /*define the max number of the vertex*/
     12 #define INFINITY 65535     /*define double byte no negitive integer max number is 65535*/
     13 #define ERROR -1
     14 
     15 typedef int vertex; /*define the data type of the vertex*/
     16 typedef int weightType; /*define the data type of the weight*/
     17 typedef char dataType; /*define the data type of the vertex value*/
     18 
     19 /*define the data structure of the Edge*/
     20 typedef struct eNode *ptrToENode;
     21 typedef struct eNode {
     22     vertex v1, v2; /*two vertex between the edge <v1,v2>*/
     23     weightType weight; /*the value of the edge's weight */
     24 };
     25 typedef ptrToENode edge;
     26 
     27 /*==================A adjacent link to describe a graph=========================================*/
     28 /*define the data structure adjacent table node*/
     29 typedef struct adjNode *ptrToAdjNode;
     30 typedef struct adjNode {
     31     vertex adjVerx; /*the index of the vertex*/
     32     weightType weight; /*the value of the weight*/
     33     ptrToAdjNode next; /*the point to point the next node*/
     34 };
     35 
     36 /*define the data structure of the adjacent head*/
     37 typedef struct vNode *ptrToVNode;
     38 typedef struct vNode {
     39     ptrToAdjNode head; /*the point to point the adjacent table node*/
     40     dataType data; /*the space to store the name of the vertex,but some time the vertex has no names*/
     41 } adjList[MAX_VERTEX_NUM];
     42 
     43 /*define the data structure of graph*/
     44 typedef struct gLNode *ptrTogLNode;
     45 typedef struct gLNode {
     46     int vertex_number; /*the number of the vertex*/
     47     int edge_nunber; /*the number of the edge*/
     48     adjList g; /*adjacent table*/
     49 };
     50 typedef ptrTogLNode adjacentTableGraph; /*a graph show by adjacent table*/
     51 
     52 /*
     53  create a graph given the vertex number.
     54  @param vertexNum The verter number of the graph
     55  @return a graph with vertex but no any egdgs
     56  */
     57 adjacentTableGraph createLGraph(int vertexNum) {
     58     adjacentTableGraph graph;
     59 
     60     vertex v;
     61     graph = (adjacentTableGraph) malloc(sizeof(struct gLNode));
     62     graph->vertex_number = vertexNum;
     63     graph->edge_nunber = 0;
     64     /*initialize the adjacent table*/
     65     for (v = 0; v < graph->vertex_number; v++) {
     66         graph->g[v].head = NULL;
     67     }
     68     return graph;
     69 }
     70 
     71 /*
     72  insert a edge to graph.We will distinct oriented graph and undirected graph
     73  The e->v1 and e->v2 are the vertexs' indexs in the adjacent table
     74  @param graph The graph you want to insert edge
     75  @param e The edge you want to insert the graph
     76  @param isOriented Whether the graph is oriented graph.If the graph is oriented
     77  we will set adjacent table graph[v1]->head=v2 and set graph[v1].head=v2
     78  otherwise we only set graph[v1].head=v2
     79  */
     80 void insertEdgeToLink(adjacentTableGraph graph, edge e, int isOriented) {
     81     /*build node<v1,v2>*/
     82     ptrToAdjNode newNode;
     83     newNode = (ptrToAdjNode) malloc(sizeof(struct adjNode));
     84     newNode->adjVerx = e->v2;
     85     newNode->weight = e->weight;
     86     newNode->next = graph->g[e->v1].head;
     87     graph->g[e->v1].head = newNode;
     88     /*if the graph is directed graph*/
     89     if (!isOriented) {
     90         newNode = (ptrToAdjNode) malloc(sizeof(struct adjNode));
     91         newNode->adjVerx = e->v1;
     92         newNode->weight = e->weight;
     93         newNode->next = graph->g[e->v2].head;
     94         graph->g[e->v2].head = newNode;
     95     }
     96 }
     97 
     98 /*
     99  build a graph stored by adjacent table
    100  */
    101 adjacentTableGraph buildLGraph(int isOrdered) {
    102     adjacentTableGraph graph;
    103     edge e;
    104     vertex i;
    105     int vertex_num;
    106 
    107     scanf("%d", &vertex_num);
    108     graph = createLGraph(vertex_num);
    109     scanf("%d", &(graph->edge_nunber));
    110     if (graph->edge_nunber) {
    111         e = (edge) malloc(sizeof(struct eNode));
    112         for (i = 0; i < graph->edge_nunber; i++) {
    113             scanf("%d %d %d", &e->v1, &e->v2, &e->weight);
    114             e->v1--;
    115             e->v2--;
    116             insertEdgeToLink(graph, e, isOrdered);
    117         }
    118     }
    119 
    120     return graph;
    121 }
    122 
    123 /*----------------------define collection and some operator of graph's nodes-----------------------------*/
    124 
    125 /*
    126  * The element of collection
    127  */
    128 typedef vertex elementType;
    129 
    130 /*
    131  * The index of root element,we use it as the collection name
    132  */
    133 typedef vertex setName;
    134 
    135 /*
    136  * A array to store the collection,we set the
    137  * first index is 0
    138  */
    139 typedef elementType setType[MAX_VERTEX_NUM];
    140 
    141 /*
    142  * Initialize collection
    143  * @param A <code>elementType</code> array to store the collections,maybe
    144  * many collection will be stored in this array
    145  * @param n The length of the collection
    146  */
    147 void initializeVSet(setType s, int n) {
    148     elementType x;
    149     for (x = 0; x < n; x++) {
    150         s[x] = -1;
    151     }
    152 }
    153 
    154 /*
    155  * Union two collections which is showed by root element.We will union smaller collection
    156  * to greater collection and we will update the quantity for greater collection
    157  * @param s A <code>elementType</code> array to store the collections,maybe
    158  * many collection will be stored in this array
    159  * @param root1 The root element of the first collection
    160  * @param root2 The root element of the second collection
    161  */
    162 void unionCollection(setType s, setName root1, setName root2) {
    163     /*
    164      * If root2's quantity greater than root1
    165      */
    166     if (s[root2] < s[root1]) {
    167         s[root2] += s[root1];
    168         s[root1] = root2;
    169     } else {
    170         s[root1] += s[root2];
    171         s[root2] = root1;
    172     }
    173 }
    174 
    175 /*
    176  * Find the element in which collection and use the root element
    177  * to represent this collection and return it.In this method,we will compress path
    178  * @param s A <code>elementType</code> array to store the collections,maybe
    179  * many collection will be stored in this array
    180  * @param x The element we find which collection it in.
    181  */
    182 setName find(setType s, elementType x) {
    183     if (s[x] < 0) {
    184         return x;
    185     } else {
    186         /*
    187          *compress path
    188          */
    189         return s[x] = find(s, s[x]);
    190     }
    191 }
    192 
    193 /*
    194  * Check v1 and v1 whether is belong to a same collection. If not union these
    195  * two collection,otherwise do nothing.
    196  * @param vSet A <code>elementType</code> array to store the collections,maybe
    197  * many collection will be stored in this array
    198  * @param v1 The index of node in the graph,also the element is the collection.
    199  * @param v2 The index of node in the graph,also the element is the collection.
    200  * @return If the two element is belong same collection,union them and return 1
    201  * else do nothing and return 0;
    202  */
    203 int checkCircle(setType vSet, vertex v1, vertex v2) {
    204     setName root1 = find(vSet, v1);
    205     setName root2 = find(vSet, v2);
    206     if (root1 == root2) {
    207         return 0;
    208     } else {
    209         unionCollection(vSet, root1, root2);
    210         return 1;
    211     }
    212 }
    213 
    214 /*-------------define the minimal heap of edge-------------------*/
    215 
    216 /*
    217  * Update the tree whose root element index is p into minimal heap,we use the edgs's
    218  * weight as the to construct the minimal heap.
    219  *
    220  * @param eset A array of edge to store the heap,because the edge is point variable
    221  * So the eSet is a edge type array,you can compare it with <code>int* arr</code>
    222  * @param The index of the root element.
    223  * @param n The length of the heap,the max index is n-1 in this case. And
    224  * this heap index is start from zero.
    225  */
    226 void percDowm(edge eSet, int p, int n) {
    227     int parent, child;
    228     struct eNode x;
    229 
    230     x = eSet[p];
    231     for (parent = p; (parent * 2 + 1) < n; parent = child) {
    232         /*
    233          * Because the first index if from zero,so the left child
    234          * is parent*2+1
    235          */
    236         child = parent * 2 + 1;
    237         /*
    238          * Find smaller weigh between the left child and right child
    239          */
    240         if ((child != n - 1) && eSet[child].weight > eSet[child + 1].weight) {
    241             child++;
    242         }
    243         if (x.weight <= eSet[child].weight) {
    244             break;
    245         } else {
    246             eSet[parent] = eSet[child];
    247         }
    248     }
    249     eSet[parent] = x;
    250 }
    251 
    252 /*
    253  * Initialize eSet heap and update it to be the minimal heap
    254  * @param graph A graph which is stored by adjacent list
    255  * @param eSet A array of the edge as the minimal heap
    256  */
    257 void initializeESet(adjacentTableGraph graph, edge eSet) {
    258     vertex v;
    259     ptrToAdjNode w;
    260     int counter = 0;
    261     for (v = 0; v < graph->vertex_number; v++) {
    262         for (w = graph->g[v].head; w; w = w->next) {
    263             /*
    264              * expect for put same edge to it,we only
    265              * put <v1,v2> to it.
    266              */
    267             if (v < w->adjVerx) {
    268                 eSet[counter].v1 = v;
    269                 eSet[counter].v2 = w->adjVerx;
    270                 eSet[counter].weight = w->weight;
    271                 counter++;
    272             }
    273 
    274         }
    275     }
    276     /*
    277      * Initialize the minimal heap
    278      */
    279     for (counter = graph->edge_nunber / 2; counter >= 0; counter--) {
    280         percDowm(eSet, counter, graph->edge_nunber);
    281     }
    282 }
    283 
    284 /*
    285  * Get minimal edge from the minimal weight heap
    286  * @param eset A array of edge to store the heap,because the edge is point variable
    287  * So the eSet is a edge type array,you can compare it with <code>int* arr</code>
    288  * @param The current size of the minimal heap
    289  * @return The index of the minimal edge in this heap(array)
    290  */
    291 int getEdge(edge eSet, int currentSize) {
    292     if (currentSize == 0) {
    293         return currentSize - 1;
    294     }
    295     struct eNode temp = eSet[currentSize - 1];
    296     eSet[currentSize - 1] = eSet[0];
    297     eSet[0] = temp;
    298     percDowm(eSet, 0, currentSize - 1);
    299     return currentSize - 1;
    300 }
    301 
    302 /*
    303  * Implement the kruskal algorithms to find the minimal created tree
    304  * Algorithms thought:we choose the minimal edge from graph but don't
    305  * construct a circle each time. Until we choose the V-1 edges. The V
    306  * is equal with the quantity of the graph's vertex
    307  * In this program,we will use a counter to record the quantity of edges
    308  * At last of this method,if we check the quantity of the edge is less than
    309  * V-1, it indicates the graph is not collected,so -1 will be return,otherwise we will return
    310  * the minimal created tree total weight.
    311  * @param graph A graph which is stored by adjacent list
    312  * @param mst A A graph which is stored by adjacent list to store the minimal created tree
    313  * @return If the graph is collected,the weight of the minimal created tree
    314  * will be return, otherwise return -1
    315  */
    316 int kruskal(adjacentTableGraph graph, adjacentTableGraph mst) {
    317     /*
    318      * totalWeight is to record the total weight
    319      * of the minimal created tree
    320      */
    321     weightType totalWeight;
    322     /*
    323      * eCounter is to record the quantity of edges which has been
    324      * insert the <code>mst<code>
    325      *
    326      * nextEdge is to record the next minimal edge in the minimal heap
    327      */
    328     int eCounter, nextEdge;
    329 
    330     /*
    331      *A set of the vertex to store the vertex and implement
    332      *some operation such as union find and so on
    333      */
    334     setType vSet;
    335 
    336     /*
    337      * A array of edge to as the minimal heap to store the egdes
    338      */
    339     edge eSet;
    340 
    341     /*
    342      * Initialize some variables
    343      */
    344     initializeVSet(vSet, graph->vertex_number);
    345     eSet = (edge) malloc((sizeof(struct eNode)) * (graph->edge_nunber));
    346     initializeESet(graph, eSet);
    347 //    mst = createLGraph(graph->vertex_number);
    348     totalWeight = 0;
    349     eCounter = 0;
    350     nextEdge = graph->edge_nunber;
    351     while (eCounter < graph->vertex_number - 1) {
    352         nextEdge = getEdge(eSet, nextEdge);
    353         if (nextEdge < 0) {
    354             break;
    355         }
    356         /*
    357          * Check whether a circle between two vertex
    358          */
    359         if (checkCircle(vSet, eSet[nextEdge].v1, eSet[nextEdge].v2)) {
    360             insertEdgeToLink(mst, eSet + nextEdge, 0);
    361             totalWeight += eSet[nextEdge].weight;
    362             eCounter++;
    363         }
    364     }
    365     if (eCounter < graph->vertex_number - 1) {
    366         totalWeight = -1;
    367     }
    368     return totalWeight;
    369 }
    370 
    371 /*========Use DFS to print the result of the minimal created tree==========*/
    372 /*
    373  * A method to access graph
    374  */
    375 void visit(adjacentTableGraph graph, vertex v) {
    376     printf("%d ", v);
    377 }
    378 
    379 /*
    380  Depth first search a graph
    381  @param graph The graph need to search
    382  @param startPoint The fisrt point we start search the graph
    383  @paran int *visited The array we use to tag the vertex we has accessed.
    384  */
    385 void DFS(adjacentTableGraph graph, vertex startPoint, int *visited) {
    386     ptrToAdjNode p;
    387     visit(graph, startPoint);
    388     p = graph->g[3].head;
    389     visited[startPoint] = 1;
    390     for (p = graph->g[startPoint].head; p; p = p->next) {
    391         if (visited[p->adjVerx] == 0) {
    392             DFS(graph, p->adjVerx, visited);
    393         }
    394     }
    395 }
    396 
    397 /*
    398  * Initialize a visited array that make them all to zero
    399  */
    400 void initVisited(int length, int *visited) {
    401     int i;
    402     for (i = 0; i < length; i++) {
    403         visited[i] = 0;
    404     }
    405 }
    406 
    407 int main() {
    408     adjacentTableGraph graph = buildLGraph(0);
    409     adjacentTableGraph mst = createLGraph(graph->vertex_number);
    410     vertex visited[graph->vertex_number];
    411     weightType totalWeight = kruskal(graph, mst);
    412     printf("%d
    ", totalWeight);
    413     /*initVisited(graph->vertex_number, visited);
    414     DFS(mst, 0, visited);*/
    415     return 0;
    416 }
    valige_path_kruskal
  • 相关阅读:
    一个cs架构的在线考试系统
    TreeComboBox控件范例
    new和override修饰符的区别
    Hello cnblogs
    MapInfo图层坐标系统转换
    C#调用新浪微博API生成RSS资源文件
    MapInfo图层格式转ArcGIS图层格式
    用ArcGIS的ArcToolbox进行地图切割
    VS2008智能提示消失的解决方法
    【学习笔记】零基础C#窗口程序开发入门
  • 原文地址:https://www.cnblogs.com/yghjava/p/6858364.html
Copyright © 2011-2022 走看看