👋 Hi, I’m @Beast Cheng
👀 I’m interested in photography, hiking, landscape…
🌱 I’m currently learning python, javascript, kotlin…
📫 How to reach me --> 458290771@qq.com
喜欢《数据结构》部分笔记的小伙伴可以订阅专栏,今后还会不断更新。🧑💻
感兴趣的小伙伴可以点一下订阅、收藏、关注!🚀
谢谢大家!🙏
AOV网
AOV网(Activity On Vertex Network,用顶点表示活动的网)
用DAG图(有向无环图)表示 一个工程。顶点表示活动,有向边 < V i , V j > <V_i,V_j> <Vi,Vj> 表示活动 V i V_i Vi 必须先于活动 V j V_j Vj 进行
拓扑排序
拓扑排序:找到做事的先后顺序
- 先准备厨具
- 然后买菜
- 选择先洗蕃茄(打鸡蛋)
- 切番茄
- 打鸡蛋
- 下锅炒
- 吃
拓扑排序的实现:
- 从AOV网中选择一个没有前驱(入度为0)的顶点并输出
- 从网中删除该顶点和所有以它为起点的有向边
- 重复第一步和第二步,知道当前的 AOV网为空或当前网中不存在无前驱的顶点为止
对有回路的图进行拓扑排序
当前所有顶点入度 > 0,说明原图存在回路,所以不存在拓扑排序序列
拓扑排序的代码实现
#define MaxVertexNum 100 // 图中顶点数目的最大值
typedef struct ArcNode{ // 边表结点int adjvex; // 该弧所指向的顶点的位置struct ArcNode *nextarc; // 指向下一条弧的指针// InfoType info; // 网的边权值
} ArcNode;typedef struct VNode{ // 顶点表结点VertexType data; // 顶点信息ArcNode *firstarc; // 指向第一条依附于该顶点的弧的指针
} VNode, AdjList[MaxVertexNum];typedef struct{AdjList vertices; // 邻接表int vexnum, arcnum; // 图的顶点数和弧数
} Graph; // Graph是以邻接表存储的图类型bool TopologicalSort(Graph G){InitStack(S); // 初始化栈,存储入度为0的顶点for(int i = 0; i < G.vexnum; i ++){if(indegree[i] == 0){Push(S, i); // 将所有入度为0的顶点进栈}}int count = 0; // 计数,记录当前已经输出的顶点数while(!isEmpty(S)){ // 栈不空,则存在入度为0的顶点Pop(S, i); // 栈顶元素出栈print[count ++] = i; // 输出顶点ifor(p = G.vertices[i].firstarc; p = p->nextarc){// 将所有i指向的顶点的入度减一,并且将入读减为零的顶点压入栈Sv = p->adjvex;if(!(--indegree[v])){Push(S, v); // 入度为0,则入栈}}} // whileif(count < G.vexnum){return false; // 拓扑排序失败,有向图中有回路}else{return true; // 拓扑排序成功}
}
时间复杂度: O ( ∣ V ∣ + ∣ E ∣ ) O(|V|+|E|) O(∣V∣+∣E∣)
若采用邻接矩阵,则需要 O ( ∣ V ∣ 2 ) O(|V|^2) O(∣V∣2)
逆拓扑排序
对于一个AOV网,如果采用一下步骤进行排序,则称之为 逆拓扑排序 :
- 从AOV网中选择一个没有后继(出度为0)的顶点并输出
- 从网中删除该顶点和所有以它为终点的有向边
- 重复①和②直到当前的AOV网为空
逆拓扑排序的实现(DFS算法)
void DFSTraverse(Graph G){for(v=0; v<G.vexnum; ++v)visited[v] = FALSE;for(v=-; v<G.vexnum; ++v)if(!visited[v])DFS(G, v);
}void DFS(Graph G, int v){visited[v] = TRUE;for(w = FirstNeighbor(G, v); w >= 0; w = NextNeighbor(G, v, w)){if(!visited[w]){DFS(G, w);}}printf(v);
}