zoukankan      html  css  js  c++  java
  • 邻接表

    // crikal.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "iostream"
    #include "vector"
    #include "stack"
    #include <fstream> 
    using namespace std;
    
    
    #define  MaxNumVertex  20 //最大顶点数
    #define  MaxNumEdge 40  //最大边数
    #define  infinity 65535//无穷大
    typedef int elementtype;       //elementtype 为int 型
    
    //结点类型
    struct ArcNode
    {
        elementtype data;//顶点信息
        int weight ; //权重
        ArcNode *nextarc ;//指向下一条弧
    };
    
    //表头
    struct VNode
    {
        elementtype data;//顶点信息
        ArcNode *firstarc;//指向第一条弧
    };
    typedef struct VNode AdjList[MaxNumVertex];
        
    
    class graph{
    public:
        graph();
        ~graph();
        elementtype insertvertex(elementtype v); //在图中增加一个顶点
        elementtype insertedge(elementtype v,elementtype u,elementtype weight);//在图中增加一条从v顶点到u顶点的弧
        elementtype firstadj(elementtype v);//求图g中顶点v的第一个邻接点
        elementtype nextadj(elementtype v,elementtype m);//求图中顶点v的m邻接点之后的邻接点
        elementtype firstpre(elementtype v);//求图中顶点v的第一个前驱
        elementtype nextpre(elementtype v,elementtype m);//求图中顶点v的m前驱点之后的前驱点
        elementtype degreein(elementtype v);//求图中顶点v的入度数
        elementtype FindDegreein(elementtype ind[]);//各顶点的入度存放于入度数组中
        elementtype degreeout(elementtype v);//求图中顶点v的入度数
        elementtype FindDegreeout(elementtype oud[]);//各顶点的入度存放于入度数组中
        elementtype EW(elementtype E[]);//最早发生时间的求解
        bool CriticalPath();//关键路径
        elementtype create();//创建图
        int  CurrentVertex;//当前顶点数
        void show();
        elementtype Getedge(elementtype v,elementtype u);//在图中获得v顶点到u顶点的权重
    
    private:
        AdjList vertices;
        elementtype vertex[MaxNumVertex];//顶点表
        elementtype edge[MaxNumVertex][MaxNumVertex];//图中弧的类型
        
    };
    
    /*
    *初始化
    */
    graph::graph()
    {
        CurrentVertex = 0; 
    }
    
    /*
    *在图中增加一个顶点
    */
    elementtype graph::insertvertex(elementtype v)
    {
        //判断这个顶点是否已经存在
        int i;
        bool flags = true;
        for(i=0;i<CurrentVertex;i++)
        {
            if(vertices[i].data==v)
            {
                flags = false ;
                break;
            }
        }
        if(flags)
        {
            vertices[CurrentVertex].data = v ;
            vertices[CurrentVertex].firstarc= NULL;
            CurrentVertex++;
        }else  cout<<v<<"顶点已经存在!"<<endl;
        return 0;
    }
    
    /*
    *在图中增加一条从v顶点到u顶点的弧
    */
    elementtype graph::insertedge(elementtype v,elementtype u,elementtype weight)
    {
        int i ;
        ArcNode *s = new ArcNode;
        s->data = u;
        s->weight = weight;
        for( i = 0 ; i < CurrentVertex ; i ++ )
        {
            if(vertices[i].data==v)//找到顶点v对应的表头
            {
                ArcNode *p = new ArcNode;
                ArcNode *q = new ArcNode;
                p = vertices[i].firstarc ;
                bool flags = true;
                if(p==NULL)
                {
                    //cout<<"Yes
    ";
                    s->nextarc = p;
                    vertices[i].firstarc = s ;
                    //    cout<<vertices[i].data<<","<<vertices[i].firstarc->data<<","<<vertices[i].firstarc->weight<<endl;
                }else
                {
                    while(p!=NULL)
                    {
                        if(p->data!=u)
                        {
                            q = p;
                            p = p->nextarc;
                        }else{
                            flags = false;
                            break;
                        }
                    }
                    if(flags)
                    {
                        s->nextarc = q->nextarc;
                        q->nextarc = s;
                   }else cout<<v<<"->"<<u<<"这条弧弧已经存在!"<<endl;
                }
            }
        }
        return 0;
    }
    
    
    /*
    *求图中顶点v的第一个邻接点
    */
    elementtype graph::firstadj(elementtype v)
    {
        int i;
        elementtype u = 0;
        for(i=0;i<CurrentVertex;i++)
        {
            if(vertices[i].data==v)//找到顶点v对应的表头
            {
                ArcNode *p = new ArcNode;
                p = vertices[i].firstarc ;
                if(p)
                {
                    u = p->data;
                }else
                {
                    break;
                }
            }
        }
        return u;
    }
    
    /*
    *求图中顶点v的m邻接点以后的邻接点
    */
    elementtype graph::nextadj(elementtype v,elementtype m)
    {
        int i;
        elementtype u = 0;
        for(i=0;i<CurrentVertex;i++)
        {
            if(vertices[i].data==v)//找到顶点v对应的表头
            {
                ArcNode *p = new ArcNode;
                p = vertices[i].firstarc ;
                while(p)
                {
                    if(p->data!=m)
                    {
                        p = p ->nextarc ;
                    }else break;
                }
                if(p&&p->data==m&&p->nextarc) u = p->nextarc->data ;
                break;
            }
        }
        return u;
    }
    
    /*
    *求图中顶点v的第一个前驱
    */
    elementtype graph::firstpre(elementtype v)
    {
        int i;
        elementtype u = 0;
        bool flags = false;
        for(i=0;i<CurrentVertex;i++)
        {    
            ArcNode *p = new ArcNode;
            p = vertices[i].firstarc ;
            while(p)
            {
                //cout<<p->data;
                if(p->data==v)
                {
                    u = vertices[i].data;
                    flags = true;
                    break;
                }
                p = p ->nextarc;
            }
            if(flags)break;
    
        }
        return u;
    }
    
    /*
    *求图中顶点v的m前驱点之后的前驱点
    */
    elementtype graph::nextpre(elementtype v,elementtype m)
    {
        int i,j;
        elementtype u = 0;
        bool flags = false;
        for(i=0;i<CurrentVertex;i++)
        {    
            if(vertices[i].data==m)
            {
                ArcNode *p = new ArcNode;
                for(j=i+1;j<CurrentVertex;j++)
                {
                    p = vertices[j].firstarc ;
                    while(p)
                    {
                        if(p->data==v)
                        {
                            u = vertices[j].data;
                            flags = true;
                            break;
                        }
                        p = p ->nextarc;
                    }
                    if(flags)break;
                }
                break;
            }
    
        }
        return u;
    }
    /*
    *求图中顶点v的入度数
    */
    elementtype graph::degreein(elementtype v)
    {
        int i,num = 0;
        for(i=0;i<CurrentVertex;i++)
        {    
            ArcNode *p = new ArcNode;
            p = vertices[i].firstarc ;
            while(p)
            {
                if(p->data==v)
                {
                    num++;
                    break;
                }
                p = p ->nextarc;
            }
        }
        return num;
    }
    
    /*
    *每个顶点的入度
    */
    elementtype graph::FindDegreein(elementtype ind[])
    {
        int i;
        for(i=0;i<CurrentVertex;i++)
        {
            ind[vertices[i].data] = degreein(vertices[i].data);
        }
        return 0;
    }
    
    /*
    *求图中顶点v的出度数
    */
    elementtype graph::degreeout(elementtype v)
    {
       int i,num = 0;
        for(i=0;i<CurrentVertex;i++)
        {    
            if(vertices[i].data==v)
            {
                ArcNode *p = new ArcNode;
                p = vertices[i].firstarc ;
                while(p)
                {
                    num++;
                    p = p ->nextarc;
                }
            break;
            }
        }
        return num;
    }
    
    /*
    *每个顶点的出度
    */
    elementtype graph::FindDegreeout(elementtype outd[])
    {
        int i;
        for(i=0;i<CurrentVertex;i++)
        {
            outd[vertices[i].data] = degreeout(vertices[i].data);
        }
        return 0;
    }
    
    /*
    *在图中获得v顶点到u顶点的权重
    */
    elementtype graph::Getedge(elementtype v,elementtype u)
    {
        int i;
        int weight = 0;
        for(i=0;i<CurrentVertex;i++)
        {
            if(vertices[i].data==v)
            {
                ArcNode *p = new ArcNode;
                p = vertices[i].firstarc ;
                while(p)
                {
                    if(p->data==u)
                    {
                        weight =p->weight;
                        break;
                    }
                    p = p ->nextarc;
                }
                break;
            }
        }
        return weight;
    }
    void graph::show()
    {
        int i;
        elementtype m;
        cout<<"test"<<endl;
        for( i = 0 ; i < CurrentVertex ; i ++ )
        {
            ArcNode *p = new ArcNode;
            p = vertices[i].firstarc ;
            cout<<"表头:"<<vertices[i].data<<endl;
            while(p!=NULL)
            {
                cout<<p->data<<","<<p->weight<<endl;    
                p = p->nextarc;    
                    
            }    
        }
        cout<<"第一个邻接点:"<<endl;
        for( i = 0 ; i < CurrentVertex ; i ++ )cout<<vertices[i].data<<","<<firstadj(vertices[i].data)<<endl;
        cout<<endl;
        cout<<"第2个邻接点:"<<endl;
        for( i = 0 ; i < CurrentVertex ; i ++ )
        {
                cout<<vertices[i].data<<":";
                m = firstadj(vertices[i].data) ;
                while(m)
                {
        
                    m = nextadj(vertices[i].data,m);
                    cout<<m<<",";
                }
                cout<<endl;
        }
        cout<<endl;
        
        for( i = 0 ; i < CurrentVertex ; i ++ )cout<<"第一个前驱点:"<<vertices[i].data<<","<<firstpre(vertices[i].data)<<endl;
        //cout<<"第一个前驱点:"<<vertices[CurrentVertex-1].data<<endl;
        //cout<<firstpre(vertices[CurrentVertex-1].data)<<endl;
    
    
        for( i = 0 ; i < CurrentVertex ; i ++ )
        {
                
               cout<<"第2个前驱:"<<vertices[i].data<<":";
                m = firstpre(vertices[i].data) ;
                while(m)
                {
        
                    m = nextpre(vertices[i].data,m);
                    cout<<m<<",";
                }
                cout<<endl;
        }
        
        cout<<endl;
    
        for( i = 0 ; i < CurrentVertex ; i ++ )cout<<"入度数目:"<<vertices[i].data<<","<<degreein(vertices[i].data)<<endl;
         elementtype ind[MaxNumVertex];//求各顶点的入度存放于入度数组ind中
        FindDegreein(ind);//
        for( i = 0 ; i < CurrentVertex ; i ++ )cout<<"入度数目:"<<ind[vertices[i].data]<<endl;
        for( i = 0 ; i < CurrentVertex ; i ++ )cout<<"出度数目:"<<vertices[i].data<<","<<degreeout(vertices[i].data)<<endl;
        elementtype outd[MaxNumVertex];//求各顶点的出度存放于出度数组outd中
    
        FindDegreeout(outd);//求各个结点的出度
        for( i = 0 ; i < CurrentVertex ; i ++ )cout<<"出度数目:"<<vertices[i].data<<","<<outd[vertices[i].data]<<endl;
    
        cout<<Getedge(vertices[CurrentVertex-2].data,vertices[CurrentVertex-1].data)<<endl;
    }
    
    /*
    *最早发生时间的求解
    */
    elementtype graph::EW(elementtype E[])
    {
        int i;
        stack<elementtype> s;//定义并初始索要用到的栈
        elementtype x,w,ind[MaxNumVertex];//求各顶点的入度存放于入度数组ind中
        FindDegreein(ind);
    
        for(i=0;i<CurrentVertex;i++)//各个结点最早发生时间的初始化
        {
            E[vertices[i].data] = -1;
        }
        for(i=0;i<CurrentVertex;i++)//将入度为0的顶点入栈
        {
            if(degreein(vertices[i].data)==0)
            {
                s.push(vertices[i].data);
                E[vertices[i].data] = 0;//第一个入度为0的结点的最早发生时间为0
            }
        }
        int count =0;//用于统计已经完成的结点数目
        while(!s.empty())
        {
            x = s.top();
            count++;//计数
            s.pop();
            w = firstadj(x);//开始对v的各个后继顶点的入度-1
            while(w!=0)
            {
                if(E[w]<(E[x]+Getedge(x,w)))
                {
                    E[w] = E[x]+Getedge(x,w);//更新w的最早发生时间
                }
                if(!(--ind[w]))//若w的入度-1后为0,则入栈
                {
                    s.push(w);
                }
                w = nextadj(x,w);
            }
        }
    
        
        for(i=0;i<CurrentVertex;i++)//各个结点最早发生时间的初始化
        {
            cout<<E[vertices[i].data]<<endl;
        }
    
        if(count<CurrentVertex)return false;//产生有回路的标志
        else return true;
        return 0;
    }
    
    /*
    *关键路径
    */
    bool graph::CriticalPath()
    {
        int i;
        stack<int> s;//定义并初始索要用到的栈
        elementtype x,w,ind[MaxNumVertex];//求各顶点的入度存放于入度数组ind中
        elementtype outd[MaxNumVertex];//求各顶点的出度存放于出度数组outd中
        elementtype E[MaxNumVertex];
        elementtype L[MaxNumVertex];
        FindDegreein(ind);//求各个结点的入度
        FindDegreeout(outd);//求各个结点的出度
        EW(E);//求各个结点的最早发生时间
        
        for(i=0;i<CurrentVertex;i++)
        {
            L[vertices[i].data] = infinity;//各个结点最迟发生时间的初始化
        }
        for(i=0;i<CurrentVertex;i++)//将出度为0的顶点入栈
        {
            if(degreeout(vertices[i].data)==0)
            {
                s.push(vertices[i].data);
                L[vertices[i].data] = E[vertices[i].data];//第一个出度为0的结点的最迟发生时间
            }
        }
        int count =0;//用于统计已经完成的结点数目
        while(!s.empty())
        {
            x = s.top();
            count++;//计数
            s.pop();
            w = firstpre(x);//开始对v的各个前驱顶点的出度-1
            while(w!=0)
            {
                if(L[w]>(L[x]-Getedge(w,x)))
                {
                    L[w] = L[x]-Getedge(w,x);//更新w结点的最迟发生时间
                }
        
                if(!(--outd[w]))//若w的出度-1后为0,则入栈
                {
                    s.push(w);
                }
                w = nextpre(x,w);
            }
    
        }
    
        cout<<"E[i],L[i]:"<<endl;
        for(i=0;i<CurrentVertex;i++)//输出各个节点的最早发生时间和最迟发生时间
        {
            cout<<"E["<<i<<"]="<<E[vertices[i].data]<<",L["<<i<<"]="<<L[vertices[i].data]<<endl;
        }
    
        vector<elementtype>equal;//记录E[I]=L[I]
        for(i=0;i<CurrentVertex;i++)
        {
            if(E[vertices[i].data]==L[vertices[i].data])
            {
                equal.push_back(vertices[i].data);
            }
        }
    
        elementtype start,end;
        for(i=0;i<CurrentVertex;i++)//寻找起始结点
        {
            if(degreein(vertices[i].data)==0)
            {
                start = vertices[i].data;
                break;
            }
        }
        FindDegreeout(outd);//求各个结点的出度
        for(i=CurrentVertex-1;i>=0;i--)//寻找终止结点
        {
            if(degreeout(vertices[i].data)==0)
            {
                end = vertices[i].data;
                break;
            }
        }
    
        cout<<"CriticalPath is:";
        while(start!=end)
        {
            for(i=0;i<equal.size();i++)//输出关键路径
            {
                if(Getedge(start,equal[i])!=0)
                {
                    cout<<start<<"->";
                    start = equal[i];
                    if(start==end)
                    {
                        cout<<start<<endl;
                    }
                    break;
                }
            }
        }
        return 0;
    }
    
    /*
    *创建图
    */
    elementtype graph::create()
    {
        int i,VertextNum,ArcNum,v,u,weight;
        ifstream infile("file.txt",ios::in);
        if(!infile)
        {
            cerr<<"open error!"<<endl;
            exit(1);
        }
        infile>>VertextNum>>ArcNum;
        for( i = 0 ; i < VertextNum ; i ++ )
        {
            infile>>v;
            insertvertex(v);
        }
        for( i = 0 ; i < ArcNum ; i ++ )
        {
            infile>>v>>u>>weight;
            insertedge(v,u,weight);
        }
        infile.close();
        cout<<"graph create finish!"<<endl<<endl;
        return 0;
    }
    graph::~graph()
    {
    }
    
    int main()
    {
        graph g;
        g.create();
        g.show();
        g.CriticalPath();
        return 0;
    }
  • 相关阅读:
    jmeter_04_常用取样器
    jmeter_03_鉴权
    jmeter_02_目录文档说明
    jmeter_01_常用快捷键
    Web Api 与 Andriod 接口对接开发经验
    Eclipse自动生成作者、日期注释等功能设置
    c#解析XML到DATASET及dataset转为xml文件函数
    Jquery 仿 android Toast效果
    正在运行的android程序,按home键之后退回到桌面,在次点击程序图标避免再次重新启动程序解决办法
    异步网络加载开源框架AsyncHttpClient使用
  • 原文地址:https://www.cnblogs.com/minmsy/p/6692770.html
Copyright © 2011-2022 走看看