👋 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; // 输出顶点i
for(p = G.vertices[i].firstarc; p = p->nextarc){
// 将所有i指向的顶点的入度减一,并且将入读减为零的顶点压入栈S
v = p->adjvex;
if(!(--indegree[v])){
Push(S, v); // 入度为0,则入栈
}
}
} // while
if(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);
}