图论_拓扑排序_2020-5-31

AOV(Activity on Vertex network): 活动在顶点上的网

顶点:    表示活动

边:      表示活动的先后顺序

拓扑排序:

    有向无环图G,所有顶点排成一个线性序列

应用:

如下图要先要完成1 ,在2,3,->4,5 ->6

 

代码实现:上图的拓扑排序        

            有向无环图,邻接表存储 

拓扑排序:

/*@date:   2020-5-31@author:wbyAOV(Activity on Vertex network): 活动在顶点上的网顶点:表示活动边:表示活动的先后顺序拓扑排序:    有向无环图G,所有顶点排成一个线性序列    步骤:        1:从有向图中选择一个没有前驱(入度为0)的结点u输出        2:删除1中的输出的顶点u,并且删除u点出发的全部边        3:重复上述两步,直到图中不存在入度为0的顶点*/#include <iostream>#include<cstring>using namespace std ;#define MaxSize 50      //图最大顶点个数#define inf 999999999  //无穷大值,在图中表示不连通typedef  int  datatype; //可以根据需要改变数据类型,也可以自己封装数据类型//邻接表typedef struct ArcNode{    int adjvex;        //该边指向的顶点编号,(邻接点编号)    ArcNode *next ;    //指向下一条边的指针}ArcNode ;             //弧结点typedef struct{    int  num ;             // 顶点编号信息    int  inDegreeCount  ;  //顶点的入度    int  outDegreeCount ;  //顶点的出度统计    ArcNode *firstArc ;   // 指向第一条边的指针}VNode ;                  //结点typedef struct{  int n,e ;                 // n 图顶点的总数, e 边数  VNode adjList[MaxSize] ;  //各节点邻接表(一个节点一条链表,链表中元素为邻接边顶点adjvex,和边上info)}AGraph;/*  构造图的初始函数  */AGraph* InitiaL_Graph(){    AGraph *graph ;    int n ,e ;     // n ,这个图的顶点个数,e 变数    int i;    graph = new AGraph ;  //开辟一个图存储空间,不然有空指针异常    cout<<"初始化图操作:请输入你要构造的图的 顶点数(n) 和边数(e)"<<endl ;    cout<<"请输入总的顶点数:n \t";    cin>>n;    cout<<"请输入总的变数:e:  \t";    cin>>e;    graph->n = n ;    graph->e = e ;    cout<<"请输入各个顶点的邻接边:\tadjvex: 顶点编号 "<<endl ;    int inDegreeCount[n] ; //用一个数组统计所有顶点的入度信息    memset(inDegreeCount,0,sizeof(inDegreeCount)) ; //清0    for(i=1;i<=n;i++)        inDegreeCount[i] =0 ;   //初始时,所有结点的入度为0     i =1 ;    while(i<=n){ //从第1个结点到第n个结点        VNode   *vnodei ;                    //当前节点邻接链        ArcNode *arcNodeHead,*temp_arnode;    //节点链表,采用尾插法,temp_arcnode ,是临时结点,arcNodeHead是链表头        int outDegreeCount =0;      //当前结点出度信息统计,初始0        vnodei = new VNode ;        //分配地址,不然有空指针异常        arcNodeHead = new ArcNode;        arcNodeHead->next =NULL;     //初始化链表        arcNodeHead->adjvex=i ;      //第一个邻接点,指向自己        temp_arnode = arcNodeHead ;        cout<<"第"<<i<<"个结点的邻接链表,格式:邻结点的: 编号  输入-1结束当前顶点链的输入"<<endl ;        while(true){          int node_num ;            //邻结点编号          ArcNode *temp;           //临时保存一条邻接边的信息          cin>>node_num;          if(node_num==-1){                temp_arnode->next =NULL ;                break ;         }          temp = new ArcNode ;          temp->adjvex = node_num ;          temp_arnode->next = temp ; //将邻接边加入链表中,尾插法          temp_arnode = temp ; //指针后移动          inDegreeCount[node_num]++ ;  //入度,当前链表中出现顶点的入度+1          outDegreeCount++  ;  //当前链表输入几个顶点,出度就为几      }      temp_arnode->next=NULL ;          //链表尾置为空      vnodei->firstArc =arcNodeHead->next  ;  //应为第一个结点没有保存领接边信息,后移1位      vnodei->num = i ; //标记为i结的邻接边      graph->adjList[i] = *vnodei; //添加到图的邻接表中      graph->adjList[i].outDegreeCount =  outDegreeCount ;       i++ ;  //下一个结点    }    for(i=1;i<=n;i++)  //将所有入度信息,赋值给图中结点        graph->adjList[i].inDegreeCount =inDegreeCount[i] ;    return graph ;}void PrintAdj(AGraph *graph){  int i,n,num ;  n = graph->n ; //图的边数  for(i=1;i<=n;i++){    ArcNode *p ;    num = graph->adjList[i].num ;       //结点i编号    p= graph->adjList[i].firstArc ;     //结点i的邻结点链    cout<<num<<" ->";    while(p){        cout<<p->adjvex<<"->" ;         //邻结点编号        p=p->next ;    }    cout<<" 结点<<num<<的入度为"<<graph->adjList[i].inDegreeCount<<"  出度:"<<graph->adjList[i].outDegreeCount<<endl ;  }}// 拓扑排序void TopSort(AGraph * graph){    int i,u,v;    int n ;    int visit =0;    int Stack[MaxSize] ,top =-1 ; //栈    n = graph->n ; //图的顶点个数    ArcNode * p ;    for(i=1 ;i<= n ;i++){        if(graph->adjList[i].inDegreeCount == 0){ //将所有入度为0的顶点入栈            Stack[++top]  = i ;        }    }    while(top!=-1){         u= Stack[top--] ; //顶点出栈         visit++ ;         cout<<u<<"->" ; //访问当前入度v为0的顶点         p=graph->adjList[u].firstArc;      //顶点u的邻接链表         while(p!=NULL){             v = p->adjvex ;  //顶点u的邻接顶点v             graph->adjList[v].inDegreeCount-=1; //删除顶点u,所有u的所有邻接点v的入度个数-1             if( graph->adjList[v].inDegreeCount ==0) //更新后的入度为0,进栈                Stack[++top]  = v ;             p=p->next ;         }    }    cout<<endl ;    if(visit == n)        cout<<"遍历所有结点"<<endl ;    else        cout<<"失败"<<endl ;}int main(){   int i ,n ;   AGraph *graph = InitiaL_Graph() ; //图的初始化   //打印图的邻接表   cout<<"邻接表"<<endl ;   PrintAdj(graph);   cout<<"这个图的拓扑排序如下"<<endl ;   TopSort(graph) ;  return (1) ;}/*input: n =6 e=82 3 -14 5 -15 6 -16 -16 -1-1*/

 

Reference:

[1]: 2019版<<>数据结构高分笔记>>天勤

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值