zoukankan      html  css  js  c++  java
  • 数据结构课程设计-克鲁斯卡尔算法最小生成树

         假设连通网N=(V,{E}),则令最小生成树的初始状态为只有n个顶点而无边的非连通图T=(V,{∮}),图中每个顶点自成一个连通分量。在E中选择代价最小的边,若该边依附的顶点落在T中不同的连通分量上,则将此边加入到T中,否则舍去此边而选择下一条代价最小的边。依次类推,直至T中所有顶点都在同一连通分量上为止。

    (1)根据原图,构造一个只含n个顶点,边集为空的子图。若将图中各个顶点看成一棵树的根节点,则它是一个含有n棵树的森林。

    (2)从网的边集 E 中选取一条权值最小的边,若该条边的两个顶点分属不同的树,则将其加入子图。也就是说,将这两个顶点分别所在的两棵树合成一棵树;反之,若该条边的两个顶点已落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之

    (3)依次类推,直至森林中只有一棵树,也即子图中含有 n-1条边为止。

         手动输入建立邻接矩阵:

    首先输入城市数目n,建立n*n大小空矩阵。其次输入城市名称,并利用map函数使名称与数字可以相互转化。最后输入可构建线路的条数x,并输入x条边及权值填充邻接矩阵。

                                                

          寻找根结点

    根节点数组中保存对应的上一节点的值。依次往上寻找,知道数组中存储值为0,此时的参数即位目前的根节点。

                                             

          克鲁斯卡尔算法输出

    建立边集数组,保证起始点的数值小于终点。利用sort函数,按权值将边从小到大排列。从小到大遍历所有边,查找每条边的起始点的根节点和终点的根节点。如果不同,证明加上这条边不会产生回路,输出这条边的信息,并使节点数组中终点的上一节点为初始点。

                                       

    界面:

     

    代码如下:

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <stdlib.h>
      5 #include <algorithm>
      6 #include <map>
      7 #include <iomanip>
      8 #include <fstream>
      9 using namespace std;
     10 
     11 #define max_city 100   //最大城市数
     12 
     13 map <string,int> city_numbers;  //城市->编号
     14 
     15 map <int,string> numbers_city;  //编号->城市
     16 
     17 const int inf=0x3f3f3f3f;
     18 
     19 typedef struct
     20 {
     21     int maps[max_city][max_city];   //邻接矩阵
     22     int city_number;
     23     int city_way;  //城市数,线路数
     24 } Graph ;
     25 
     26 typedef struct
     27 {
     28     int way_begin;
     29     int way_end;
     30     int way_weight;
     31 } Ways;
     32 //线路集
     33 
     34 void BuildGraph1(Graph *this_graph)
     35 {
     36     printf("请输入城市数(按回车键结束输入):
    ");
     37     cin>>this_graph->city_number;
     38 
     39     for (int i=0;i<this_graph->city_number;i++)
     40     {
     41         for(int j=0;j<this_graph->city_number;j++)
     42         {
     43             if (i==j)
     44                 this_graph->maps[i][j]=0;
     45             else
     46                 this_graph->maps[i][j]=this_graph->maps[j][i]=inf;
     47         }
     48     }
     49 
     50     printf("请输入城市名称(城市名字之间用空格隔开,按回车键结束输入):
    ");
     51     for(int i=0;i<this_graph->city_number;i++)
     52     {
     53         char name[1000];
     54         cin>>name;
     55         city_numbers[name]=i;
     56         numbers_city[i]=name;
     57     }
     58 
     59     printf("请输入可构架线路数(按回车键结束输入):
    ");
     60     cin>>this_graph->city_way;
     61 
     62     printf("请输入每条线路两端的城市名及权值:
    ");
     63     for(int i=0;i<this_graph->city_way;i++)
     64     {
     65         char start[1000],last[1000];
     66         int weight;
     67         printf("请输入第%d条线路(城市名及权值用空格隔开,每条线路按回程键结束输入):
    ",i+1);
     68 
     69         cin>>start>>last>>weight;
     70         this_graph->maps[city_numbers[start]][city_numbers[last]]=this_graph->maps[city_numbers[last]][city_numbers[start]]=weight;
     71     }
     72 
     73 }
     74 //手动输入信息
     75 
     76 bool BuildGraph2(Graph *this_graph)
     77 {
     78     FILE *fp;
     79     char address[1000];
     80     printf("请输入文件的地址(按回车键结束输入):
    ");
     81     cin>>address;
     82 
     83     if((fp=fopen(address,"r"))==NULL)
     84         return false;
     85 
     86     if(fscanf(fp,"%d",&this_graph->city_number)==EOF)
     87         return false;
     88 
     89     for (int i=0;i<this_graph->city_number;i++)
     90     {
     91         for(int j=0;j<this_graph->city_number;j++)
     92         {
     93             if (i==j)
     94                 this_graph->maps[i][j]=0;
     95             else
     96                 this_graph->maps[i][j]=this_graph->maps[j][i]=inf;
     97         }
     98     }
     99 
    100     for(int i=0;i<this_graph->city_number;i++)
    101     {
    102         char name[1000];
    103         if(fscanf(fp,"%s",name)==EOF)
    104             return false ;
    105         city_numbers[name]=i;
    106         numbers_city[i]=name;
    107     }
    108 
    109     if(fscanf(fp,"%d",&this_graph->city_way)==EOF)
    110         return false;
    111 
    112     for(int i=0;i<this_graph->city_way;i++)
    113     {
    114         char start[1000],last[1000];
    115         int weight;
    116         if(fscanf(fp,"%s%s%d",start,last,&weight)==EOF)
    117              return false;
    118         this_graph->maps[city_numbers[start]][city_numbers[last]]=this_graph->maps[city_numbers[last]][city_numbers[start]]=weight;
    119     }
    120 
    121     fclose(fp);
    122     return true;
    123 }
    124 //从文件读入信息
    125 
    126 bool cmp(Ways first,Ways last)
    127 {
    128     return first.way_weight<last.way_weight;
    129 }
    130  //排序条件
    131 
    132 int find_parent(int parent[],int find_city)
    133 {
    134     while(parent[find_city]>0)
    135     {
    136         find_city=parent[find_city];
    137     }
    138     return find_city;
    139 }
    140 //寻找根节点
    141 
    142 void Putout1(Graph this_graph)
    143 {
    144     int num=0;
    145     int parent[max_city];
    146     Ways way[max_city];
    147     memset(parent,0,sizeof(parent));
    148 
    149     for (int i=0;i<this_graph.city_number;i++)
    150     {
    151         for(int j=i+1;j<this_graph.city_number;j++)
    152         {
    153             if(this_graph.maps[i][j]!=inf)
    154             {
    155                 way[num].way_begin=i;
    156                 way[num].way_end=j;
    157                 way[num++].way_weight=this_graph.maps[i][j];
    158             }
    159         }
    160     }
    161     //建立边集
    162 
    163     sort(way,way+num,cmp);
    164     //边集排序
    165 
    166     int sum=0;
    167     printf("最低经济方案如下如下:
    ");
    168     cout<<"编号"<<setw(8)<<"城市1"<<setw(8)<<"城市2"<<setw(8)<<"权值"<<endl;
    169     for (int i=0;i<this_graph.city_way;i++)
    170     {
    171         int n=find_parent(parent,way[i].way_begin);
    172         int m=find_parent(parent,way[i].way_end);
    173         //寻找首位两点的根
    174 
    175         if (n != m)
    176         {
    177             parent[n] = m;
    178             char city1[1000],city2[1000];
    179             cout<<++sum<<setw(8)<<numbers_city[way[i].way_begin]<<setw(8)<<numbers_city[way[i].way_end]<<setw(8)<<way[i].way_weight<<endl;
    180         }
    181         //假如n与m不等,说明两个顶点不会产生回路
    182     }
    183 }
    184 //直接输出结果
    185 
    186 bool Putout2(Graph this_graph)
    187 {
    188     int num=0;
    189     int parent[max_city];
    190     Ways way[max_city];
    191     memset(parent,0,sizeof(parent));
    192 
    193     for (int i=0;i<this_graph.city_number;i++)
    194     {
    195         for(int j=i+1;j<this_graph.city_number;j++)
    196         {
    197             if(this_graph.maps[i][j]!=inf)
    198             {
    199                 way[num].way_begin=i;
    200                 way[num].way_end=j;
    201                 way[num++].way_weight=this_graph.maps[i][j];
    202             }
    203         }
    204     }
    205     //建立边集
    206 
    207     sort(way,way+num,cmp);
    208     //边集排序
    209 
    210     fstream fp;
    211     printf("请输入文件的地址(按回车键结束输入):
    ");
    212     int sum=0;
    213     char address[1000];
    214     cin>>address;
    215     fp.open(address);
    216 
    217     if(!fp)
    218         return false;
    219     fp<<"最低经济方案如下如下:"<<endl;
    220     fp<<"编号"<<setw(8)<<"城市1"<<setw(8)<<"城市2"<<setw(8)<<"权值"<<endl;
    221     for (int i=0;i<this_graph.city_way;i++)
    222     {
    223         int n=find_parent(parent,way[i].way_begin);
    224         int m=find_parent(parent,way[i].way_end);
    225         //寻找首位两点的根
    226 
    227         if (n != m)
    228         {
    229             parent[n] = m;
    230             char city1[1000],city2[1000];
    231             fp<<++sum<<setw(8)<<numbers_city[way[i].way_begin]<<setw(8)<<numbers_city[way[i].way_end]<<setw(8)<<way[i].way_weight<<endl;
    232         }
    233     }
    234     //假如n与m不等,说明两个顶点不会产生回路
    235     return true;
    236 }
    237 //打印到文件中
    238 
    239 int main()
    240 {
    241     int  ch;
    242 
    243     while(true)
    244     {
    245 
    246         printf("|-------------------------------------------------------|
    ");
    247         printf("|							|
    ");
    248         printf("|		  欢迎进入最小生成树系统!  		|
    ");
    249         printf("|							|
    ");
    250         printf("|-------------------------------------------------------|
    ");
    251         printf("|							|
    ");
    252         printf("|		    1——手动输入信息          		|
    ");
    253         printf("|		    2——从文件读入信息        		|
    ");
    254         printf("|		    0——退出系统        		|
    ");
    255         printf("|							|
    ");
    256         printf("|-------------------------------------------------------|
    ");
    257         printf("请输入选项编号(0 ~ 2): (按回车键结束输入)
    ");
    258 
    259         Graph this_graph;
    260         cin>>ch;
    261 
    262         if(ch==0)
    263             break;
    264 
    265         if(ch==1)
    266             BuildGraph1(&this_graph);
    267 
    268         else if(ch==2)
    269         {
    270             if(!BuildGraph2(&this_graph))
    271             {
    272                 printf("打开文件读入信息失败!
    ");
    273                 continue;
    274             }
    275             printf("打开文件读入信息成功!
    ");
    276         }
    277 
    278         printf("|-------------------------------------------------------|
    ");
    279         printf("|							|
    ");
    280         printf("|		    1——直接输出结果          		|
    ");
    281         printf("|		    2——输出到文件        		|
    ");
    282         printf("|		    0——退出系统        		|
    ");
    283         printf("|							|
    ");
    284         printf("|-------------------------------------------------------|
    ");
    285         printf("请输入选项编号(0 ~ 2): (按回车键结束输入)
    ");
    286 
    287         cin>>ch;
    288         if(ch==0)
    289             break;
    290 
    291         if(ch==1)
    292             Putout1(this_graph);
    293 
    294         else if(ch==2)
    295         {
    296             if(!Putout2(this_graph))
    297             {
    298                 printf("打开文件输入信息失败!
    ");
    299                 continue;
    300             }
    301             printf("打开文件输入信息成功!
    ");
    302         }
    303     }
    304 }
    View Code

     

     

  • 相关阅读:
    vim编辑器经常使用命令
    @RequestMapping value 能够反复吗 [
    [Android 4.4.2] 泛泰A870 Mokee4.4.2 20140531 RC1.0 by syhost
    leetcode——Reverse Linked List II 选择链表中部分节点逆序(AC)
    烤羊肉串引来的思考——命令模式
    全面解析Activity的生命周期
    PHP与Linux进程间的通信
    模块管理常规功能自己定义系统的设计与实现(36--终级阶段 综合查询[3])
    小米与格力的10亿豪赌!
    《Java设计模式》之装饰模式
  • 原文地址:https://www.cnblogs.com/kingbk/p/6286898.html
Copyright © 2011-2022 走看看