(c++)数据结构与算法之图:邻接矩阵、深度广度遍历、构造最小生成树(prim、kruskal算法)

来源:互联网 发布:软件开发基础知识 编辑:程序博客网 时间:2024/06/05 12:01
//图的邻接矩阵实现//广度遍历bfs和深度遍历dfs//构造最小生成树的prim、kruskal算法#include <iostream>#include<stack>#include<queue>#define WEIGHTMAX  100#define VERTEXMAX 50#define VISITED 1#define UNVISITED 0using namespace std;class ufset             //等价类{private:    int n;                      //个数    int *root,*next,*length;    //等价类代表元、下一个元素、该元素所在等价类的元素个数public:    friend class graph;    ufset(int s)                //初始时均各自为等价类    {        root=new int[s];        next=new int[s];        length=new int[s];        n=s;        for(int i=0;i<s;i++)        {            root[i]=next[i]=i;            length[i]=1;        }    }    ~ufset()    {        delete [] root;        delete [] next;        delete [] length;    }    void show()                 //输出    {        cout<<"root:"<<endl;        for(int i=0;i<n;i++)        {            cout<<root[i]<<" ";        }        cout<<endl;        cout<<"next:"<<endl;        for(int i=0;i<n;i++)        {            cout<<next[i]<<" ";        }        cout<<endl;        cout<<"length:"<<endl;        for(int i=0;i<n;i++)        {            cout<<length[i]<<" ";        }        cout<<endl;    }    void Union(int u,int v)         //两个等价类的合并    {        if(length[root[u]]<length[root[v]])        {            int temp=u;            u=v;            v=temp;        }        if(root[u]==root[v])    return;        int p=next[root[u]];        //next        next[root[u]]=next[root[v]];        next[root[v]]=p;        length[root[v]]=1;                //length        length[root[u]]++;        int oldroot=root[v];        //root        for(int i=0;i<n;i++)            if(root[i]==oldroot)                root[i]=root[u];    }    bool unionOK(int u,int v)   //两个元素是否在同一个等价类中    {        if(root[v]==root[u])            return true;        else            return false;    }};class edge              //边类(数据公开){public:    int start,end;    int weight;    friend class graph;    edge(){};    edge(int w)    {        weight=w;    }    edge(int s,int e,int w)    {        start=s;        end=e;        weight=w;    }};void visit(int v){    cout<<v<<"-->";}class graph{private:    int **matrix;           //邻接矩阵    int v_num,e_num;        //结点数、边数    int *mark;              //用于判断是否被访问的数组(0:未访问  1:已访问 )public:    graph(){};    graph(int v)    {        if(v>=VERTEXMAX)    cout<<"construct false"<<endl;        v_num=v;        e_num=0;        mark=new int[v_num];        for(int i=0;i<v_num;i++)            mark[i]=0;        matrix=new int*[v_num];        int i,j;        for(i=0;i<v_num;i++)            matrix[i]=new int[v_num];        for(i=0;i<v_num;i++)            for(j=0;j<v_num;j++)                matrix[i][j]=0;    }    ~graph()    {        delete mark;        for(int i=0;i<v_num;i++)    delete [] matrix[i];        delete [] matrix;    }    void resetMark()                    //重置节点标记数组    {        for(int i=0;i<v_num;i++)            mark[i]=0;    }    bool isEdge(edge onee)              //判断是否为边    {        if(matrix[onee.start][onee.end]>0&&           matrix[onee.start][onee.end]<WEIGHTMAX&&           matrix[onee.end][onee.start]>0&&           matrix[onee.end][onee.start]<WEIGHTMAX)            return true;        else        return false;    }    void setEdge(int start,int end,int weight)      //给图添加一条边    {        if(matrix[start][end]==0&&matrix[end][start]==0)        {            e_num++;        }        matrix[start][end]=weight;        matrix[end][start]=weight;    }    void delEdge(int start,int end)                 //删除图中一条边    {        if(matrix[start][end]!=0&&matrix[end][start]!=0)            e_num--;        else    return;        matrix[start][end]=0;        matrix[end][start]=0;    }    void showEdge()                     //展示邻接矩阵    {        cout<<"邻接矩阵如下: "<<endl;        for(int i=0;i<v_num;i++)            for(int j=0;j<v_num;j++)            {                cout<<matrix[i][j]<<" ";                if(j==v_num-1)      cout<<endl;            }    }    edge firstEdge(int v)               //返回该结点按顺序的第一条边    {        edge e(v,v,0);        for(int i=0;i<v_num;i++)        {            if(matrix[v][i]!=0)            {                e.end=i;                e.weight=matrix[v][i];                return e;            }        }        cout<<"this vertex dont have edge"<<endl;        return e;    }    edge nextEdge(int v,edge onee)      //返回该边的下一条边(同头结点)    {        for(int i=onee.end+1;i<v_num;i++)        {            if(matrix[v][i]!=0)            {                edge e(v,i,matrix[v][i]);                return e;            }        }        cout<<"no next edge"<<endl;        return onee;    }    void dfs_traverse(graph g,int fir)  //递归深度遍历    {        mark[fir]=1;        cout<<fir<<"-->";        for(int i=0;i<v_num;i++)        {            if(g.matrix[fir][i]>=1&&!mark[i])                dfs_traverse(g,i);        }    }    void dfs_notraverse()               //非递归深度遍历(用栈实现)    {        resetMark();        stack<int> s;        for(int i=0;i<v_num;i++)        {            if(mark[i]==0)            {                s.push(i);                while(!s.empty())                {                    int pc=s.top();                    s.pop();                    if(mark[pc]==0)                        visit(pc);                    mark[pc]=1;                    for(int j=v_num-1;j>0;j--)                    //for(int j=0;j<v_num;j++)              //???   为何顺序颠倒???                    {                        if(matrix[pc][j]>0&&matrix[pc][j]<WEIGHTMAX)                        if(mark[j]==0)                            s.push(j);                    }                }            }        }    }    void bfs()                          //广度遍历(用队列实现)    {        resetMark();        queue<int> q;        for(int i=0;i<v_num;i++)        {            if(mark[i]==0)            {                q.push(i);                while(!q.empty())                {                    int pc=q.front();                    q.pop();                    if(mark[pc]==0)                        visit(pc);                    mark[pc]=1;                    for(int j=0;j<v_num;j++)                    //for(int j=v_num;j>=0;j--)                 //?????                    {                        if(matrix[pc][j]>0&&matrix[pc][j]<WEIGHTMAX)                            if(mark[j]==0)                                q.push(j);                    }                }            }        }    }    void prim()                         //prim    {        resetMark();        int x=0,y=0;                            //下标        edge *e=new edge[v_num-1];              //构建的最小生成树的边组成的数组        int *ver=new int[v_num];                //结点的数组,用于统计哪些结点已被构建,当数组满时说明构建完成        {//初始化markedge            for(int i=0;i<v_num;i++)                ver[i]=-1;        }        ver[0]=0;                               //放入首个结点        mark[0]=1;        y++;        while(y<v_num)                          //如果结点没有全部访问完则循环        {            int minWeight=WEIGHTMAX,sta,en;            for(int i=0;ver[i]!=-1;i++)         //遍历寻找权重最小的边            {                for(int j=0;j<v_num;j++)                {                    //如果边满足:权重最小、边的尾结点未被访问,则加入边的尾结点                    if(matrix[ver[i]][j]!=0&&minWeight>matrix[ver[i]][j]                       &&mark[j]==0)                    {                        minWeight=matrix[ver[i]][j];                        sta=ver[i];                        en=j;                    }                }            }            edge temp(sta,en,minWeight);            e[x++]=temp;            ver[y++]=en;            mark[en]=1;        }        {//展示结果:            cout<<"插入边顺序: "<<endl;            for(int i=0;i<v_num-1;i++)                cout<<e[i].start<<"---"<<e[i].weight<<"--->"<<e[i].end<<endl;            cout<<"插入结点顺序: ";            for(int i=0;i<v_num;i++)                cout<<ver[i]<<"  ";            cout<<endl;        }        delete [] ver;        delete [] e;    }    void kruskal()                      //kruskal    {        int n=v_num,union_num=0;        queue<edge> q;        ufset ufs(n);        {//遍历使所有边按权重从小到大的顺序排成数组,进队            edge eq[e_num];            int x=0;            int **edgew=new int*[n];            edgew=matrix;            while(x<+e_num)            {                for(int i=0;i<n;i++)                {                    for(int j=0;j<n;j++)                    {                        if(edgew[i][j]!=0)                        {                            edge e(i,j,edgew[i][j]);                            eq[x++]=e;                            edgew[i][j]=edgew[j][i]=0;                        }                    }                }            }            for(int i=0;i<e_num;i++)            {                int minweight=eq[i].weight;                for(int j=0;j<e_num;j++)                    {                        if(eq[j].weight>minweight)                        {                            minweight=eq[j].weight;                            edge temp;                            temp=eq[j];                            eq[j]=eq[i];                            eq[i]=temp;                        }                    }            }            for(int i=0;i<e_num;i++)                q.push(eq[i]);            delete edgew;        }        cout<<"边插入顺序:"<<endl;        while(!q.empty())        {            edge e=q.front();            q.pop();            if(!ufs.unionOK(e.start,e.end))            {                cout<<e.start<<"---"<<e.weight<<"--->"<<e.end<<endl;                ufs.Union(e.start,e.end);            }        }        cout<<"结点插入顺序:";        for(int i=0;i<n;i++)        {            cout<<ufs.next[i]<<"  ";        }        cout<<endl;    }};int main(){    graph a(8);    {//set edge(初始化图)        a.setEdge(0,1,1);        a.setEdge(0,2,2);        a.setEdge(1,3,3);        a.setEdge(1,4,5);        a.setEdge(3,7,4);        a.setEdge(4,7,4);        a.setEdge(2,6,1);        a.setEdge(2,5,3);        a.setEdge(5,6,2);    }    cout<<"带权无向图:(P160 4-12)"<<endl;    a.showEdge();    cout<<" node1 first edge's weight: "<<a.firstEdge(1).weight<<endl;    cout<<"node2 first edge's next edge's weight: "<<a.nextEdge(2,a.firstEdge(2)).weight<<endl;    cout<<"递归深度遍历:   ";    a.dfs_traverse(a,0);    cout<<endl;    cout<<"非递归深度遍历:  ";    a.dfs_notraverse();    cout<<endl;    cout<<"    广度遍历:  ";    a.bfs();    cout<<endl;    cout<<"prim:"<<endl;    a.prim();    cout<<"kruskal:"<<endl;    a.kruskal();    cout << "Hello world!" << endl;    return 0;}
第一次写,写的比较复杂,将就看吧。
阅读全文
0 0
原创粉丝点击