找到做事的先后顺序
什么是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条边都要遍历