zoukankan      html  css  js  c++  java
  • 数据结构图之二(最小生成树--克鲁斯卡尔算法)

    【1】克鲁斯卡尔算法

    普里姆算法是以某顶点为起点,逐步找各顶点上最小权值的边来构建最小生成树。

    克鲁斯卡尔算法是直接以边为目标去构建。

    因为权值是在边上,直接去找最小权值的边来构建生成树也是很自然的想法,只不过构建时要考虑是否会形成环路而已。

    此时我们用到了图的存储结构中的边集数组结构。

    以下是边集数组结构的定义代码:

    本算法所用同普里姆算法的实例,我们直接创建图的边集数组。

    并对边的权值从小到大排序后如下图:

    【2】克鲁斯卡尔算法及详解

    克鲁斯卡尔算法及其详解:

    鉴于此算法很简单,当 i=0, i=1, i=2时执行结果可以眼观,不再赘述。直接分析重点:

    此算法的Find函数由边数e决定,时间复杂度为O(loge),而外面有一个for循环e次。

    所以克鲁斯卡尔算法的时间复杂度为O(eloge)

    对比两个算法:

    克鲁斯卡尔算法主要针对边展开,边数少时效率会很高,所以对于稀疏图有优势

    而普利姆算法对于稠密图,即边数非常多的情况会好些。

    【3】克鲁斯卡尔算法实现

    实现代码如下:

      1 #include <iostream>
      2 using namespace std;
      3 
      4 #define    MAXVER  9
      5 #define MAXEDGE 15
      6 
      7 typedef struct Node
      8 {
      9     int begin;        // 起点
     10     int weight;     // 权值
     11     int end;        // 末点
     12 } edgeNode;
     13 
     14 class Graph
     15 {
     16 private:
     17     edgeNode edge[MAXEDGE];
     18 public:
     19     Graph()
     20     {
     21         for (int i = 0; i < MAXEDGE; ++i)
     22         {
     23             edge[i].begin = edge[i].weight = edge[i].end = 0;
     24         }
     25     }
     26     ~Graph()
     27     {}
     28 
     29 public:
     30     void InsertSort()
     31     {
     32        for (int i = 0; i < MAXEDGE- 1; ++i)
     33        {
     34             if (edge[i+1].weight < edge[i].weight)
     35             {
     36                  Node temp = edge[i+1];
     37                  int j = i + 1;
     38                  do
     39                  {
     40                      edge[j] = edge[j-1];
     41                      --j;
     42                  } while(j >= 0 && edge[j].weight > temp.weight);
     43                                 
     44                  edge[j+1] = temp;
     45             }
     46         }
     47     }
     48 
     49     istream & operator>>(istream &in)
     50     {
     51         int begin, value, end;
     52         cout << "请输入15条边的起点 终点 权值:" << endl;
     53         for (int i = 0; i < MAXEDGE; ++i)
     54         {
     55             in >> begin >> end >> value;
     56             edge[i].begin = begin;
     57             edge[i].weight = value;
     58             edge[i].end = end;
     59         }
     60         return in;
     61     }
     62     ostream & operator<<(ostream &out)
     63     {
     64         // 插入排序
     65         InsertSort();
     66         out << "输出排序边权值后信息:" << endl;
     67         for (int i = 0; i < MAXEDGE; ++i)
     68         {
     69             out << "edge[" << i << "] " << edge[i].begin << "  " << edge[i].weight << " " << edge[i].end << endl;
     70         }
     71         return out;
     72     }
     73     // 克鲁斯卡尔算法
     74     void MiniSpanTree_Kruskal()
     75     {
     76         int i = 0, n = 0, m = 0;
     77         int parent[MAXVER];
     78         for ( ; i < MAXVER; ++i)
     79             parent[i] = 0;
     80         for (i = 0; i < MAXEDGE; ++i)
     81         {
     82             n = Find(parent, edge[i].begin);
     83             m = Find(parent, edge[i].end);
     84             if (n != m)
     85             {
     86                 parent[n] = m;
     87                 cout << " " << edge[i].begin << " " << edge[i].end << " " << edge[i].weight << endl;
     88             }
     89         }
     90     }
     91 
     92     int Find(int *parent, int f)
     93     {
     94         while (parent[f] > 0)
     95             f = parent[f];
     96         return f;
     97     }
     98 };
     99 
    100 istream & operator>>(istream &in, Graph &g)
    101 {
    102     g >> in;
    103     return in;
    104 }
    105 
    106 ostream & operator<<(ostream &out, Graph &g)
    107 {
    108     g << out;
    109     return out;
    110 }
    111 
    112 void main()
    113 {
    114     Graph myg;
    115     cin >> myg;
    116     cout << myg;
    117     myg.MiniSpanTree_Kruskal();
    118 }
    119  // 备注:
    120  // 最小生成树克鲁斯卡尔算法实现
    121  // 整理于2013-12-04
    122  // 测试需要输入:
    123  /*
    124  起始   终点   权值
    125  0 1 10
    126  0 5 11
    127  1 2 18
    128  1 8 12
    129  1 6 16
    130  2 8 8
    131  2 3 22
    132  3 8 21
    133  3 6 24
    134  3 7 16
    135  3 4 20
    136  4 7 7
    137  4 5 26
    138  5 6 17
    139  6 7 19
    140   */
    View Code

    Good  Good  Study, Day  Day  Up.

    顺序  选择  循环  总结

  • 相关阅读:
    最近花了几个夜晚帮师妹整了一个企业网站
    英文学习网站
    Visual Studio 常用快捷键 (二)
    Visual Studio 常用快捷键
    学习英文之社区,博客及源码
    CodeForces 676D代码 哪里有问题呢?
    线程中调用python win32com
    Python 打包工具cx_freeze 问题记录及解决办法
    HDU1301 Jungle Roads
    HDU 1875 畅通工程再续
  • 原文地址:https://www.cnblogs.com/Braveliu/p/3457872.html
Copyright © 2011-2022 走看看