拓扑排序算法

找到做事的先后顺序

什么是AOV网?

在一个表示工程的有向图中,顶点表示活动,弧表示活动之间的优先关系

实现:
1.从AOV网中选择一个没有前驱(入度为0)的顶点并输出
2.从网中删除该顶点和所有以它为起点的有向边
3.重复1和2直到当前AOV网为空或当前网中不存在无前驱的顶点为止 

流程图例演示:
     1      2
    / \    / \
   /   \  /   \
  v     vv     v
  3 --> 4 ---> 5
 
第一步:
            2
           / \
          /   \
         v     v
  3 --> 4 ---> 5
第二步:    
            2
           / \
          /   \
         v     v
        4 ---> 5
第三步:        
        4 ---> 5
        
第四步:     5      

注意:拓扑排序情况不唯一

拓扑排序的图使用邻接表来存储        原因:多次设计到节点的删除操作,用临接表比较方便。

//需要用到的存储结构
typedef struct VertexNode{   //顶点表结点
    int in;                  //顶点入度
    int date;                //存储顶点信息
    EdgeNode *firstedge;     //指向边表结点
}VertexNode,AdjList[MAXVEX];
​
typedef struct EdgeNode{     /*边表节点*/
    int adjvex;              //存放下标
    int weight;              //存放权重,不是网可以不要该属性
    struct EdgeNode * next;  //链域,指向下一个邻接点
}EdgeNode;
​
typedef struct {
    AdjList adjList;
    int numVertexes,numEdges;   //图中当前顶点数和边数
}graphAdjList,*GraphAdjList;
//拓扑排序,若图无回路,输出排序序列并返回OK,若有回路返回ERROR
Status TopologicalSort(GraphAdjList GL){
    
    int count =0; //记录输出了多少个结点,用于判断是否存在环
    int * stack;  //用来存储入度是0的顶点
    int top=0; //stack的top指针
    stack = (int *)malloc(GL.numVertexes*sizeof(int));//动态开辟空间
    //往stack中加入度为0的结点
    for(int i =0;i<GL->numVertexes;i++){
        if(GL->adjList[i].in==0){
            stack[top]=i;//如果第i个结点的入度是0就加入到stack中
            top++;//top向上移一个
        }
    }
    //一个个弹出stack中度为0的结点并做处理(删除结点并且连边结点的度减一)
    int getTop;
    EdgeNode *e; //边结点
    while(top!=0){
        getTop=stack[top--];//出栈,弹出序号i,表示第i个结点
        //减去邻接表中,对应边结点的入度
        count++;//输出的结点数加一
        for(e=GL->adjList[getTop]->firstedge;e!=null;e=e->next;){
            if(--GL.adjList[e->adjvex].in == 0){//边结点的入度减一,减一后如果等于0,就加入到stack中
                stack[top++]=e->adjvex;
            }
        }
    }
    if(count<GL->numVertexes) return ERROR;
    else return TRUE;
    //如果最终输出的顶点数小于总的结点数,说明始终存在着结点入度不为0的情况,也就是存在环
}

时间复杂度:O(n+e) :因为n个顶点,e条边都要遍历

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值