图的各种算法

这篇博客主要探讨了图的各种算法,适合找工作时进行算法复习。内容涵盖图的基本概念、路径搜索和图的结构操作等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

找工作时当练习写的,仅供参考。

头文件:

 
#ifndef GRAPH_H_INCLUDED
#define GRAPH_H_INCLUDED
#define Max 10000
//adjacent matrix
class MGraph{
    private:
        int TotVer;
        vector<int> Vertics;
        vector<vector<int> > Edge;
    public:
        MGraph(){ }
        MGraph(int t):TotVer(t){
            //read vertics
            cout<<"read vertics"<<endl;
            int v;
            for(int i=0;i<t;++i){
                cin>>v;
                Vertics.push_back(v);
            }
            //read edges
            cout<<"read edges"<<endl;
            Edge.resize(t);
            for(int i=0;i<t;++i)
                Edge[i].resize(t,0);
            for(int i=0;i<t;++i)
                for(int j=0;j<t;++j)
                    if(i!=j) Edge[i][j]=Max;
            int i,j,cur;
            while(cin>>i>>j>>cur){
                if(i==-1&&j==-1&&cur==-1) break;
                if(i!=j) Edge[i][j]=Edge[j][i]=cur;
            }
        }


        int GetTotVec(){
            return TotVer;
        }
        vector<int>& GetVertics(){
            return Vertics;
        }
        vector<vector<int> >& GetEdge(){
            return Edge;
        }


         void Dijkstra(int);
         void Floyd();
};
//adjacent table
struct Edge{
    int dest;
    int cost;
    Edge* next;
    Edge(int d,int c):dest(d),cost(c),next(NULL){ }
};
struct Vertex{
    int data;
    Edge* adj;
    Vertex():data(0),adj(NULL){ }
};
struct MSTNode{
    int tail,head;
    int cost;
};
class AGraph{
    private:
        int TotVer;
        int TotEdge;
        vector<Vertex> NodeTable;
    public:
        AGraph(){ }
        AGraph(int t,int e):TotVer(t),TotEdge(e){
            int d;
            int tail,head,cost;
            Edge* cure;
            //read vertics
            cout<<"read vertics"<<endl;
            NodeTable.resize(t);
            for(int i=0;i<t;++i){
                cin>>d;
                NodeTable[i].data=d;
            }
            //read edges
            cout<<"read edges"<<endl;
            for(int i=0;i<e;++i){
                cin>>tail>>head>>cost;
                int k=0;
                while(k!=tail) ++k;
                cure=NodeTable[k].adj;
                if(cure==NULL) NodeTable[k].adj=new Edge(head,cost);
                else{
                    while(cure->next!=NULL) cure=cure->next;
                    cure->next=new Edge(head,cost);
                }


                /*k=0;
                while(k!=head) ++k;
                cure=NodeTable[k].adj;
                if(cure==NULL) NodeTable[k].adj=new Edge(tail,cost);
                else{
                    while(cure->next!=NULL) cure=cure->next;
                    cure->next=new Edge(tail,cost);
                }*/
            }
        }
        ~AGraph(){
            Edge *p;
            for(int i=0;i<TotVer;++i){
                p=NodeTable[i].adj;
                while(p!=NULL){
                    NodeTable[i].adj=p->next;
                    delete p;
                    p=NodeTable[i].adj;
                }
            }
        }


        vector<Vertex>& GetNode(){
            return NodeTable;
        }


        void DFS(int v,vector<int>& flag);
        void DFS();


        void BFS(int v,vector<int>& flag);
        void BFS();


        void Kruskal();
        int find_set(vector<vector<int> >& v,int k);
        int union_set(vector<vector<int> >&v,int i,int j);


        void Prim();


        vector<int> TopologicalSort();


        void CriticalPath();
};//end

#endif // GRAPH_H_INCLUDED

各种图算法:

#include <iostream>
#include <vector>
#include <deque>
#include <iterator>
#include <cstdlib>
using namespace std;
#include <graph.h>

//dfs
void AGraph::DFS(int v,vector<int>& flag){
    cout<<NodeTable[v].data<<endl;
    flag[v]=1;
    int w;


    Edge* p=NodeTable[v].adj;
    while(p!=NULL){
        w=p->dest;
        if(!flag[w]) DFS(w,flag);
        p=p->next;
    }
}
void AGraph::DFS(){
    vector<int> flag(TotVer,0);
    for(int i=0;i<TotVer;++i)
        if(!flag[i]) DFS(i,flag);
}
//bfs
void AGraph::BFS(int v,vector<int>& flag){
    deque<int> d;
    int w;
    Edge* p;

    cout<<NodeTable[v].data<<endl;
    flag[v]=1;
    d.push_back(v);
    while(!d.empty()){
        v=d.front();
        d.pop_front();
        p=NodeTable[v].adj;
        while(p!=NULL){
            w=p->dest;
            if(!flag[w]){
                cout<<NodeTable[w].data<<endl;
                flag[w]=1;
                d.push_back(w);
            }
            p=p->next;
        }
    }
}//end bfs
void AGraph::BFS(){
    vector<int> flag(TotVer,0);
    for(int i=0;i<TotVer;++i)
        if(!flag[i]) BFS(i,flag);
}
//kruskal
int AGraph::find_set(vector<vector<int> >& v,int k){ //寻找点所在连通分量
    for(int i=0;i<v.size();++i)
        if(v[i][k]) return i;
}
int AGraph::union_set(vector<vector<int> >&v,int i,int j){ //合并连通分量
    for(int k=0;k<TotVer;++k)
        if(v[i][k]||v[j][k]) v[i][k]=1;
    v.erase(v.begin()+j);
}


void AGraph::Kruskal(){
    vector<vector<int> > ver(TotVer,vector<int>(TotVer,0));//存放连通分量
    vector<MSTNode> vedge;//存放各边
    vector<MSTNode> mst;//存放最小生成树
    vector<int> flag(TotVer,0);
    Edge* p;
    MSTNode tmp;


    for(int i=0;i<TotVer;++i)
        ver[i][i]=1;


    for(int i=0;i<TotVer;++i){
        if(!flag[i]) flag[i]=1;
        p=NodeTable[i].adj;
        while(p!=NULL){
            tmp.tail=i;
            tmp.head=p->dest;
            tmp.cost=p->cost;
            if(!flag[tmp.head]) vedge.push_back(tmp);
            p=p->next;
        }
    }
    //sort vedge
    for(int i=1;i<vedge.size();++i){
        MSTNode tmpnode=vedge[i];
        int tmp=vedge[i].cost;
        int Left=0,Right=i-1;
        while(Left<=Right){
            int mid=(Left+Right)/2;
            if(tmp<vedge[mid].cost) Right=mid-1;
            else Left=mid+1;
        }
        for(int j=i-1;j>=Left;--j)
            vedge[j+1]=vedge[j];
        vedge[Left]=tmpnode;
    }
    for(int i=0;i<TotEdge;++i){     //kruskal
        int v=find_set(ver,vedge[i].tail);
        int w=find_set(ver,vedge[i].head);
        if(v!=w){
            mst.push_back(vedge[i]);
            union_set(ver,v,w);
        }
    }
    for(int i=0;i<mst.size();++i)
        cout<<mst[i].tail<<" "<<mst[i].head<<" "<<mst[i].cost<<endl;
}
//prim


void AGraph::Prim(){
    vector<int> minTree;//最小树的节点
    vector<MSTNode> mst;
    vector<int> flag(TotVer,0);//进树标志
    MSTNode mnode;


    minTree.push_back(0);//某个节点进树,在这里选择0节点
    flag[0]=1;
    for(int i=1;i<TotVer;++i){//建树
        int msttail=-1;
        int msthead=-1;
        int tmp=Max;
        Edge* p;


        for(int j=0;j<minTree.size();++j){ //寻找树内节点到树外各个节点的有最短距离的边
            int tail=minTree[j];
            int head;
            p=NodeTable[tail].adj;
            while(p!=NULL){
                head=p->dest;
                if(!flag[head]&&p->cost<tmp){
                    tmp=p->cost;
                    msthead=head;
                    msttail=tail;
                }
                p=p->next;
            }
        }


        minTree.push_back(msthead);
        flag[msthead]=1;
        mnode.tail=msttail;
        mnode.head=msthead;
        mnode.cost=tmp;
        mst.push_back(mnode);//加入最小生成树
    }
    for(int i=0;i<mst.size();++i)
        cout<<mst[i].tail<<" "<<mst[i].head<<" "<<mst[i].cost<<endl;
}//end prim


//dijkstra
void MGraph::Dijkstra(int v){
    vector<int> dist(TotVer);//当前状态下v距离未进入的节点的最短距离
    vector<int> path(TotVer,-1);//当前最短路径状态下各个节点的前驱节点
    vector<int> flag(TotVer,0);//节点进入标志


    flag[v]=1;
    for(int i=0;i<TotVer;++i){
        dist[i]=Edge[v][i];
        if(i!=v&&dist[i]<Max) path[i]=v;
    }
    for(int i=0;i<TotVer-1;++i){
        int min=Max;
        int u;


        for(int j=0;j<TotVer;++j)//寻找下一个节点
            if(!flag[j]&&dist[j]<min){
                u=j;
                min=dist[j];
            }


        flag[u]=1;
        for(int j=0;j<TotVer;++j)//更新dist和path
            if(!flag[j]&&dist[u]+Edge[u][j]<dist[j]){
                dist[j]=dist[u]+Edge[u][j];
                path[j]=u;
            }
    }
    for(int i=0;i<TotVer;++i){
        int w=i;
        cout<<w;
        while(path[w]!=-1){
            cout<<"<--"<<path[w];
            w=path[w];
        }
        cout<<endl;


    }
}


//floyd
void MGraph::Floyd(){
    vector<vector<int> > dist(TotVer,vector<int>(TotVer));
    vector<vector<int> > path(TotVer,vector<int>(TotVer,-1));


    for(int i=0;i<TotVer;++i)
        for(int j=0;j<TotVer;++j){
            dist[i][j]=Edge[i][j];
            if(i!=j&&dist[i][j]<Max) path[i][j]=i;
        }


    for(int k=0;k<TotVer;++k)
        for(int i=0;i<TotVer;++i)
            for(int j=0;j<TotVer;++j)
                if(dist[i][k]+dist[k][j]<dist[i][j]){
                    dist[i][j]=dist[i][k]+dist[k][j];
                    path[i][j]=path[k][j];
                }


    for(int i=0;i<TotVer;++i){
        cout<<i<<":"<<endl;
        for(int j=0;j<TotVer;++j){
            int k=j;
            cout<<"<"<<i<<","<<j<<">:";
            cout<<j;
            k=path[i][j];
            while(k!=-1){
                cout<<"<--"<<k;
                k=path[i][k];
            }
            cout<<endl;
        }
        cout<<"-------------------"<<endl;
    }
}//end floyd


//TopologicalSort
vector<int> AGraph::TopologicalSort(){
    vector<int> count(TotVer,0);
    vector<int> verset;
    int top=-1;


    for(int i=0;i<TotVer;++i){//Initialize the count
        Edge* p=NodeTable[i].adj;
        while(p){
            ++count[p->dest];
            p=p->next;
        }
    }
    for(int i=0;i<TotVer;++i)//initialze the stack
        if(count[i]==0){
            count[i]=top;
            top=i;
        }
    for(int i=0;i<TotVer;++i){  //sort
        if(top==-1){
            cout<<"has a cycle"<<endl;
            exit(0);
        }
        else{
            int j=top;
            top=count[top];
            verset.push_back(j);
            Edge* p=NodeTable[j].adj;
            while(p){
                if(--count[p->dest]==0){
                    count[p->dest]=top;
                    top=p->dest;
                }
                p=p->next;
            }
        }


    }
    return verset;
}//end tsort


//critical path
void AGraph::CriticalPath(){
    vector<int> tsort;
    vector<int> ve(TotVer,0);
    vector<int> vl(TotVer,0);
    Edge* p=NULL;
     int k,e,l;


    tsort=TopologicalSort();
    for(int i=0;i<TotVer;++i){
        int t=tsort[i];
        p=NodeTable[t].adj;
        while(p){
            k=p->dest;
            if(ve[t]+p->cost>ve[k]) ve[k]=ve[t]+p->cost;
            p=p->next;
        }
    }


    for(int i=0;i<TotVer;++i) vl[i]=ve[TotVer-1];
    for(int i=TotVer-2;i>=0;--i){
        int t=tsort[i];
        p=NodeTable[t].adj;
        while(p){
            k=p->dest;
            if(vl[k]-p->cost<vl[t]) vl[t]=vl[k]-p->cost;
            p=p->next;
        }
    }


    for(int i=0;i<TotVer;++i){ //critical path
        p=NodeTable[i].adj;
        while(p){
            k=p->dest;
            e=ve[i];
            l=vl[k]-p->cost;
            if(l==e) cout<<"<"<<i<<","<<k<<">"<<"is critical path"<<endl;
            p=p->next;
        }
    }
}//critical path






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值