上后谈爱情

导航

 

1.krusual算法通过边生成有权不分方向的图中最小生成树,第一点:建立一个从小到大排序的数组(Krusual的生成数组);第二点:通过集合中并操作,对新加入的边(对新加入顶点通过集合的Union操作防止产生环路)。

#include<iostream>
using namespace std;
//Krusual算法的理解,依次从边中挑选出不形成回路的边形成森林
typedef char VerterType;
//使用邻接矩阵
#define MAxSize 20
int father[MAxSize],son[MAxSize];
//father表示每一个节点的父节点
typedef struct Graph{
    int VerterNum,edgenum;
    VerterType ver[MAxSize];
    int edge[MAxSize][MAxSize];

}Graph;
//定义一个边集结构,用来存储图上边的信息
//存储生成图,经过排序之后的边上的图,采用集概念防止其产生回路
typedef struct gEdge{
    int begin;
    int end;
    int weight;
    gEdge():begin(0),end(0),weight(NULL){};
}gEdge;

Graph G;
void CreateGraph()
{
    int VerterNum;char ver;
    cout<<"请输入顶点总数"<<endl;
    cin>>VerterNum;
    int i,j;
    memset(G.edge,0,sizeof(int)*50);
    cout<<"请输入图的顶点"<<endl;
    for(i=0;i<VerterNum;i++)
    {
        cin>>ver;
        G.ver[i]=ver;
    }
    cout<<"请输入有向图相对应的邻接矩阵"<<endl;
    int val=0;int edgenum=0;
    for(i=0;i<VerterNum;i++)
        for(j=0;j<VerterNum;j++)
        { 
                    cin>>val;
                    G.edge[i][j]=val;
                    
        }

        
        cout<<endl;
        //因为是有向图,
        for(i=0;i<VerterNum;i++)
        for(j=i;j<VerterNum;j++)
        {   
                    if(G.edge[i][j]!=0)
                    {    edgenum++;}
                    
        }
        //只要其上三角就行
        G.VerterNum=VerterNum;G.edgenum=edgenum;
}
//对数据边进行排序,产生生成图
gEdge *CreateEdge()
{
    //边的数组
    gEdge *p=new gEdge[G.edgenum];
    int i,j,k=0;
    for(i=0;i<G.VerterNum;i++)
        for(j=i;j<G.VerterNum;j++)
        {//选择插入排序
            if(G.edge[i][j]!=0)
            {
                p[k].begin=i;
                p[k].end=j;
                p[k].weight=G.edge[i][j];
                k++;
            
            }        
        }
        gEdge temp;
        for( i=0; i<G.edgenum-1; i++ )                  //对边集数组进行选择排序  
        for( j=i+1; j<G.edgenum; j++ )  
            if( p[i].weight > p[j].weight ) {  
                temp = p[i];  
                p[i] = p[j];  
                p[j] = temp;  
            }  
  
    return p;  
}

int unionsearch(int x) //查找根结点+路径压缩  
{  
    return x == father[x] ? x : unionsearch(father[x]);  
}  
bool Union(int x,int y)
{
    int root1,root2;
    root1=unionsearch(x);
    root2=unionsearch(y);
    if(root1==root2)
    {
        return false;
    }
    else
    {
        if(son[root1]>=son[root2])
        {
            father[root2]=root1;
            son[root1]+=son[root2];//儿子接点数
        }
        else{
            father[root1]=root2;
            son[root2]+=son[root1];
        }
    }
    return true;
}
void Krusual()
{
    //得到Krusual排序生成矩阵信息;
    gEdge *p=CreateEdge();
    int i ,j=0;int totalval=0;
    //没有环的矩阵
    int *MST=new int[G.edgenum];
    //使用Set中并操作,将原始是edgenum条离散的树整合成森林
    //将其初始化,开始时候每个顶点的父节点都是自己,最后形成的森林(不成环)
    for(i=0;i<G.VerterNum;i++)
    {
        father[i]=i;
        son[i]=1;
    }
    int flag[MAxSize];
    memset(flag,-1,sizeof(int)*MAxSize);
    for(i=0;i<G.edgenum;i++)
    {
        if(Union(p[i].begin,p[i].end))
        {
            totalval+=p[i].weight;
            MST[j++]=i;
            flag[i]=1;
            cout<<G.ver[p[i].begin]<<"-->"<<G.ver[p[i].end]<<endl;
        }
    }

    if(j==G.VerterNum-1)
    {
        cout<<totalval<<endl;
    }else
    {
        cout<<"datat error"<<endl;
    }
}
int main()
{
    
    CreateGraph();
    Krusual();
    return 0;
}

 

 

posted on 2016-11-13 20:12  上后谈爱情  阅读(282)  评论(0编辑  收藏  举报