Quantcast
Channel: 看雪安全论坛
Viewing all articles
Browse latest Browse all 9556

帮忙看一下这个prim最小生成树的算法是不是有问题?

$
0
0
代码:

// Minimum-Cost-Spanning-Tree.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"


#include<iostream>
#include<stdlib.h>//产生随机数组用
#include<time.h> //同上
#include <list>
#include "windows.h"

using namespace std;


class MyArc
{
public:
        int m_beginVex;
        int m_endVex;
        int m_weight;
        MyArc(int beginVex,int endVex,int weight);
        MyArc(){}
        bool operator < (const MyArc& arc)
        {
                return m_weight<arc.m_weight;
        }
        bool operator == (const MyArc& arc)
        {
                return m_weight==arc.m_weight;
        }
        bool operator > (const MyArc& arc)
        {
                return m_weight>arc.m_weight;
        }
};

MyArc::MyArc(int beginVex,int endVex,int weight):m_beginVex(beginVex),m_endVex(endVex),m_weight(weight)
{

}

class Graph
{
public:
        int m_vexnum;//顶点数
        int m_arcnum;//弧数目
        int *m_pmatrix;
public:
        ~Graph();
        Graph(int vexnum);
        Graph(int vexnum,int *pmatrix);
        void insert(MyArc arc);//按权值大小排序插入
        bool bound(int x);  //判断顶点x是否已与其它顶点连通

};

//构造函数
Graph::Graph(int vexnum)
{
        m_pmatrix=new int[vexnum*vexnum];
        m_vexnum=vexnum;
        m_arcnum=0;
        for(int i=0;i<vexnum*vexnum;++i)
        {
                m_pmatrix[i]=0; //初始化邻接矩阵
        }


}

//构造函数
Graph::Graph(int vexnum,int *pmatrix)
{
        m_vexnum=vexnum;
        // m_arcnum=arcnum;
        m_pmatrix=new int[m_vexnum*m_vexnum];
        for(int i=0;i<m_vexnum*m_vexnum;++i)
        {
                m_pmatrix[i]=pmatrix[i];
        }
}

//测试 顶点x是否已与其他点连通
bool Graph::bound(int x)
{
        for(int i=0;i<m_vexnum;++i) if(m_pmatrix[x+i*m_vexnum]!=0) return true;
        return false;
}

//在邻接表中连通 arc表示的边,并且设置权
void Graph::insert(MyArc arc)
{
        m_pmatrix[arc.m_beginVex*m_vexnum+arc.m_endVex]=arc.m_weight;
        m_pmatrix[arc.m_endVex*m_vexnum+arc.m_beginVex]=arc.m_weight;
        ++m_arcnum;
}
//析构
Graph::~Graph()
{
        delete[] m_pmatrix;
        m_pmatrix = NULL;
}

class MyQueues
{
public:
        list<MyArc>  m_list;
        MyQueues(){}
        void insert_by_weight(const MyArc& arc);//边按权值插入队列中合适位置,
        void insert_Graph(const Graph &graph);//将图的连通分量插入队列
        void sort_by_number();//按照编号权值大小再次排列
        MyArc pop();
        MyArc pop_min(list<int> temp);// 对应节点的最小权值的边出队
};

MyArc MyQueues:: pop_min(list<int> temp)//顶点集合中到另一个集合权值最小的弧
{
        int min = 0;
        list<int>::iterator pos_vex = temp.begin();
        list<MyArc>::iterator pos = m_list.begin();
        list<MyArc>::iterator temp_pos;
        MyArc arc ;
        for(pos = m_list.begin(); pos != m_list.end(); pos++)
        {
                if(pos->m_beginVex == *pos_vex)
                {
                        min = pos->m_weight;//找到第一个作为最小
                        break;
                }
        }
        while(pos_vex!=temp.end())
        {
                pos = m_list.begin();
                while(pos!=m_list.end())
                {
                        if((pos->m_weight <=min)&&(pos->m_beginVex == *pos_vex||pos->m_endVex == *pos_vex) )//找到这顶点最小权值的边
                        {
                                arc = *pos;
                                min = pos->m_weight;
                                temp_pos = pos;

                        }
                        pos++;

                }
                pos_vex++;
        }
        m_list.erase(temp_pos);

        return arc;
}


//边出队
MyArc MyQueues::pop()
{
        MyArc arc=m_list.front();
        m_list.pop_front();
        return arc;
}
void MyQueues::sort_by_number()
{
        int arcnum = m_list.size();
        list<MyArc>::iterator pos=m_list.begin();


        list<MyArc> templist;
        int vexnum = 0;
        for(int i=0;i<arcnum;i++)
        {
                pos = m_list.begin();
                while(1)
                {
                        //pos = m_list.begin();
                        while(pos != m_list.end())
                        {
                                if(pos->m_beginVex == vexnum) //从零开始
                                {
                                        templist.push_back(*pos);
                                        pos = m_list.erase(pos);
                                }
                                else
                                {
                                        pos++;
                                }

                        }
                        if(pos == m_list.end())
                        {
                                vexnum++;
                                break;
                        }

                }

        }
        m_list = templist;
}
//边按权值插入队列中合适位置,
void MyQueues::insert_by_weight(const MyArc& arc)
{
        list<MyArc>::iterator pos=m_list.begin();
        while(pos!=m_list.end())
        {
                if(*pos>arc) break;
                else
                        ++pos;
        }
        m_list.insert(pos,arc);
}
//将图的连通分量插入队列
void MyQueues::insert_Graph(const Graph &graph)
{
        for(int i=0;i<graph.m_vexnum;++i)
        {
                for(int j=i+1;j<graph.m_vexnum;++j)//上三角矩阵的联通分量
                {
                        if(graph.m_pmatrix[i*graph.m_vexnum+j])
                                insert_by_weight(MyArc(i,j,graph.m_pmatrix[i*graph.m_vexnum+j]));
                }
        }
}
//用随机数组初始化matrix数组并且打印
void SetMatrix(int vexnum,int *pmatrix)
{
        srand((unsigned)time(NULL));
        for(int i=0;i<vexnum;++i)//产生随机权值矩阵
        {
                for(int j=i;j<vexnum;++j)
                {
                        if(j==i)
                        {
                                pmatrix[i*vexnum+j]=0;
                                continue;
                        }
                        int rnum=rand();
                        rnum%=99;
                        rnum++;//产生1~99的随机整数作为边的权值
                        pmatrix[i*vexnum+j]=rnum;//先填写上三角矩阵
                        pmatrix[j*vexnum+i]=rnum;//后填写下三角矩阵
                }
        }
        cout<<"***随机产生的各边权值矩阵 [顶点数为 "<<vexnum<<"] ****\n";
        for(int i=0;i<vexnum;++i)//输出随机权值矩阵
        {
                for(int j=0;j<vexnum;++j)
                {
                        cout<<pmatrix[i*vexnum+j]<<"\t";
                }
                cout<<endl;
        }

}


//判断连通边arc后 图graph 是否存在回路
bool IsCycle(Graph& graph, MyArc& arc)
{
        list<int> mylist;
        mylist.push_back(arc.m_beginVex);
        int *ps=new int[graph.m_vexnum];
        for(int i=0;i<graph.m_vexnum;++i)
                ps[i]=0;
        while(!mylist.empty())
        {
                int x=mylist.front();
                ps[x]=1;
                mylist.pop_front();
                for(int i=0;i<graph.m_vexnum;++i)
                {
                        if(graph.m_pmatrix[i+x*graph.m_vexnum]!=0)
                        {
                                if(i==arc.m_endVex) return true;
                                if(ps[i]!=1) mylist.push_back(i);
                        }
                }
        }
        delete[] ps;
        return false;//遍历完成没有环
}

//克鲁斯卡尔算法
void kruskal(const Graph& graph,Graph& smtree)
{
        MyQueues arcqueues;//保存从小到大排列的边
        arcqueues.insert_Graph(graph);
        MyArc myarc;//Arc表示边的类型
        int arcnum=0; //边的个数
        while(arcnum<graph.m_vexnum-1)//此处的含义为边的数目正好为顶点数目减一,注意与prim算法表达式相同但是含义不同
        {
                myarc=arcqueues.pop();
                if(!IsCycle(smtree,myarc))
                {
                        smtree.insert(myarc);
                        ++arcnum;
                }
        }
}

//prim算法
void prim(const Graph& graph,Graph& smtree)
{

        MyQueues arcqueues;//保存从小到大排列的边
        arcqueues.insert_Graph(graph);
        arcqueues.sort_by_number();

        MyArc myarc;//Arc表示边的类型
        int vexnum = 0; //已经放入集合的顶点个数
        int vex = 0; //初始顶点编号

        list<int> vexList;//已经放入最小生成树的顶点的集合
        vexList.push_back(vexnum);//先加入第0号节点
        list<int>::iterator pos = vexList.begin();


        int i = 1;
        while(vexnum<graph.m_vexnum-1)
        {
                //cout<<"end"<<endl;
                //if (vexnum==(graph.m_vexnum-1))
                //{
                        //break;
                //}
       
                myarc = arcqueues.pop_min(vexList);
                pos = vexList.begin();
                for (pos = vexList.begin() ; pos != vexList.end();)
                {
                        if ((myarc.m_endVex != *pos))
                        {
                                pos++;
                        }
                        else
                                break;

                }

                if(pos==vexList.end())//没有在已经的最小生成树的节点中
                {
                        smtree.insert(myarc);
                        //cout<<"insert      :"<<i++<<endl;
                        vexList.push_back(myarc.m_endVex);
                        vexnum++;

                }

        }

}

//输出最小生成树
void SmallestTreeOutput(const Graph& smtree)
{
        cout<<"最小生成树:"<<endl;
        int sum = 0;
        for(int i=0;i<smtree.m_vexnum;++i)//输出最小树
                for(int j=i+1;j<smtree.m_vexnum;++j)
                        if(smtree.m_pmatrix[i*smtree.m_vexnum+j])
                        {
                                int temp = smtree.m_pmatrix[i*smtree.m_vexnum+j];
                                cout<<'('<<i<<','<<j<<','<<temp<<')'<<endl;
                                sum = sum + temp;
                        }

        cout <<"最短距离为:"<<sum<<endl;
}


/*
主函数
*/

int main()
{
        int i;
        while(1)
        {

       
        cout<<"请输入顶点数目:";
        cin>>i;
        int vex=i;
        int *matrix=new int[vex*vex];
       

        SetMatrix(vex,matrix);
        Graph graph(vex,matrix) , smtree_kruskal(vex);

        kruskal(graph,smtree_kruskal);
        SmallestTreeOutput(smtree_kruskal);


        Graph smtree_prim(vex);
       
        prim(graph,smtree_prim);
        SmallestTreeOutput(smtree_prim);
        delete []matrix;
       
        }
        system("pause");
}

我运行的时候,prim算法跟kruskal算法两个计算无向完全图的最小生成树的长途不一样啊。。。不知道对不对。。。求指点

Viewing all articles
Browse latest Browse all 9556

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>