zoukankan      html  css  js  c++  java
  • 无向网的最小生成树——Kruskal算法(转)

    最小生成树的Kruskal算法,适用于边较少的连通网,下面的算法中没有将其像上一篇日志一样转换为一棵树,要转换的话就像上一篇日志一样,进行建树就可以了,下面是代码

    "graph.h"文件

      1 #include<iostream>
    2 #include<queue>
    3 #include<string>
    4 using namespace std;
    5
    6 const int MAX_VERTEX_NUM=20;
    7 bool visited[20];//用于遍历时辅组使用
    8
    9 class VNode;
    10 //表结点
    11 class ArcNode
    12 {
    13 public:
    14 int adjvex;
    15 int weight;
    16 ArcNode *nextarc;
    17 friend class VNode;
    18 };
    19
    20 class ALGraph;
    21 //头结点
    22 class VNode
    23 {
    24 string data;
    25 ArcNode *firstarc;
    26 friend class ALGraph;
    27 };
    28
    29 class EDGE
    30 {
    31 public:
    32 int begin;
    33 int end;
    34 int cost;
    35 friend class ALGraph;
    36 };
    37
    38 EDGE edges[20]; //设为全局变量,便于将初始化和使用分开
    39
    40 class ALGraph
    41 {
    42 private:
    43 VNode vertices[MAX_VERTEX_NUM];
    44 int vexnum;
    45 int arcnum;
    46 public:
    47 void CreateUDG_ALG()
    48 {
    49 //采用邻接表构造无向网G
    50 //创建邻接表的过程顺便将信息存入edges中,便于后面的求最小生成树
    51 string v1,v2;
    52 int i,j,k,w;
    53 cout<<"输入顶点数和边数:";
    54 cin>>vexnum>>arcnum;
    55
    56 cout<<"输入顶点民称:";
    57 for(i=0;i<vexnum;i++)
    58 {
    59 cin>>vertices[i].data;
    60 vertices[i].firstarc=NULL;
    61 }
    62
    63 //输入各弧并构造邻接表
    64 for(k=0;k<arcnum;k++)
    65 {
    66 cout<<"输入边所对应的两个顶点和该边的权值:";
    67 cin>>v1>>v2>>w;
    68 i=Locate_Vex(v1);
    69 j=Locate_Vex(v2);
    70 while(i<0|| i>vexnum-1 || j<0 || j>vexnum-1)
    71 {
    72 cout<<"结点位置输入错误,重新输入: ";
    73 cin>>v1>>v2>>w;
    74 i=Locate_Vex(v1);
    75 j=Locate_Vex(v2);
    76 }
    77
    78 ArcNode *p=new ArcNode;
    79 p->adjvex=j;
    80 p->weight=w;
    81 p->nextarc=vertices[i].firstarc;
    82 vertices[i].firstarc=p;
    83
    84 ArcNode *q=new ArcNode;
    85 q->adjvex=i;
    86 q->weight=w;
    87 q->nextarc=vertices[j].firstarc;
    88 vertices[j].firstarc=q;
    89
    90 edges[k].begin=i;
    91 edges[k].end=j;
    92 edges[k].cost=w;
    93 }
    94 }
    95
    96 int Locate_Vex(string v) //返回顶点在数组中的位置
    97 {
    98 for(int k=0;vertices[k].data!=v;k++);
    99 return k;
    100 }
    101
    102 void BFS_Traverse() //广度优先遍历
    103 {
    104 int i,k,w;
    105 queue<int> q;
    106 ArcNode *p;
    107 for(i=0;i<vexnum;i++)
    108 visited[i]=false;
    109 for(i=0;i<vexnum;i++)
    110 {
    111 if(!visited[i])
    112 {
    113 visited[i]=true;
    114 cout<<vertices[i].data<<" ";
    115 if(vertices[i].firstarc)
    116 q.push(i);
    117 while(!q.empty())
    118 {
    119 k=q.front();
    120 q.pop();
    121 for(p=vertices[k].firstarc;p;p=p->nextarc)
    122 {
    123 w=p->adjvex;
    124 if(!visited[w])
    125 {
    126 visited[w]=true;
    127 cout<<vertices[w].data<<" ";
    128 if(vertices[w].firstarc)
    129 q.push(w);
    130 }
    131 }
    132 }
    133 }
    134 }
    135 }
    136
    137 //深度优先遍历
    138 void DFS_Traverse()
    139 {
    140 for(int i=0;i<vexnum;i++)
    141 visited[i]=false;
    142 for(i=0;i<vexnum;i++)
    143 if(!visited[i])
    144 DFS(i);
    145 }
    146
    147 void DFS(int i)
    148 {
    149 visited[i]=true;
    150 cout<<vertices[i].data<<" ";
    151 ArcNode *p;
    152 for(p=vertices[i].firstarc;p;p=p->nextarc)
    153 {
    154 int w=p->adjvex;
    155 if(!visited[w])
    156 DFS(w);
    157 }
    158 }
    159
    160 /*Kruskal算法*/
    161 /*------------------------------------------------
    162 /假设N=(V,{VR})是一个连通网,令最小生成树初始状态为
    163 /只有n个顶点的非连通图,T=(V,{}),图中的每个顶点自成
    164 /一个连通分量.在VR中选择权值最小边,若该边依附的顶点
    165 /落在T的不同连通分量上,则将此边加入T中,然后合并连个
    166 /连通分量否则就舍弃那条边,直至T中所有顶点都在同
    167 /一连通分量上为止。
    168 /--------------------------------------------------
    169 /为了判断所选的边加入到生成树中是否会形成回路,可以
    170 /将各个顶点划分为所属集合的方法来解决,每个集合中的顶点
    171 /表示一个无回路的连通分量.用parents[]表示这些顶点,初始
    172 /值为0,表示各顶点自成一个连通分量.从edges中依次序选择
    173 /一条边时,查找它的两个顶点所属的分量的bnf和edf.
    174 /当bnf和edf不同时,就说明该边的两个顶点属于两个不同
    175 /集合,相等时说明在同一个集合。
    176 /------------------------------------------------*/
    177 void Kruskal_Min_Tree()
    178 {
    179 int bnf,edf;
    180 int parents[20];
    181 Sort(edges); //按照权值大小排序
    182
    183 for(int i=0;i<vexnum;i++) //初始化parent[]数组
    184 parents[i]=0;
    185 for(i=0;i<arcnum;i++)
    186 {
    187 bnf=Find(parents,edges[i].begin);
    188 edf=Find(parents,edges[i].end);
    189 if(bnf!=edf)
    190 {
    191 parents[bnf]=edf;
    192 cout<<"("<<vertices[edges[i].begin].data<<','<<vertices[edges[i].end].data<<','<<edges[i].cost<<')'<<endl;
    193 }
    194 }
    195 }
    196
    197 void Sort(EDGE edges[])
    198 {
    199 for(int i=0;i<arcnum;i++)
    200 for(int j=i+1;j<arcnum;j++)
    201 if(edges[i].cost>edges[j].cost)
    202 {
    203 EDGE temp;
    204 temp.begin=edges[i].begin;
    205 temp.end=edges[i].end;
    206 temp.cost=edges[i].cost;
    207 edges[i].begin=edges[j].begin;
    208 edges[i].end=edges[j].end;
    209 edges[i].cost=edges[j].cost;
    210 edges[j].begin=temp.begin;
    211 edges[j].end=temp.end;
    212 edges[j].cost=temp.cost;
    213 }
    214 }
    215
    216 int Find(int parents[],int f)
    217 {
    218 while(parents[f]>0)
    219 f=parents[f];
    220 return f;
    221 }
    222
    223 };

      测试函数"main.cpp"

     1 #include"graph.h"
    2
    3 int main()
    4 {
    5 ALGraph G;
    6 G.CreateUDG_ALG();
    7
    8 cout<<"图的广度优先遍历为:";
    9 G.BFS_Traverse();
    10 cout<<endl;
    11
    12 cout<<"图的深度优先遍历为:";
    13 G.DFS_Traverse();
    14 cout<<endl;
    15
    16 cout<<"最小生成树的边的组成和对应的权值为:"<<endl;
    17 G.Kruskal_Min_Tree();
    18 cout<<endl;
    19
    20 return 0;
    21 }

      输出结果:

     1 输入顶点数和边数:9 15
    2 输入顶点民称:v1 v2 v3 v4 v5 v6 v7 v8 v9
    3 输入边所对应的两个顶点和该边的权值:v1 v6 7
    4 输入边所对应的两个顶点和该边的权值:v1 v7 3
    5 输入边所对应的两个顶点和该边的权值:v1 v2 2
    6 输入边所对应的两个顶点和该边的权值:v2 v7 6
    7 输入边所对应的两个顶点和该边的权值:v2 v3 4
    8 输入边所对应的两个顶点和该边的权值:v6 v5 6
    9 输入边所对应的两个顶点和该边的权值:v6 v9 5
    10 输入边所对应的两个顶点和该边的权值:v7 v9 1
    11 输入边所对应的两个顶点和该边的权值:v7 v8 3
    12 输入边所对应的两个顶点和该边的权值:v3 v8 2
    13 输入边所对应的两个顶点和该边的权值:v3 v4 2
    14 输入边所对应的两个顶点和该边的权值:v9 v5 2
    15 输入边所对应的两个顶点和该边的权值:v9 v8 4
    16 输入边所对应的两个顶点和该边的权值:v8 v4 8
    17 输入边所对应的两个顶点和该边的权值:v5 v4 1
    18 图的广度优先遍历为:v1 v2 v7 v6 v3 v8 v9 v5 v4
    19 图的深度优先遍历为:v1 v2 v3 v4 v5 v9 v8 v7 v6
    20 最小生成树的边的组成和对应的权值为:
    21 (v7,v9,1)
    22 (v5,v4,1)
    23 (v3,v8,2)
    24 (v3,v4,2)
    25 (v9,v5,2)
    26 (v1,v2,2)
    27 (v1,v7,3)
    28 (v6,v9,5)
    29
    30 Press any key to continue

      

  • 相关阅读:
    2019牛客暑期多校训练营(第三场)B题、H题
    2019牛客暑期多校训练营(第四场)k题、j题
    Manacher算法 & Palindrome
    HDU 3336——Count the string
    判断一个点是否在三角形内
    P1052 过河
    P1353 [USACO08JAN]跑步Running
    hdu 1686 Oulipo
    Cyclic Nacklace HDU
    高精地图技术分析
  • 原文地址:https://www.cnblogs.com/math2010/p/2142073.html
Copyright © 2011-2022 走看看