无向连通网的最小生成树算法[第3部分]

来源:互联网 发布:数组splice 删除 编辑:程序博客网 时间:2024/05/29 13:57
普利姆算法的测试数据如下:每行数据表示边的两个端点和权值10 131 0 42 1 23 0 34 3 85 1 25 2 25 4 16 3 107 4 48 5 48 7 69 6 59 7 2

普利姆最小生成树算法:

/*    时间:2017.1.1    描述:普利姆算法求解最小生成树*/#include<iostream>#include<climits>#include<cstdio>#include<iomanip>#include<cstring>#include<fstream>#define INF INT_MAX#define FILEINPUT 1using namespace std;typedef struct edgeNode{    int from,to;    int cost;}EDGENODE;void creatMatrix(int **AdjMatrix,int n,int e);                              //构建无向图的邻接矩阵void printMatrix(int **AdjMatrix,int n);                                    //输出图的邻接矩阵void initEdgeSet(int **AdjMatrix,EDGENODE *edgeSet,int n,int start);        //初始化边集int  chooseEdge(EDGENODE *edgeSet,int n,int index);                         //从候选边集中选取权重最小的边void modfiyEdgeSet(int **AdjMatrix,EDGENODE *edgeSet,int n,int index,int to);//调整候选边集void primMst(int **AdjMatrix,EDGENODE *edgeSet,int n,int start);            //普利姆算法void printMst(EDGENODE *edgeSet,int n);                                     //输出最小生成树选举结果int main(){    //freopen("data.txt","r",stdin);    #if FILEINPUT                                           //条件编译:输入重定向到文件(输入邻接矩阵数据)        ifstream fin("data.txt");        streambuf *strm_buf=cin.rdbuf();        cin.rdbuf(fin.rdbuf());    #endif    int i,n,e,start;    int **AdjMatrix;                                        //存储邻接矩阵    EDGENODE *edgeSet;                                      //存储最小生成树选的边集    cout<<"Enter the number of nodes and edges:"<<endl;    cin>>n>>e;    AdjMatrix=(int **)malloc(sizeof(int *)*n);              //为邻接矩阵分配存储空间    for(i=0;i<n;i++)        AdjMatrix[i]=(int *)malloc(sizeof(int)*n);    edgeSet=(EDGENODE *)malloc(sizeof(EDGENODE)*n);         //为最小生成树边集合配存储空间    creatMatrix(AdjMatrix,n,e);                             //构建无向图的邻接矩阵    printMatrix(AdjMatrix,n);                               //输出图的邻接矩阵    #if FILEINPUT                                           //条件编译:输入重定向到键盘(输入普利姆算法的起始顶点)        cin.rdbuf(strm_buf);    #endif    while(1)    {        cout<<"Enter the start position of the Graph: ";        cin>>start;        primMst(AdjMatrix,edgeSet,n,start);        printMst(edgeSet,n);    }    #if FILEINPUT                                           //条件编译:输入重定向到键盘(输入普利姆算法的起始顶点)        fin.close();    #endif    return 0;}void creatMatrix(int **AdjMatrix,int n,int e){    int i,j,from,to,cost;    for(i=0;i<n;i++)        for(j=0;j<n;j++)            AdjMatrix[i][j]=INF;    cout<<"<from----to----cost>"<<endl;    for(i=0;i<e;i++)    {        cin>>from>>to>>cost;        AdjMatrix[from][to]=cost;        AdjMatrix[to][from]=cost;    }}void printMatrix(int **AdjMatrix,int n){    int i,j;    for(i=0;i<n;i++)    {        for(j=0;j<n;j++)            if(AdjMatrix[i][j]==INF)                cout<<setiosflags(ios::left)<<setw(6)<<"INF";            else                cout<<setiosflags(ios::left)<<setw(6)<<AdjMatrix[i][j];        cout<<endl;    }}void initEdgeSet(int **AdjMatrix,EDGENODE *edgeSet,int n,int start){    int i,index=0;    for(i=0;i<n;i++)        if(i!=start)        {            edgeSet[index].from=start;            edgeSet[index].to=i;            edgeSet[index].cost=AdjMatrix[start][i];            index++;        }}int chooseEdge(EDGENODE *edgeSet,int n,int index){    int minCost=INF,minPos,i;    for(i=index;i<n-1;i++)        if(edgeSet[i].cost<minCost)        {            minCost=edgeSet[i].cost;            minPos=i;        }    if(minCost==INF)    {        cout<<"The Graph is disconnected!"<<endl;        exit(1);//图不连通,程序结束    }    return minPos;}void modfiyEdgeSet(int **AdjMatrix,EDGENODE *edgeSet,int n,int index,int to){    int i,cost;    for(i=index;i<n-1;i++)    {        cost=AdjMatrix[to][edgeSet[i].to];        if(cost<edgeSet[i].cost)        {            edgeSet[i].cost=cost;            edgeSet[i].from=to;        }    }}void primMst(int **AdjMatrix,EDGENODE *edgeSet,int n,int start){    int iter,minPos,to;    EDGENODE edge;    initEdgeSet(AdjMatrix,edgeSet,n,start);     //初始化边集合    for(iter=0;iter<n-1;iter++)    {        minPos=chooseEdge(edgeSet,n,iter);      //从边集中选择取值最小边        edge=edgeSet[minPos];                   //将选择的最小边edgeSet[iter]        edgeSet[minPos]=edgeSet[iter];                  edgeSet[iter]=edge;        to=edgeSet[iter].to;                    //将选择的边结点加入U集合        modfiyEdgeSet(AdjMatrix,edgeSet,n,iter,to);//调整候选边结点    }}void printMst(EDGENODE *edgeSet,int n){    int index;    int totalCost=0;    for(index=0;index<n-1;index++)    {        cout<<"("<<edgeSet[index].from<<","<<edgeSet[index].to<<") "<<edgeSet[index].cost<<endl;        totalCost+=edgeSet[index].cost;    }    cout<<"totalCost: "<<totalCost<<endl;}
克鲁斯科尔算法的测试数据:第一行表示图的顶点数和边数;从第二行开始表示表的顶点编号和权值10 130 1 41 2 20 3 33 4 81 5 22 5 24 5 13 6 104 7 45 8 47 8 66 9 57 9 2

克鲁萨卡尔算法:

/*    时间:2017.1.1    描述:结合并查集实现克鲁斯卡尔算法求最小生成树*/#include<iostream>#include<climits>#include<iomanip>#include<cstring>#include<fstream>#include<algorithm>#define INF INT_MAX#define FILEINPUT 1using namespace std;typedef struct edgeNode{    int from,to;    int cost;}EDGENODE;bool operator<(const EDGENODE &a,const EDGENODE &b){    if(a.cost!=b.cost)        return a.cost<b.cost;    else if(a.from!=b.from)        return a.from<b.from;    else         return a.to<b.to;}int flag[512];void creatMatrix(int **AdjMatrix,EDGENODE *edgeSet,int n,int e);void printMatrix(int **AdjMatrix,int n);void printEdgeSet(EDGENODE *edgeSet,int e);void kruskalMst(EDGENODE *edgeSet,int n,int e);int findRootEdge(int nodeNumber);int mergeEdge(int nodeFrom,int nodeTo);int main(){    //freopen("data.txt","r",stdin);    #if FILEINPUT                                           //条件编译:输入重定向到文件(输入邻接矩阵数据)        ifstream fin("data.txt");        streambuf *strm_buf=cin.rdbuf();        cin.rdbuf(fin.rdbuf());    #endif    int i,n,e;    int **AdjMatrix;                                        //存储邻接矩阵    EDGENODE *edgeSet;                                      //边集合    cout<<"Enter the number of nodes and edges:"<<endl;         cin>>n>>e;    AdjMatrix=(int **)malloc(sizeof(int *)*n);              //为邻接矩阵分配存储空间    for(i=0;i<n;i++)        AdjMatrix[i]=(int *)malloc(sizeof(int)*n);    edgeSet=(EDGENODE *)malloc(sizeof(EDGENODE)*e);         //为边集合分配存储空间    for(i=0;i<n;i++)                                        //初始化并查集        flag[i]=i;    creatMatrix(AdjMatrix,edgeSet,n,e);    printMatrix(AdjMatrix,n);    kruskalMst(edgeSet,n,e);    #if FILEINPUT                                           //条件编译:输入重定向到键盘(输入普利姆算法的起始顶点)        cin.rdbuf(strm_buf);        fin.close();    #endif    return 0;}void creatMatrix(int **AdjMatrix,EDGENODE *edgeSet,int n,int e){    int i,j,from,to,cost;    EDGENODE edge;    for(i=0;i<n;i++)        for(j=0;j<n;j++)            AdjMatrix[i][j]=INF;    cout<<"<from----to----cost>"<<endl;    for(i=0;i<e;i++)    {        cin>>from>>to>>cost;        AdjMatrix[from][to]=cost;        AdjMatrix[to][from]=cost;        edge.from=from;        edge.to=to;        edge.cost=cost;        edgeSet[i]=edge;    }}void printMatrix(int **AdjMatrix,int n){    int i,j;    for(i=0;i<n;i++)    {        for(j=0;j<n;j++)        {            if(AdjMatrix[i][j]==INF)                cout<<setiosflags(ios::left)<<setw(6)<<"INF";            else                cout<<setiosflags(ios::left)<<setw(6)<<AdjMatrix[i][j];        }        cout<<endl;    }}void printEdgeSet(EDGENODE *edgeSet,int e){    int index=0;    for(index=0;index<e;index++)        cout<<"("<<edgeSet[index].from<<","<<edgeSet[index].to<<") "<<edgeSet[index].cost<<endl;}int findRootEdge(int nodeNumber) {    int i,j,root;    root=nodeNumber;    while (flag[root]!=root)                //循环结束,则找到同一边集中的最小结点编号          root= flag[root];           i=nodeNumber;    while(i!=root)                          //本循环修改查找路径中所有边结点编号    {        j=flag[i];        flag[i]=root;        i=j;    }    return root;}int mergeEdge(int nodeFrom,int nodeTo)      //边结点合并到连通图中{    int indexFrom=findRootEdge(nodeFrom);    int indexTo=findRootEdge(nodeTo);    if(flag[indexFrom]<flag[indexTo])       flag[indexTo]=indexFrom;    else       flag[indexFrom]=indexTo;    if(indexFrom==indexTo)        return 1;    else        return 0;}void kruskalMst(EDGENODE *edgeSet,int n,int e){    int index=0;    int countEdge=0;    int minCost=0;    //cout<<"------------------------------------"<<endl;    //printEdgeSet(edgeSet,e);    sort(edgeSet,edgeSet+e);                            //对边集进行快速排序    //cout<<"------------------------------------"<<endl;    //printEdgeSet(edgeSet,e);    //cout<<"------------------------------------"<<endl;    while(index<e)    {        int from=edgeSet[index].from;        int to=edgeSet[index].to;        int cost=edgeSet[index].cost;        if(mergeEdge(from,to)==0)                       //利用并查集判断环路,同时对查找路径进行压缩合并        {            countEdge++;            minCost+=cost;            cout<<"("<<from<<","<<to<<") "<<cost<<endl;            index++;        }        else        {            index++;        }        if(countEdge==n-1)        {            break;        }    }    if(index<e)                                                     cout<<"minCost: "<<minCost<<endl;    else    {        cout<<"The Graph is disconnected!"<<endl;       //index>=e则不能构造最小生成树    }}
0 0
原创粉丝点击