数据结构与算法基础-学习-29-图之关键路径

news2025/1/11 19:52:24

 图的其他相关知识点和源码分享可以参考之前的博客:   

《数据结构与算法基础-学习-23-图之邻接矩阵与邻接表》,

《数据结构与算法基础-学习-24-图的遍历之DFS(深度优先搜索)和BFS(广度优先搜索)》,

《数据结构与算法基础-学习-25-图之MST(最小代价生成树)之Prim(普利姆)算法》,

《数据结构与算法基础-学习-26-图之MST(最小代价生成树)之Kluskal(克鲁斯卡尔)算法》,

《数据结构与算法基础-学习-27-图之最短路径之Dijkstra(迪杰斯特拉)算法》,

《数据结构与算法基础-学习-28-图之拓扑排序》

一、相关定义

1、把工程计划表示为边表示活动的网络,即AOE网,用顶点表示事件,弧表示活动,弧的权表示活动持续时间。

2、事件表示在它之前的活动已经完成,在它之后的活动可以开始。

3、关键路径:路径长度最长的路径。

4、路径长度:路径上个活动持续时间之和。

二、个人理解

1、关键路径表示一个工程的话,例如做饭,开始做饭表示整个工程开始,结束做饭表示整个工程结束,也就是说只一个起点或者叫源点(入度为0的顶点),只有一个终点或者叫汇点(出度为0的顶点)。

2、我们在进行关键路径计算时,需要判断:

(1)这是不是一个有向图。

(2)是不是无环(可以通过拓扑排序来判断)。

(3)是不是只有一个源点和一个终点。

三、解决了那些事

1、完成整项工程至少需要花费多少时间。

2、哪些活动是影响工程进度的关键。

四、描述量

名称描述
ve(vj)表示事件(顶点)vj的最早发生时间。
vl(vj)表示事件(顶点)vj的最迟发生时间。
e(i)表示活动(弧)ai的最早开始时间。
l(i)表示活动(弧)ai的最迟开始时间。

五、公式

1、ve(j) = Max(ve(i) + w(i,j)),表示i->j的情况下。

2、vl(i) = Min(vl(j) - w(i,j)),表示i->j的情况下。

3、e(i) = ve(j),表示j->k,第i各活动的情况下。

4、l(i) = vl(k) - w(j,k),表示j->k,第i各活动的情况下。

六、关键路径算法思路

 我这边是结合邻接矩阵实现的,生成邻接矩阵如下:

2023-8-23 9:33:49--[ Debug ]--Printf AMGraph                     :
VertexArray    : [0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ]
ArcArray       :
0  : [32767 ,6     ,4     ,5     ,32767 ,32767 ,32767 ,32767 ,32767 ]
1  : [32767 ,32767 ,32767 ,32767 ,1     ,32767 ,32767 ,32767 ,32767 ]
2  : [32767 ,32767 ,32767 ,32767 ,1     ,32767 ,32767 ,32767 ,32767 ]
3  : [32767 ,32767 ,32767 ,32767 ,32767 ,2     ,32767 ,32767 ,32767 ]
4  : [32767 ,32767 ,32767 ,32767 ,32767 ,32767 ,9     ,7     ,32767 ]
5  : [32767 ,32767 ,32767 ,32767 ,32767 ,32767 ,32767 ,4     ,32767 ]
6  : [32767 ,32767 ,32767 ,32767 ,32767 ,32767 ,32767 ,32767 ,2     ]
7  : [32767 ,32767 ,32767 ,32767 ,32767 ,32767 ,32767 ,32767 ,4     ]
8  : [32767 ,32767 ,32767 ,32767 ,32767 ,32767 ,32767 ,32767 ,32767 ]
InduityArray   : [0 ,1 ,1 ,1 ,2 ,1 ,1 ,2 ,2 ]
OutdegreeArray : [3 ,1 ,1 ,1 ,2 ,1 ,1 ,1 ,0 ]
CurVertexNum   : 9
CurArcNum      : 11

在之前分享的邻接矩阵代码的基础上增加了入度InduityArray和出度OutdegreeArray,为了方便计算。

1、计算事件最早发生时间

2023-8-23 9:46:19--[ Debug ]--SqQueue Data   :
Data           : [ 0 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ]
FrontIndex     : 0
RearIndex      : 0
SqQueueLen     : 9
SqQueueMaxLen  : 9
Flag           : INT_TYPE_FLAG

初始化一个事件最早发生的队列,不一定是队列,数组也行。源点的最早发生时间是0,填入到队列中,其他值还不确定所以先初始化-1。

2023-8-23 9:56:37--[ Debug ]--Printf SqStack
Data           : [ 0 ]
Flag           : INT_TYPE_FLAG
2023-8-23 9:56:37--[ Debug ]--Printf HashTable
DataNum : 1     , [ (0,(nil)) ]
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
TotalDataNum : 1     
ArrayMaxLen  : 9

还需要两个访问数组,分别是用哈希表和栈实现的,为什么要用两个呢,因为一个用来快速访问节点是否访问过。一个用来进行节点回溯。后面看着看着就会领悟的。我们先把访问过的源点0压入两个访问数组中。

进入一个大循环,循环退出条件为所有节点都被访问过。

栈中压出第一个节点0,然后我们在邻接矩阵中扫描第0行。我们可以扫描到三个边a1、a2、a3,且他们对应的终点V1、V2、V3的入度都是1,根据公式ve(j) = Max(ve(i) + w(i,j))。

(1)0->1,ve(1) = Max(ve(0) + w(0,1)) = 0 + 6 = 6

(2)0->2,ve(2) = Max(ve(0) + w(0,2)) = 0 + 4 = 4

(3)0->3,ve(3) = Max(ve(0) + w(0,3)) = 0 + 5 = 5

这三个点都访问过,我们都压入访问数组中,具体如下:

2023-8-23 9:56:37--[ Debug ]--SqQueue Data   :
Data           : [ 0 ,6 ,4 ,5 ,-1 ,-1 ,-1 ,-1 ,-1 ]
FrontIndex     : 0
RearIndex      : 0
SqQueueLen     : 9
SqQueueMaxLen  : 9
Flag           : INT_TYPE_FLAG
2023-8-23 9:56:37--[ Debug ]--Printf SqStack
Data           : [ 1 ,2 ,3 ]
Flag           : INT_TYPE_FLAG
2023-8-23 9:56:37--[ Debug ]--Printf HashTable
DataNum : 1     , [ (0,(nil)) ]
DataNum : 1     , [ (1,(nil)) ]
DataNum : 1     , [ (2,(nil)) ]
DataNum : 1     , [ (3,(nil)) ]
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
TotalDataNum : 4     
ArrayMaxLen  : 9     

第0行都已经遍历完,我们压出栈的下一个元素3,然后我们在邻接矩阵中扫描第3行。

我们可以扫描到边a6,且对应的终点V6的入度是1,根据公式ve(j) = Max(ve(i) + w(i,j))。

(1)3->5,ve(5) = Max(ve(3) + w(3,5)) = 5 + 2 = 7

这个点访问过,我们压入访问数组中,具体如下:

2023-8-23 9:56:37--[ Debug ]--SqQueue Data   :
Data           : [ 0 ,6 ,4 ,5 ,-1 ,7 ,-1 ,-1 ,-1 ]
FrontIndex     : 0
RearIndex      : 0
SqQueueLen     : 9
SqQueueMaxLen  : 9
Flag           : INT_TYPE_FLAG
2023-8-23 9:56:37--[ Debug ]--Printf SqStack
Data           : [ 1 ,2 ,5 ]
Flag           : INT_TYPE_FLAG
2023-8-23 9:56:37--[ Debug ]--Printf HashTable
DataNum : 1     , [ (0,(nil)) ]
DataNum : 1     , [ (1,(nil)) ]
DataNum : 1     , [ (2,(nil)) ]
DataNum : 1     , [ (3,(nil)) ]
DataNum : 0     , [(nil)]
DataNum : 1     , [ (5,(nil)) ]
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
TotalDataNum : 5     
ArrayMaxLen  : 9     

第3行都已经遍历完,我们压出栈的下一个元素5,然后我们在邻接矩阵中扫描第5行。

我们可以扫描到边a9,且对应的终点V7的入度是2,且V7的另一条入度边a8的起点V4没有访问过,所以不能计算V7的事件最早发生时间。

具体如下:

2023-8-23 9:56:37--[ Debug ]--SqQueue Data   :
Data           : [ 0 ,6 ,4 ,5 ,-1 ,7 ,-1 ,-1 ,-1 ]
FrontIndex     : 0
RearIndex      : 0
SqQueueLen     : 9
SqQueueMaxLen  : 9
Flag           : INT_TYPE_FLAG
2023-8-23 9:56:37--[ Debug ]--Printf SqStack
Data           : [ 1 ,2 ]
Flag           : INT_TYPE_FLAG
2023-8-23 9:56:37--[ Debug ]--Printf HashTable
DataNum : 1     , [ (0,(nil)) ]
DataNum : 1     , [ (1,(nil)) ]
DataNum : 1     , [ (2,(nil)) ]
DataNum : 1     , [ (3,(nil)) ]
DataNum : 0     , [(nil)]
DataNum : 1     , [ (5,(nil)) ]
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
TotalDataNum : 5     
ArrayMaxLen  : 9     

第5行都已经遍历完,我们压出栈的下一个元素2,然后我们在邻接矩阵中扫描第2行。

我们可以扫描到边a5,且对应的终点V4的入度是2,V4入度边的起点V1和V2我们都是访问过的,可以计算事件最早发生时间,根据公式ve(j) = Max(ve(i) + w(i,j))。

(1)1->4,2->4,ve(4) = Max(ve(1) + w(1,4),ve(2) + w(2,4)) = Max(6 +1,4 + 1) = Max(7,5) = 7

这个点访问过,我们压入访问数组中,具体如下:

2023-8-23 9:56:37--[ Debug ]--SqQueue Data   :
Data           : [ 0 ,6 ,4 ,5 ,7 ,7 ,-1 ,-1 ,-1 ]
FrontIndex     : 0
RearIndex      : 0
SqQueueLen     : 9
SqQueueMaxLen  : 9
Flag           : INT_TYPE_FLAG
2023-8-23 9:56:37--[ Debug ]--Printf SqStack
Data           : [ 1 ,4 ]
Flag           : INT_TYPE_FLAG
2023-8-23 9:56:37--[ Debug ]--Printf HashTable
DataNum : 1     , [ (0,(nil)) ]
DataNum : 1     , [ (1,(nil)) ]
DataNum : 1     , [ (2,(nil)) ]
DataNum : 1     , [ (3,(nil)) ]
DataNum : 1     , [ (4,(nil)) ]
DataNum : 1     , [ (5,(nil)) ]
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
TotalDataNum : 6     
ArrayMaxLen  : 9     

第2行都已经遍历完,我们压出栈的下一个元素4,然后我们在邻接矩阵中扫描第4行。

我们可以扫描到边a7,a8,V6的入度是1我们可以直接计算事件最早发生,a8对应的终点V7的入度是2,V7入度边的起点V4和V5我们都是访问过的,可以计算事件最早发生时间,根据公式ve(j) = Max(ve(i) + w(i,j))。

(1)4->6,ve(6) = Max(ve(4) + w(4,6)) = Max(7 + 9) = 16

(2)4->7,5->7,ve(7) = Max(ve(4) + w(4,7),ve(5) + w(5,7)) = Max(7 +7,7 + 4) = Max(14,11) = 14

这些点访问过,我们压入访问数组中,具体如下:

2023-8-23 9:56:37--[ Debug ]--SqQueue Data   :
Data           : [ 0 ,6 ,4 ,5 ,7 ,7 ,16 ,14 ,-1 ]
FrontIndex     : 0
RearIndex      : 0
SqQueueLen     : 9
SqQueueMaxLen  : 9
Flag           : INT_TYPE_FLAG
2023-8-23 9:56:37--[ Debug ]--Printf SqStack
Data           : [ 1 ,6 ,7 ]
Flag           : INT_TYPE_FLAG
2023-8-23 9:56:37--[ Debug ]--Printf HashTable
DataNum : 1     , [ (0,(nil)) ]
DataNum : 1     , [ (1,(nil)) ]
DataNum : 1     , [ (2,(nil)) ]
DataNum : 1     , [ (3,(nil)) ]
DataNum : 1     , [ (4,(nil)) ]
DataNum : 1     , [ (5,(nil)) ]
DataNum : 1     , [ (6,(nil)) ]
DataNum : 1     , [ (7,(nil)) ]
DataNum : 0     , [(nil)]
TotalDataNum : 8     
ArrayMaxLen  : 9     

第4行都已经遍历完,我们压出栈的下一个元素7,然后我们在邻接矩阵中扫描第7行。

我们可以扫描到边a11,V8入度边的起点V6和V7我们都是访问过的,可以计算事件最早发生时间,根据公式ve(j) = Max(ve(i) + w(i,j))。

(1)6->8,7->8,ve(8) = Max(ve(6) + w(6,8),ve(7) + w(7,8)) = Max(16 +2,14 + 4) = Max(18,18) = 18

这些点访问过,我们压入访问数组中,具体如下:

2023-8-23 9:56:37--[ Debug ]--SqQueue Data   :
Data           : [ 0 ,6 ,4 ,5 ,7 ,7 ,16 ,14 ,18 ]
FrontIndex     : 0
RearIndex      : 0
SqQueueLen     : 9
SqQueueMaxLen  : 9
Flag           : INT_TYPE_FLAG
2023-8-23 9:56:37--[ Debug ]--Printf SqStack
Data           : [ 1 ,6 ,8 ]
Flag           : INT_TYPE_FLAG
2023-8-23 9:56:37--[ Debug ]--Printf HashTable
DataNum : 1     , [ (0,(nil)) ]
DataNum : 1     , [ (1,(nil)) ]
DataNum : 1     , [ (2,(nil)) ]
DataNum : 1     , [ (3,(nil)) ]
DataNum : 1     , [ (4,(nil)) ]
DataNum : 1     , [ (5,(nil)) ]
DataNum : 1     , [ (6,(nil)) ]
DataNum : 1     , [ (7,(nil)) ]
DataNum : 1     , [ (8,(nil)) ]
TotalDataNum : 9     
ArrayMaxLen  : 9     

所有点被访问完了,事件最早发生时间也就被算出来了。

2、事件最迟发生时间

事件最迟发生时间和事件最早发生时间的计算上的区别:

1、事件最早发生时间是从起点到源点,事件最迟发生时间反之从源点到起点。

2、事件最早发生时间是横向扫描邻接矩阵,事件最迟发生时间反之是纵向扫描。

3、事件最早发生时间是根据入度进行相关判断,事件最迟发生时间反之是根据出度判断。

源点的事件最迟发生时间和起点是一样的,都是18,我们先填入18和节点8,如下:

2023-8-23 14:6:28--[ Debug ]--SqQueue Data   :
Data           : [ -1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,18 ]
FrontIndex     : 0
RearIndex      : 0
SqQueueLen     : 9
SqQueueMaxLen  : 9
Flag           : INT_TYPE_FLAG
2023-8-23 14:6:28--[ Debug ]--Printf SqStack
Data           : [ 8 ]
Flag           : INT_TYPE_FLAG
2023-8-23 14:6:28--[ Debug ]--Printf HashTable
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
DataNum : 1     , [ (8,(nil)) ]
TotalDataNum : 1     
ArrayMaxLen  : 9     

进入循环,我们从栈中压出节点8,开始纵向扫描节点8,发现6和7节点,且他们的出度都是1,根据公式vl(j) = Min(vl(j) - w(i,j)),进行计算:

(1)6->8,vl(6) = Min(vl(8) - w(6,8)) = Min(18 - 2) = 16

(2)7->8,vl(7) = Min(vl(8) - w(7,8)) = Min(18 - 4) = 14

这些点访问过,我们压入访问数组中,具体如下:

2023-8-23 14:6:28--[ Debug ]--SqQueue Data   :
Data           : [ -1 ,-1 ,-1 ,-1 ,-1 ,-1 ,16 ,14 ,18 ]
FrontIndex     : 0
RearIndex      : 0
SqQueueLen     : 9
SqQueueMaxLen  : 9
Flag           : INT_TYPE_FLAG
2023-8-23 14:6:28--[ Debug ]--Printf SqStack
Data           : [ 6 ,7 ]
Flag           : INT_TYPE_FLAG
2023-8-23 14:6:28--[ Debug ]--Printf HashTable
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
DataNum : 1     , [ (6,(nil)) ]
DataNum : 1     , [ (7,(nil)) ]
DataNum : 1     , [ (8,(nil)) ]
TotalDataNum : 3     
ArrayMaxLen  : 9     

继续进入循环,我们从栈中压出节点7,开始纵向扫描节点7,发现4和5节点,5的出度是1,可以直接计算,4的出度是2,且节点6和7都已经访问过了,也可以计算,根据公式vl(j) = Min(vl(j) - w(i,j)),进行计算:

(1)4->6,4->7,vl(4) = Min(vl(6) - w(4,6),vl(7) - w(4,7)) = Min(16 - 9,14 - 7) = 7

(2)5->7,vl(5) = Min(vl(7) - w(5,7)) = Min(14 - 4) = 10

这些点访问过,我们压入访问数组中,具体如下:

2023-8-23 14:6:28--[ Debug ]--SqQueue Data   :
Data           : [ -1 ,-1 ,-1 ,-1 ,7 ,10 ,16 ,14 ,18 ]
FrontIndex     : 0
RearIndex      : 0
SqQueueLen     : 9
SqQueueMaxLen  : 9
Flag           : INT_TYPE_FLAG
2023-8-23 14:6:28--[ Debug ]--Printf SqStack
Data           : [ 6 ,4 ,5 ]
Flag           : INT_TYPE_FLAG
2023-8-23 14:6:28--[ Debug ]--Printf HashTable
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
DataNum : 1     , [ (4,(nil)) ]
DataNum : 1     , [ (5,(nil)) ]
DataNum : 1     , [ (6,(nil)) ]
DataNum : 1     , [ (7,(nil)) ]
DataNum : 1     , [ (8,(nil)) ]
TotalDataNum : 5     
ArrayMaxLen  : 9     

继续进入循环,我们从栈中压出节点5,开始纵向扫描节点5,发现3节点,3的出度是1,可以直接计算,根据公式vl(j) = Min(vl(j) - w(i,j)),进行计算:

(1)3->5,vl(3) = Min(vl(5) - w(3,5)) = Min(10 - 2) = 8

这些点访问过,我们压入访问数组中,具体如下:

2023-8-23 14:6:28--[ Debug ]--SqQueue Data   :
Data           : [ -1 ,-1 ,-1 ,8 ,7 ,10 ,16 ,14 ,18 ]
FrontIndex     : 0
RearIndex      : 0
SqQueueLen     : 9
SqQueueMaxLen  : 9
Flag           : INT_TYPE_FLAG
2023-8-23 14:6:28--[ Debug ]--Printf SqStack
Data           : [ 6 ,4 ,3 ]
Flag           : INT_TYPE_FLAG
2023-8-23 14:6:28--[ Debug ]--Printf HashTable
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
DataNum : 1     , [ (3,(nil)) ]
DataNum : 1     , [ (4,(nil)) ]
DataNum : 1     , [ (5,(nil)) ]
DataNum : 1     , [ (6,(nil)) ]
DataNum : 1     , [ (7,(nil)) ]
DataNum : 1     , [ (8,(nil)) ]
TotalDataNum : 6     
ArrayMaxLen  : 9     

继续进入循环,我们从栈中压出节点3,开始纵向扫描节点3,发现0节点,0的出度是3,发现1号点没有访问过直接退出当前循环,后面的2,3不需要扫描,因为一个没访问就不可以进行计算。

具体如下:

2023-8-23 14:6:28--[ Debug ]--SqQueue Data   :
Data           : [ -1 ,-1 ,-1 ,8 ,7 ,10 ,16 ,14 ,18 ]
FrontIndex     : 0
RearIndex      : 0
SqQueueLen     : 9
SqQueueMaxLen  : 9
Flag           : INT_TYPE_FLAG
2023-8-23 14:6:28--[ Debug ]--Printf SqStack
Data           : [ 6 ,4 ]
Flag           : INT_TYPE_FLAG
2023-8-23 14:6:28--[ Debug ]--Printf HashTable
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
DataNum : 0     , [(nil)]
DataNum : 1     , [ (3,(nil)) ]
DataNum : 1     , [ (4,(nil)) ]
DataNum : 1     , [ (5,(nil)) ]
DataNum : 1     , [ (6,(nil)) ]
DataNum : 1     , [ (7,(nil)) ]
DataNum : 1     , [ (8,(nil)) ]
TotalDataNum : 6     
ArrayMaxLen  : 9     

继续进入循环,我们从栈中压出节点4,开始纵向扫描节点4,发现1,2节点,且出度都是1,可以直接计算,根据公式vl(j) = Min(vl(j) - w(i,j)),进行计算:

(1)1->4,vl(1) = Min(vl(4) - w(1,4)) = Min(7 - 1) = 6

(2)2->4,vl(2) = Min(vl(4) - w(2,4)) = Min(7 - 1) = 6

这些点访问过,我们压入访问数组中,具体如下:

2023-8-23 14:6:28--[ Debug ]--SqQueue Data   :
Data           : [ -1 ,6 ,6 ,8 ,7 ,10 ,16 ,14 ,18 ]
FrontIndex     : 0
RearIndex      : 0
SqQueueLen     : 9
SqQueueMaxLen  : 9
Flag           : INT_TYPE_FLAG
2023-8-23 14:6:28--[ Debug ]--Printf SqStack
Data           : [ 6 ,1 ,2 ]
Flag           : INT_TYPE_FLAG
2023-8-23 14:6:28--[ Debug ]--Printf HashTable
DataNum : 0     , [(nil)]
DataNum : 1     , [ (1,(nil)) ]
DataNum : 1     , [ (2,(nil)) ]
DataNum : 1     , [ (3,(nil)) ]
DataNum : 1     , [ (4,(nil)) ]
DataNum : 1     , [ (5,(nil)) ]
DataNum : 1     , [ (6,(nil)) ]
DataNum : 1     , [ (7,(nil)) ]
DataNum : 1     , [ (8,(nil)) ]
TotalDataNum : 8     
ArrayMaxLen  : 9     

继续进入循环,我们从栈中压出节点2,开始纵向扫描节点2,发现0节点,且出度都是3,1,2,3节点都被访问过,可以直接计算,根据公式vl(j) = Min(vl(j) - w(i,j)),进行计算:

(1)0->1,0->2,0->3,vl(0) = Min(vl(1) - w(0,1),vl(2) - w(0,2),vl(3) - w(0,4)) = Min(6 - 6,6 - 4,8 - 5) = Min(0,2,3) = 0

这些点访问过,我们压入访问数组中,具体如下:

2023-8-23 14:6:28--[ Debug ]--SqQueue Data   :
Data           : [ 0 ,6 ,6 ,8 ,7 ,10 ,16 ,14 ,18 ]
FrontIndex     : 0
RearIndex      : 0
SqQueueLen     : 9
SqQueueMaxLen  : 9
Flag           : INT_TYPE_FLAG
2023-8-23 14:6:28--[ Debug ]--Printf SqStack
Data           : [ 6 ,1 ,0 ]
Flag           : INT_TYPE_FLAG
2023-8-23 14:6:28--[ Debug ]--Printf HashTable
DataNum : 1     , [ (0,(nil)) ]
DataNum : 1     , [ (1,(nil)) ]
DataNum : 1     , [ (2,(nil)) ]
DataNum : 1     , [ (3,(nil)) ]
DataNum : 1     , [ (4,(nil)) ]
DataNum : 1     , [ (5,(nil)) ]
DataNum : 1     , [ (6,(nil)) ]
DataNum : 1     , [ (7,(nil)) ]
DataNum : 1     , [ (8,(nil)) ]
TotalDataNum : 9     
ArrayMaxLen  : 9     

所有点被访问完了,事件最迟发生时间也就被算出来了。

3、活动最早开始、最迟时间,关键路径

有了事件最迟发生时间和事件最早发生时间,活动最早开始、最迟时间,关键路径就好算了,直接套公式。

我们一条边一条边来。

关键路径我是活动最早开始事件 - 活动最迟开始事件,所以是负值,但不影响取关键路径。

弧信息活动最早开始事件活动最迟开始事件关键路径
a1边,0->1e(1) = ve(0) = 0

l(1) = vl(1) - w(0,1) = 0

0 - 0 = 0
a2边,0->2e(2) = ve(0) = 0

l(2) = vl(2) - w(0,2) = 2

0 - 2 = -2
a3边,0->3e(3) = ve(0) = 0

l(3) = vl(3) - w(0,3) = 3

0 - 3 = -3
a4边,1->4e(4) = ve(1) = 6

l(4) = vl(4) - w(1,4) = 6

6 - 6 = 0
a5边,2->4e(5) = ve(2) = 4

l(5) = vl(4) - w(2,4) = 6

4 - 6 = -2
a6边,3->5e(6) = ve(3) = 5

l(6) = vl(5) - w(3,5) = 8

5 - 8 = -3
a7边,4->6e(7) = ve(4) = 7

l(7) = vl(6) - w(4,6) = 7

7 - 7 = 0
a8边,4->7e(8) = ve(4) = 7

l(8) = vl(7) - w(4,7) = 7

7 - 7 = 0
a9边,5->7e(9) = ve(5) = 7

l(9) = vl(7) - w(5,7) = 10

7 - 10 = -3
a10边,6->8e(10) = ve(6) = 16

l(10) = vl(8) - w(6,8) = 16

16 - 16 = 0
a11边,7->8e(11) = ve(7) = 14

l(11) = vl(8) - w(7,8) = 14

14 - 14 = 0

七、自定义宏定义

#define CRITICAL_PATH_INIT_VAL -1

八、自定义结构体

typedef struct CriticalPathEventSt
{
    SqQueue* VertexEarlyQueue;    //事件最早发生权值或时间的队列。公式:ve(j) = Max(ve(i) + w(i,j)),表示i->j的情况下。
    SqQueue* VertexLateQueue;     //事件最晚发生权值或时间的队列。公式:vl(i) = Min(vl(j) - w(i,j)),表示i->j的情况下。
}CriticalPathEventSt;

typedef struct CriticalPathActivitySt
{
    SqQueue* ArcStartVertexQueue; //存放活动(弧)的起始节点索引的队列。
    SqQueue* ArcEndVertexQueue;   //存放活动(弧)的结束节点索引的队列。
    SqQueue* ArcEarlyQueue;       //活动最早发生权值或时间的队列。公式:e(i) = ve(j),表示j->k,第i各活动的情况下。
    SqQueue* ArcLateQueue;        //活动最晚发生权值或时间的队列。公式:l(i) = vl(k) - w(j,k),表示j->k,第i各活动的情况下。
    SqQueue* CriticalPathQueue;   //关键路径的队列。
}CriticalPathActivitySt;

typedef struct CriticalPathSt
{
    CriticalPathEventSt*    Event;
    CriticalPathActivitySt* Activity;
}CriticalPathSt;

九、自定义函数

1、InitCriticalPathEventSt

Status InitCriticalPathEventSt(CriticalPathEventSt** CpEvent, VertexIndexType ArrayMaxLen)
{
    JudgeAllNullPointer(CpEvent);

    *CpEvent                     = (CriticalPathEventSt*)MyMalloc(sizeof(CriticalPathEventSt));
    (*CpEvent)->VertexEarlyQueue = NULL;
    (*CpEvent)->VertexLateQueue  = NULL;
    InitSqQueue(&((*CpEvent)->VertexEarlyQueue),ArrayMaxLen,INT_TYPE_FLAG);
    InitSqQueue(&((*CpEvent)->VertexLateQueue),ArrayMaxLen,INT_TYPE_FLAG);

    LogFormat(Debug, "%s\n", "Init Critical Path Event St OK.");
    return SuccessFlag;
}

2、DestroyCriticalPathEventSt

Status DestroyCriticalPathEventSt(CriticalPathEventSt** CpEvent)
{
    JudgeAllNullPointer(*CpEvent);

    DestroySqQueue(&((*CpEvent)->VertexEarlyQueue));
    DestroySqQueue(&((*CpEvent)->VertexLateQueue));
    (*CpEvent)->VertexEarlyQueue = NULL;
    (*CpEvent)->VertexLateQueue  = NULL;
    free(*CpEvent);
    *CpEvent                     = NULL;

    LogFormat(Debug, "%s\n", "Destroy Critical Path Event St OK.");
    return SuccessFlag;
}

3、InitCriticalPathActivitySt

Status InitCriticalPathActivitySt(CriticalPathActivitySt** CpActivity, VertexIndexType ArrayMaxLen)
{
    JudgeAllNullPointer(CpActivity);
    
    *CpActivity                        = (CriticalPathActivitySt*)MyMalloc(sizeof(CriticalPathActivitySt));
    (*CpActivity)->ArcStartVertexQueue = NULL;
    (*CpActivity)->ArcEndVertexQueue   = NULL;
    (*CpActivity)->ArcEarlyQueue       = NULL;
    (*CpActivity)->ArcLateQueue        = NULL;
    (*CpActivity)->CriticalPathQueue   = NULL;
    InitSqQueue(&((*CpActivity)->ArcStartVertexQueue),ArrayMaxLen,INT_TYPE_FLAG);
    InitSqQueue(&((*CpActivity)->ArcEndVertexQueue),ArrayMaxLen,INT_TYPE_FLAG);
    InitSqQueue(&((*CpActivity)->ArcEarlyQueue),ArrayMaxLen,INT_TYPE_FLAG);
    InitSqQueue(&((*CpActivity)->ArcLateQueue),ArrayMaxLen,INT_TYPE_FLAG);
    InitSqQueue(&((*CpActivity)->CriticalPathQueue),ArrayMaxLen,INT_TYPE_FLAG);

    LogFormat(Debug, "%s\n", "Init Critical Path Activity St OK.");
    return SuccessFlag;
}

4、DestroyCriticalPathActivitySt

Status DestroyCriticalPathActivitySt(CriticalPathActivitySt** CpActivity)
{
    JudgeAllNullPointer(*CpActivity);
    
    DestroySqQueue(&((*CpActivity)->ArcStartVertexQueue));
    DestroySqQueue(&((*CpActivity)->ArcEndVertexQueue));
    DestroySqQueue(&((*CpActivity)->ArcEarlyQueue));
    DestroySqQueue(&((*CpActivity)->ArcLateQueue));
    DestroySqQueue(&((*CpActivity)->CriticalPathQueue));
    (*CpActivity)->ArcStartVertexQueue = NULL;
    (*CpActivity)->ArcEndVertexQueue   = NULL;
    (*CpActivity)->ArcEarlyQueue       = NULL;
    (*CpActivity)->ArcLateQueue        = NULL;
    (*CpActivity)->CriticalPathQueue   = NULL;

    free(*CpActivity);
    *CpActivity = NULL;

    LogFormat(Debug, "%s\n", "Destroy Critical Path Activity St OK.");
    return SuccessFlag;
}

5、InitCriticalPathSt

Status InitCriticalPathSt(CriticalPathSt** CP, AMGraph* AMG)
{
    JudgeAllNullPointer(CP);
    JudgeAllNullPointer(AMG);

    if (AMG->DirectionFlag == NET_UNDIRECTION_FLAG)//关键路径只支持有向网。
    {
        LogFormat(Warning,"Critical Path Init Only Support Directed Net, Exit.");
        return FailFlag;
    }

    *CP             = (CriticalPathSt*)MyMalloc(sizeof(CriticalPathSt));
    (*CP)->Event    = NULL;
    (*CP)->Activity = NULL;

    InitCriticalPathEventSt(&((*CP)->Event), AMG->CurVertexNum);
    InitCriticalPathActivitySt(&((*CP)->Activity), AMG->CurArcNum);
    
    LogFormat(Debug, "%s\n", "Init Critical Path St OK.");
    return SuccessFlag;
}

6、DestroyCriticalPathSt

Status DestroyCriticalPathSt(CriticalPathSt** CP)
{
    JudgeAllNullPointer(*CP);

    DestroyCriticalPathEventSt(&((*CP)->Event));
    DestroyCriticalPathActivitySt(&((*CP)->Activity));
    (*CP)->Event    = NULL;
    (*CP)->Activity = NULL;
    free(*CP);
    *CP             = NULL;

    LogFormat(Debug, "%s\n", "Destroy Critical Path St OK.");
    return SuccessFlag;
}

7、CheckCriticalPathAmgIllegal

//检查邻接矩阵是否适用于关键路径算法,只有一个起点和一个汇点。
//检查起点是否合法。
Status CheckCriticalPathAmgIllegal(AMGraph* AMG, VertexIndexType StartVertexIndex)
{
    JudgeAllNullPointer(AMG);

    //判断起始节点StartVertexIndex是否是在顶点索引范围内,不在,退出函数。
    if (StartVertexIndex < 0 || StartVertexIndex >= (AMG->CurVertexNum))
    {
        LogFormat(Debug,"StartVertexIndex : %d Is Illegal Node.\n",StartVertexIndex);
        return FailFlag;
    }

    VertexIndexType i;
    VertexIndexType StartVertexNum      = 0;  //起点个数
    VertexIndexType EndVertexNum        = 0;  //汇点个数
    VertexIndexType TmpStartVertexIndex = -1; //起点索引,和StartVertexIndex做对比。
    VertexIndexType TmpEndVertexIndex   = -1; //汇点索引。

    for ( i = 0; i < AMG->CurVertexNum; i++)
    {
        if (AMG->InduityArray[i] == 0)
        {
            StartVertexNum++;
            TmpStartVertexIndex = i;
        }
        if (StartVertexNum > 1)
        {
            LogFormat(Debug,"Adjacency Matrix Graph Has Multiple Starting Vertex.\n");
            return FailFlag;
        }
        
    }

    if (StartVertexNum != TmpStartVertexIndex)
    {
        LogFormat(Debug,"StartVertexIndex : %d ,It Has Precursor Vertex, Check Adjacency Matrix Graph Fail\n",StartVertexIndex);
    }

    for ( i = 0; i < AMG->CurVertexNum; i++)
    {
        if (AMG->OutdegreeArray[i] == 0)
        {
            EndVertexNum++;
            TmpEndVertexIndex = i;
        }
        if (EndVertexNum > 1)//汇点数量大于1,不符合关键路径的场景。
        {
            LogFormat(Debug,"Adjacency Matrix Graph Has Multiple Ending Vertex, Check Adjacency Matrix Graph Fail\n");
            return FailFlag;
        }
    }

    LogFormat(Debug, "(StartVertexIndex : %d,EndVertexIndex : %d), Check Adjacency Matrix Graph OK.\n",TmpStartVertexIndex,TmpEndVertexIndex);
    return SuccessFlag;
}

8、CheckInduityVertexExists

//检查某个顶点的入度顶点是否都存在于访问哈希表中。
//都被访问过返回:SuccessFlag。反之返回:FailFlag。
Status CheckInduityVertexExists(AMGraph* AMG, VertexIndexType VertexIndex, MyHashTable* VisitedHashTable, SqQueue* VertexEarlyQueue, WeightType* MaxWeight)
{
    JudgeAllNullPointer(AMG);
    JudgeAllNullPointer(VisitedHashTable);

    VertexIndexType i;
    VertexIndexType Induity         = AMG->InduityArray[VertexIndex];
    WeightType      PreVertexWeight = 0;//上一个节点的权值

    if (Induity == 0)
    {
        LogFormat(Error,"Internal Logic Error, VertexIndex(%d) Induity(0).\n",VertexIndex);
        return FailFlag;
    }
    
    HashTabElemType HashValue;

    for (i = 0; i < AMG->CurVertexNum; i++)//入度为复数的情况
    {
        if (AMG->ArcArray[i][VertexIndex] != MAX_INT_TYPE_NUM)
        {
            if (SearchHashTable(VisitedHashTable,&i,&HashValue) == SuccessFlag)
            {
                ReadSqQueue(VertexEarlyQueue,i,&PreVertexWeight);
                if (Induity == AMG->InduityArray[VertexIndex])//给MaxWeight赋予初值
                {
                    *MaxWeight = AMG->ArcArray[i][VertexIndex] + PreVertexWeight;
                }
                else
                {
                    *MaxWeight = MY_MAX(*MaxWeight,AMG->ArcArray[i][VertexIndex] + PreVertexWeight);
                }
                Induity--;
            }
            else
            {
                return FailFlag;
            }
        }
        if (Induity == 0)//说明所有入度点全部被找到,下面的顶点不需要再扫描,跳出循环。
        {
            break;
        }
    }
    
    return SuccessFlag;
}

9、CheckOutDegreeVertexExists

//检查某个顶点的出度顶点是否都存在于访问哈希表中。
//都被访问过返回:SuccessFlag。反之返回:FailFlag。
Status CheckOutDegreeVertexExists(AMGraph* AMG, VertexIndexType VertexIndex, MyHashTable* VisitedHashTable, SqQueue* VertexLateQueue, WeightType* MinWeight)
{
    JudgeAllNullPointer(AMG);
    JudgeAllNullPointer(VisitedHashTable);

    VertexIndexType i;
    VertexIndexType OutDegree       = AMG->OutdegreeArray[VertexIndex];
    WeightType      PreVertexWeight = 0;//上一个节点的权值

    if (OutDegree == 0)
    {
        LogFormat(Error,"Internal Logic Error, VertexIndex(%d) OutDegree(0).\n",VertexIndex);
        return FailFlag;
    }
    
    HashTabElemType HashValue;

    for (i = 0; i < AMG->CurVertexNum; i++)//出度为复数的情况
    {
        if (AMG->ArcArray[VertexIndex][i] != MAX_INT_TYPE_NUM)
        {
            if (SearchHashTable(VisitedHashTable,&i,&HashValue) == SuccessFlag)
            {
                ReadSqQueue(VertexLateQueue,i,&PreVertexWeight);
                if (OutDegree == AMG->OutdegreeArray[VertexIndex])//给MinWeight赋予初值
                {
                    *MinWeight = PreVertexWeight - AMG->ArcArray[VertexIndex][i];
                }
                else
                {
                    *MinWeight = MY_MIN(*MinWeight,PreVertexWeight - AMG->ArcArray[VertexIndex][i]);
                }
                OutDegree--;
            }
            else
            {
                return FailFlag;
            }
        }
        if (OutDegree == 0)//说明所有出度点全部被找到,下面的顶点不需要再扫描,跳出循环。
        {
            break;
        }
    }
    
    return SuccessFlag;
}

10、ComputeCriticalPath

Status ComputeCriticalPath(CriticalPathSt* CP,AMGraph* AMG, VertexIndexType StartVertexIndex)
{
    JudgeAllNullPointer(CP);
    JudgeAllNullPointer(AMG);

    if (CheckCriticalPathAmgIllegal(AMG, StartVertexIndex) == FailFlag)
    {
        return FailFlag;
    }

    ComputeCriticalPathEvent(CP, AMG, StartVertexIndex);
    ComputeCriticalPathActivity(CP, AMG);

    LogFormat(Debug, "%s\n", "Compute Critical Path OK.");

    return SuccessFlag;
}

11、ComputeCriticalPathActivity

Status ComputeCriticalPathActivity(CriticalPathSt* CP,AMGraph* AMG)
{
    JudgeAllNullPointer(CP);
    JudgeAllNullPointer(AMG);

    VertexIndexType i;
    VertexIndexType j;
    WeightType      VertexEarlyWeight;
    WeightType      VertexLateWeight;
    WeightType      CriticalPathWeight;

    for (i = 0; i < AMG->CurVertexNum; i++)
    {
        for (j = 0; j < AMG->CurVertexNum; j++)
        {
            if (AMG->ArcArray[i][j] != MAX_INT_TYPE_NUM)
            {
                EnterSqQueue(CP->Activity->ArcStartVertexQueue,&i);
                EnterSqQueue(CP->Activity->ArcEndVertexQueue,&j);

                ReadSqQueue(CP->Event->VertexEarlyQueue,i,&VertexEarlyWeight);   
                EnterSqQueue(CP->Activity->ArcEarlyQueue,&VertexEarlyWeight);

                ReadSqQueue(CP->Event->VertexLateQueue,j,&VertexLateWeight);
                VertexLateWeight = VertexLateWeight - AMG->ArcArray[i][j];
                EnterSqQueue(CP->Activity->ArcLateQueue,&VertexLateWeight);

                CriticalPathWeight = VertexEarlyWeight - VertexLateWeight;
                EnterSqQueue(CP->Activity->CriticalPathQueue,&CriticalPathWeight);
            }
        }
    }
    
    LogFormat(Debug, "%s\n", "Compute Critical Path Activity OK.");

    return SuccessFlag;
}

12、ComputeCriticalPathEvent

Status ComputeCriticalPathEvent(CriticalPathSt* CP,AMGraph* AMG, VertexIndexType StartVertexIndex)
{
    JudgeAllNullPointer(CP);
    JudgeAllNullPointer(AMG);
    
    VertexIndexType InitVal          = CRITICAL_PATH_INIT_VAL;
    VertexIndexType j;
    VertexIndexType NextVertexIndex  = StartVertexIndex;//下一个需要访问的顶点行
    MyHashTable*    VisitedHashTable = NULL;
    WeightType      TmpWeight        = 0;               //下一个需要访问的顶点的权值
    WeightType      TmpAddWeight     = 0;               //临时权值和
    SqStack*        VisitedStack     = NULL;

    InitSqStack(&VisitedStack,INT_TYPE_FLAG);

    //1、处理事件最早发生
    //初始化事件队列
    for ( j = 0; j < AMG->CurVertexNum; j++)
    {
        EnterSqQueue(CP->Event->VertexEarlyQueue,&InitVal);
        EnterSqQueue(CP->Event->VertexLateQueue,&InitVal);
    }
    
    j = 0;
    UpdateSqQueue(CP->Event->VertexEarlyQueue,StartVertexIndex,&j);
    
    //初始化访问数组
    InitHashTable(&VisitedHashTable, AMG->CurVertexNum, INT_TYPE_FLAG);
    InsertHashTable(&StartVertexIndex, VisitedHashTable);
    PushSqStack(VisitedStack,&StartVertexIndex);

    // PrintfSqQueue(CP->Event->VertexEarlyQueue);
    // PrintfSqStack(VisitedStack);
    // PrintfHashTable(VisitedHashTable,Debug);
    while (VisitedHashTable->TotalDataNum != AMG->CurVertexNum)//所有节点访问一遍,退出循环
    {
        PopSqStack(VisitedStack,&NextVertexIndex);
        ReadSqQueue(CP->Event->VertexEarlyQueue,NextVertexIndex,&TmpWeight);
        for (j = 0; j < AMG->CurVertexNum; j++)//横向扫描AMG
        {
            if (AMG->ArcArray[NextVertexIndex][j] != MAX_INT_TYPE_NUM )//不等于无穷大,说明一定有入度。
            {
                if (AMG->InduityArray[j] == 1)//入度为1的情况
                {
                    InsertHashTable(&j, VisitedHashTable);
                    PushSqStack(VisitedStack,&j);
                    TmpAddWeight   = AMG->ArcArray[NextVertexIndex][j] + TmpWeight;
                    UpdateSqQueue(CP->Event->VertexEarlyQueue,j,&TmpAddWeight);
                }
                else if (CheckInduityVertexExists(AMG, j, VisitedHashTable, CP->Event->VertexEarlyQueue, &TmpAddWeight) == SuccessFlag)
                {
                    InsertHashTable(&j, VisitedHashTable);
                    PushSqStack(VisitedStack,&j);
                    UpdateSqQueue(CP->Event->VertexEarlyQueue,j,&TmpAddWeight);
                }
                // PrintfSqQueue(CP->Event->VertexEarlyQueue);
                // PrintfSqStack(VisitedStack);
                // PrintfHashTable(VisitedHashTable,Debug);
            }
        }
    }

    //清理访问栈和哈希表
    ClearSqStack(VisitedStack);
    ClearHashTable(VisitedHashTable);
    
    //2、处理事件最晚发生
    //和上面时间最早发生的区别是,处理事件最晚是纵向扫描,看顶点的出度,且是从汇点算到起点,倒着算。

    //初始化
    for ( j = 0; j < AMG->CurVertexNum; j++)
    {
        if (AMG->OutdegreeArray[j] == 0)//取汇点索引值。
        {
            InitVal = j;
            break;
        }
    }
    InsertHashTable(&InitVal, VisitedHashTable);
    PushSqStack(VisitedStack,&InitVal);
    ReadSqQueue(CP->Event->VertexEarlyQueue,InitVal,&TmpWeight); //读出事件最早发生的汇点权值。
    UpdateSqQueue(CP->Event->VertexLateQueue,InitVal,&TmpWeight);//更新事件最晚发生的汇点权值。

    // PrintfSqQueue(CP->Event->VertexLateQueue);
    // PrintfSqStack(VisitedStack);
    // PrintfHashTable(VisitedHashTable,Debug);
    while (VisitedHashTable->TotalDataNum != AMG->CurVertexNum)//所有节点访问一遍,退出循环
    {
        PopSqStack(VisitedStack,&NextVertexIndex);
        ReadSqQueue(CP->Event->VertexLateQueue,NextVertexIndex,&TmpWeight);
        for (j = 0; j < AMG->CurVertexNum; j++)//纵向扫描AMG
        {
            if (AMG->ArcArray[j][NextVertexIndex] != MAX_INT_TYPE_NUM )//不等于无穷大,说明一定有出度。
            {
                if (AMG->OutdegreeArray[j] == 1)//出度为1的情况
                {
                    InsertHashTable(&j, VisitedHashTable);
                    PushSqStack(VisitedStack,&j);
                    TmpAddWeight = TmpWeight - AMG->ArcArray[j][NextVertexIndex];
                    UpdateSqQueue(CP->Event->VertexLateQueue,j,&TmpAddWeight);
                }
                else if (CheckOutDegreeVertexExists(AMG, j, VisitedHashTable, CP->Event->VertexLateQueue, &TmpAddWeight) == SuccessFlag)
                {
                    InsertHashTable(&j, VisitedHashTable);
                    PushSqStack(VisitedStack,&j);
                    UpdateSqQueue(CP->Event->VertexLateQueue,j,&TmpAddWeight);
                }
                // PrintfSqQueue(CP->Event->VertexLateQueue);
                // PrintfSqStack(VisitedStack);
                // PrintfHashTable(VisitedHashTable,Debug);
            }
        }
    }
    
    DestroyHashTable(&VisitedHashTable);
    DestroyStack(&VisitedStack);

    LogFormat(Debug, "%s\n", "Compute Critical Path Event OK.");

    return SuccessFlag;
}

十、Linux环境编译测试

[gbase@czg2 Graph]$ make
gcc -Wall -Wextra -O3 Graph.c MinimumSpanningTree.c ShortestPath.c TopologicalOrder.c CriticalPath.c main.c -o TestGraph -I /opt/Developer/ComputerLanguageStudy/C/DataStructureTestSrc/Log/ -I /opt/Developer/ComputerLanguageStudy/C/DataStructureTestSrc/PublicFunction/ -I /opt/Developer/ComputerLanguageStudy/C/DataStructureTestSrc/PublicFunction/HashTable/include/ -I /opt/Developer/ComputerLanguageStudy/C/DataStructureTestSrc/PublicFunction/SqQueue/ -I /opt/Developer/ComputerLanguageStudy/C/DataStructureTestSrc/PublicFunction/SqStack/ -L /opt/Developer/ComputerLanguageStudy/C/DataStructureTestSrc/PublicFunction/Make/Libs/ -lPublicFunction -lLog -lMyHashTable -lSqStack -lSqQueue

[gbase@czg2 Graph]$ ./TestGraph 
2023-8-23 16:5:57--[ Debug ]--Create Net Data                    : OK
2023-8-23 16:5:57--[ Debug ]--Create Net Use AMGraph             : OK
2023-8-23 16:5:57--[ Debug ]--Printf AMGraph                     :
VertexArray    : [0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ]
ArcArray       :
0  : [32767 ,6     ,4     ,5     ,32767 ,32767 ,32767 ,32767 ,32767 ]
1  : [32767 ,32767 ,32767 ,32767 ,1     ,32767 ,32767 ,32767 ,32767 ]
2  : [32767 ,32767 ,32767 ,32767 ,1     ,32767 ,32767 ,32767 ,32767 ]
3  : [32767 ,32767 ,32767 ,32767 ,32767 ,2     ,32767 ,32767 ,32767 ]
4  : [32767 ,32767 ,32767 ,32767 ,32767 ,32767 ,9     ,7     ,32767 ]
5  : [32767 ,32767 ,32767 ,32767 ,32767 ,32767 ,32767 ,4     ,32767 ]
6  : [32767 ,32767 ,32767 ,32767 ,32767 ,32767 ,32767 ,32767 ,2     ]
7  : [32767 ,32767 ,32767 ,32767 ,32767 ,32767 ,32767 ,32767 ,4     ]
8  : [32767 ,32767 ,32767 ,32767 ,32767 ,32767 ,32767 ,32767 ,32767 ]
InduityArray   : [0 ,1 ,1 ,1 ,2 ,1 ,1 ,2 ,2 ]
OutdegreeArray : [3 ,1 ,1 ,1 ,2 ,1 ,1 ,1 ,0 ]
CurVertexNum   : 9
CurArcNum      : 11
2023-8-23 16:5:57--[ Debug ]--Init SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Init SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Init Critical Path Event St OK.
2023-8-23 16:5:57--[ Debug ]--Init SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Init SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Init SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Init SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Init SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Init Critical Path Activity St OK.
2023-8-23 16:5:57--[ Debug ]--Init Critical Path St OK.
2023-8-23 16:5:57--[ Debug ]--StartVertexIndex : 0 ,It Has Precursor Vertex, Check Adjacency Matrix Graph Fail
2023-8-23 16:5:57--[ Debug ]--(StartVertexIndex : 0,EndVertexIndex : 8), Check Adjacency Matrix Graph OK.
2023-8-23 16:5:57--[ Debug ]--Init SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Update SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Init Hash Table OK.
2023-8-23 16:5:57--[ Debug ]--Hash : (0,9,0).
2023-8-23 16:5:57--[ Debug ]--New Hash Table Node OK.
2023-8-23 16:5:57--[ Debug ]--Insert Hash Table OK.
2023-8-23 16:5:57--[ Debug ]--Push SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Judge SqStack Not Empty
2023-8-23 16:5:57--[ Debug ]--Pop SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Hash : (1,9,1).
2023-8-23 16:5:57--[ Debug ]--New Hash Table Node OK.
2023-8-23 16:5:57--[ Debug ]--Insert Hash Table OK.
2023-8-23 16:5:57--[ Debug ]--Push SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Update SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Hash : (2,9,2).
2023-8-23 16:5:57--[ Debug ]--New Hash Table Node OK.
2023-8-23 16:5:57--[ Debug ]--Insert Hash Table OK.
2023-8-23 16:5:57--[ Debug ]--Push SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Update SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Hash : (3,9,3).
2023-8-23 16:5:57--[ Debug ]--New Hash Table Node OK.
2023-8-23 16:5:57--[ Debug ]--Insert Hash Table OK.
2023-8-23 16:5:57--[ Debug ]--Push SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Update SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Judge SqStack Not Empty
2023-8-23 16:5:57--[ Debug ]--Pop SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Hash : (5,9,5).
2023-8-23 16:5:57--[ Debug ]--New Hash Table Node OK.
2023-8-23 16:5:57--[ Debug ]--Insert Hash Table OK.
2023-8-23 16:5:57--[ Debug ]--Push SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Update SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Judge SqStack Not Empty
2023-8-23 16:5:57--[ Debug ]--Pop SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Hash : (4,9,4).
2023-8-23 16:5:57--[ Debug ]--Search Hash Table Fail, HashValue : 4.
2023-8-23 16:5:57--[ Debug ]--Judge SqStack Not Empty
2023-8-23 16:5:57--[ Debug ]--Pop SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Hash : (1,9,1).
2023-8-23 16:5:57--[ Debug ]--Search Hash Table OK, HashValue : 1.
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Hash : (2,9,2).
2023-8-23 16:5:57--[ Debug ]--Search Hash Table OK, HashValue : 2.
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Hash : (4,9,4).
2023-8-23 16:5:57--[ Debug ]--New Hash Table Node OK.
2023-8-23 16:5:57--[ Debug ]--Insert Hash Table OK.
2023-8-23 16:5:57--[ Debug ]--Push SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Update SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Judge SqStack Not Empty
2023-8-23 16:5:57--[ Debug ]--Pop SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Hash : (6,9,6).
2023-8-23 16:5:57--[ Debug ]--New Hash Table Node OK.
2023-8-23 16:5:57--[ Debug ]--Insert Hash Table OK.
2023-8-23 16:5:57--[ Debug ]--Push SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Update SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Hash : (4,9,4).
2023-8-23 16:5:57--[ Debug ]--Search Hash Table OK, HashValue : 4.
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Hash : (5,9,5).
2023-8-23 16:5:57--[ Debug ]--Search Hash Table OK, HashValue : 5.
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Hash : (7,9,7).
2023-8-23 16:5:57--[ Debug ]--New Hash Table Node OK.
2023-8-23 16:5:57--[ Debug ]--Insert Hash Table OK.
2023-8-23 16:5:57--[ Debug ]--Push SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Update SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Judge SqStack Not Empty
2023-8-23 16:5:57--[ Debug ]--Pop SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Hash : (6,9,6).
2023-8-23 16:5:57--[ Debug ]--Search Hash Table OK, HashValue : 6.
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Hash : (7,9,7).
2023-8-23 16:5:57--[ Debug ]--Search Hash Table OK, HashValue : 7.
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Hash : (8,9,8).
2023-8-23 16:5:57--[ Debug ]--New Hash Table Node OK.
2023-8-23 16:5:57--[ Debug ]--Insert Hash Table OK.
2023-8-23 16:5:57--[ Debug ]--Push SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Update SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Clear SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Clear Hash Table OK.
2023-8-23 16:5:57--[ Debug ]--Hash : (8,9,8).
2023-8-23 16:5:57--[ Debug ]--New Hash Table Node OK.
2023-8-23 16:5:57--[ Debug ]--Insert Hash Table OK.
2023-8-23 16:5:57--[ Debug ]--Push SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Update SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Judge SqStack Not Empty
2023-8-23 16:5:57--[ Debug ]--Pop SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Hash : (6,9,6).
2023-8-23 16:5:57--[ Debug ]--New Hash Table Node OK.
2023-8-23 16:5:57--[ Debug ]--Insert Hash Table OK.
2023-8-23 16:5:57--[ Debug ]--Push SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Update SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Hash : (7,9,7).
2023-8-23 16:5:57--[ Debug ]--New Hash Table Node OK.
2023-8-23 16:5:57--[ Debug ]--Insert Hash Table OK.
2023-8-23 16:5:57--[ Debug ]--Push SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Update SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Judge SqStack Not Empty
2023-8-23 16:5:57--[ Debug ]--Pop SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Hash : (6,9,6).
2023-8-23 16:5:57--[ Debug ]--Search Hash Table OK, HashValue : 6.
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Hash : (7,9,7).
2023-8-23 16:5:57--[ Debug ]--Search Hash Table OK, HashValue : 7.
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Hash : (4,9,4).
2023-8-23 16:5:57--[ Debug ]--New Hash Table Node OK.
2023-8-23 16:5:57--[ Debug ]--Insert Hash Table OK.
2023-8-23 16:5:57--[ Debug ]--Push SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Update SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Hash : (5,9,5).
2023-8-23 16:5:57--[ Debug ]--New Hash Table Node OK.
2023-8-23 16:5:57--[ Debug ]--Insert Hash Table OK.
2023-8-23 16:5:57--[ Debug ]--Push SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Update SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Judge SqStack Not Empty
2023-8-23 16:5:57--[ Debug ]--Pop SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Hash : (3,9,3).
2023-8-23 16:5:57--[ Debug ]--New Hash Table Node OK.
2023-8-23 16:5:57--[ Debug ]--Insert Hash Table OK.
2023-8-23 16:5:57--[ Debug ]--Push SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Update SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Judge SqStack Not Empty
2023-8-23 16:5:57--[ Debug ]--Pop SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Hash : (1,9,1).
2023-8-23 16:5:57--[ Debug ]--Search Hash Table Fail, HashValue : 1.
2023-8-23 16:5:57--[ Debug ]--Judge SqStack Not Empty
2023-8-23 16:5:57--[ Debug ]--Pop SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Hash : (1,9,1).
2023-8-23 16:5:57--[ Debug ]--New Hash Table Node OK.
2023-8-23 16:5:57--[ Debug ]--Insert Hash Table OK.
2023-8-23 16:5:57--[ Debug ]--Push SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Update SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Hash : (2,9,2).
2023-8-23 16:5:57--[ Debug ]--New Hash Table Node OK.
2023-8-23 16:5:57--[ Debug ]--Insert Hash Table OK.
2023-8-23 16:5:57--[ Debug ]--Push SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Update SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Judge SqStack Not Empty
2023-8-23 16:5:57--[ Debug ]--Pop SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Hash : (1,9,1).
2023-8-23 16:5:57--[ Debug ]--Search Hash Table OK, HashValue : 1.
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Hash : (2,9,2).
2023-8-23 16:5:57--[ Debug ]--Search Hash Table OK, HashValue : 2.
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Hash : (3,9,3).
2023-8-23 16:5:57--[ Debug ]--Search Hash Table OK, HashValue : 3.
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Hash : (0,9,0).
2023-8-23 16:5:57--[ Debug ]--New Hash Table Node OK.
2023-8-23 16:5:57--[ Debug ]--Insert Hash Table OK.
2023-8-23 16:5:57--[ Debug ]--Push SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Update SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Clear Hash Table OK.
2023-8-23 16:5:57--[ Debug ]--Destroy Hash Table OK.
2023-8-23 16:5:57--[ Debug ]--Destroy SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Compute Critical Path Event OK.
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Read  SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Enter SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Compute Critical Path Activity OK.
2023-8-23 16:5:57--[ Debug ]--Compute Critical Path OK.
2023-8-23 16:5:57--[ Debug ]--SqQueue Data   :
Data           : [ 0 ,6 ,4 ,5 ,7 ,7 ,16 ,14 ,18 ]
FrontIndex     : 0
RearIndex      : 0
SqQueueLen     : 9
SqQueueMaxLen  : 9
Flag           : INT_TYPE_FLAG
2023-8-23 16:5:57--[ Debug ]--SqQueue Data   :
Data           : [ 0 ,6 ,6 ,8 ,7 ,10 ,16 ,14 ,18 ]
FrontIndex     : 0
RearIndex      : 0
SqQueueLen     : 9
SqQueueMaxLen  : 9
Flag           : INT_TYPE_FLAG
2023-8-23 16:5:57--[ Debug ]--SqQueue Data   :
Data           : [ 0 ,0 ,0 ,1 ,2 ,3 ,4 ,4 ,5 ,6 ,7 ]
FrontIndex     : 0
RearIndex      : 0
SqQueueLen     : 11
SqQueueMaxLen  : 11
Flag           : INT_TYPE_FLAG
2023-8-23 16:5:57--[ Debug ]--SqQueue Data   :
Data           : [ 1 ,2 ,3 ,4 ,4 ,5 ,6 ,7 ,7 ,8 ,8 ]
FrontIndex     : 0
RearIndex      : 0
SqQueueLen     : 11
SqQueueMaxLen  : 11
Flag           : INT_TYPE_FLAG
2023-8-23 16:5:57--[ Debug ]--SqQueue Data   :
Data           : [ 0 ,0 ,0 ,6 ,4 ,5 ,7 ,7 ,7 ,16 ,14 ]
FrontIndex     : 0
RearIndex      : 0
SqQueueLen     : 11
SqQueueMaxLen  : 11
Flag           : INT_TYPE_FLAG
2023-8-23 16:5:57--[ Debug ]--SqQueue Data   :
Data           : [ 0 ,2 ,3 ,6 ,6 ,8 ,7 ,7 ,10 ,16 ,14 ]
FrontIndex     : 0
RearIndex      : 0
SqQueueLen     : 11
SqQueueMaxLen  : 11
Flag           : INT_TYPE_FLAG
2023-8-23 16:5:57--[ Debug ]--SqQueue Data   :
Data           : [ 0 ,-2 ,-3 ,0 ,-2 ,-3 ,0 ,0 ,-3 ,0 ,0 ]
FrontIndex     : 0
RearIndex      : 0
SqQueueLen     : 11
SqQueueMaxLen  : 11
Flag           : INT_TYPE_FLAG
2023-8-23 16:5:57--[ Debug ]--Destroy SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Destroy SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Destroy Critical Path Event St OK.
2023-8-23 16:5:57--[ Debug ]--Destroy SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Destroy SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Destroy SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Destroy SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Destroy SqQueue OK
2023-8-23 16:5:57--[ Debug ]--Destroy Critical Path Activity St OK.
2023-8-23 16:5:57--[ Debug ]--Destroy Critical Path St OK.
2023-8-23 16:5:57--[ Debug ]--Destroy SqStack OK.
2023-8-23 16:5:57--[ Debug ]--Destroy StAccessPath OK.
2023-8-23 16:5:57--[ Debug ]--Destroy StAccessPath OK.
2023-8-23 16:5:57--[ Debug ]--Destroy StAccessPath OK.
2023-8-23 16:5:57--[ Debug ]--Destroy StAccessPath OK.
2023-8-23 16:5:57--[ Debug ]--Destroy StAccessPath OK.
2023-8-23 16:5:57--[ Debug ]--Destroy StAccessPath OK.
2023-8-23 16:5:57--[ Debug ]--Destroy StAccessPath OK.
2023-8-23 16:5:57--[ Debug ]--Destroy StAccessPath OK.
2023-8-23 16:5:57--[ Debug ]--Destroy StDijkstraAccees OK.
2023-8-23 16:5:57--[ Debug ]--Destroy Net Data                   : OK
2023-8-23 16:5:57--[ Debug ]--Destroy Net Use AMGraph            : OK
2023-8-23 16:5:57--[ Debug ]--Destroy Net Use AGraph             : OK

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/917796.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

字节跳动 Git 的正确使用姿势与最佳实践

版本控制Git 黑马&尚硅谷 Git的前世今生 方向介绍 为什么要学习Git 1.0 Git是什么 1.1 版本控制 1.1.1 本地版本控制 1.1.2 集中版本控制 1.1.3 分布式版本控制 我们已经把三个不同的版本控制系统介绍完了&#xff0c;Git 作为分布式版本控制工具&#xff0c; 虽然目前来讲…

Python Web开发 OAuth2.0 简介

我们经常看到或者用到一些可以使用微博、微信、支付宝等账号登录的应用&#xff0c;还有一些微博助手、微信公众号助手、客户端之类的东西&#xff0c;这些是怎么做的呢&#xff0c;背后的原理是什么呢&#xff1f;为什么公众号配置起来那么繁琐呢&#xff1f;什么是 access to…

数据标注工具:功能及评估

从垃圾邮件过滤到个性化的聊天机器人体验&#xff0c;人工智能创新正日益成为我们日常生活中的一部分。大多数还没有部署人工智能的公司&#xff0c;都在考虑如何在其内部和外部流程中采用人工智能和机器学习工具。 在接触人工智能和机器学习前&#xff0c;很多人都不知道&…

空间换时间-五秒出解:从900ms到5ms的幕后优化大揭秘!

作者&#xff1a;麦客奥德彪 探索数据操作的效率是软件开发中的一项重要任务。开发中遇到了Java中的ArrayList和removeAll方法&#xff0c;意外发现当面对大量数据时&#xff0c;其执行效率可能会让人瞠目结舌&#xff0c;高达900毫秒以上&#xff01;然而&#xff0c;通过一系…

景区气象站

景区气象站是通过各种传感器实现气象数据采集&#xff0c;这些传感器就是它的核心部件&#xff0c;拥有抗风、防腐、耐尘的优势&#xff0c;可以在各种复杂气象条件下稳定工作&#xff0c;为工作人员提供高精度的气象数据。搭配气象通讯主机&#xff0c;对传感器采集的数据进行…

2023-08-23 LeetCode每日一题(统计点对的数目)

2023-08-23每日一题 一、题目编号 1782. 统计点对的数目二、题目链接 点击跳转到题目位置 三、题目描述 给你一个无向图&#xff0c;无向图由整数 n &#xff0c;表示图中节点的数目&#xff0c;和 edges 组成&#xff0c;其中 edges[i] [ui, vi] 表示 ui 和 vi 之间有一…

echarts 之 科技感进度条

1.图片展示 2.代码实现 /* ng qty 进度条 */ <template><div class"ngqty-progress"><div class"ngqty-info"><span>X4</span><span>50%</span></div><div :id"barNgQtyProgress index" c…

ubuntu18.04复现yolo v8之CUDA与pytorch版本问题以及多CUDA版本安装及切换

最近在复现yolo v8的程序&#xff0c;特记录一下过程 环境&#xff1a;ubuntu18.04ros melodic 小知识&#xff1a;GPU并行计算能力高于CPU—B站UP主说的 Ubuntu可以安装多个版本的CUDA。如果某个程序的Pyorch需要不同版本的CUDA&#xff0c;不必删除之前的CUDA&#xff0c;…

wazuh环境配置

目录 一、wazuh的安装 1.1官方仓库安装 1.2虚拟机OVA安装 1.2.1 然后执行下面命令 1.2.2 这里还要下载脚本和config.yml配置文件&#xff0c;用来生成证书​编辑 1.2.3然后编辑config.yml文件&#xff0c;将下面的三个IP地址改为一样的 1.2.4运行./wazuh-certs-tool.sh以…

Linux Ubuntu系统安装OpenVPN服务

OpenVPN Ubuntu/Linux 服务端安装 官方文档&#xff1a;https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage 介绍 嘿&#xff0c;今天我们要探讨的话题是OpenVPN——那个让你在互联网上以安全又私密的方式冲浪的神奇工具。 首先&#xff0c;你可能会问&#xff…

机器学习模型的可解释性算法汇总

模型可解释性汇总 现有许多机器学习模型,尤其是深度学习模型,虽然他们的预测效果很好,但不具备很强的解释性,难以解释模型内部是如何作出决策的。这确实会带来很多问题: 信任度问题。如果一个模型无法解释自身,人们很难 100%信任它。这对于一些重要应用场景如医疗诊断来说尤其重…

【安全】原型链污染 - Code-Breaking 2018 Thejs

目录 准备工作 环境搭建 加载项目 复现 代码审计 payload 总结 准备工作 环境搭建 Nodejs BurpSuite 加载项目 项目链接 ① 下载好了cmd切进去 ② 安装这个项目 可以检查一下 ③运行并监听 可以看到已经在3000端口启动了 复现 代码审计 const fs require(fs) cons…

整理mongodb文档:聚合管道

个人博客 整理mongodb文档:聚合管道 个人博客&#xff0c;求关注&#xff0c;电脑版看体验更加&#xff0c;如果不够清晰&#xff0c;请指出来&#xff0c;谢谢 文章概叙 文章主要通过几个常用的聚合表达式来介绍聚合管道的使用&#xff0c;以及从索引的角度来介绍聚合管道…

使用lambda表达式提取共用代码使其更加简洁

1、在开发预下单接口访问并发问题出现需要加锁代码如下 RLock lock redissonClient.getLock(String.format(appointmentKey, activityId, studentId));try {boolean tryLock lock.tryLock(10, 20, TimeUnit.SECONDS);if (tryLock) {AppointmentMallOrderInfoDTO appointmentM…

【修改MAC地址工具】-TMAC

本文介绍修改MAC地址的神器小工具Technitium-MAC-Address-Changer 1. 下载地址 地址1&#xff1a; https://technitium.com/tmac/ 地址2&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1-jtwQ936gtepVWXKo_qwfg 提取码&#xff1a;2n1s 2. 安装 直接双击就可以安装…

iTwinCapture中文版原ContextCapture安装包以及安装教程

iTwinCapture软件安装教程 一、获取软件 中文安装包评论区或后台回复iTwinCapture 在App Store或Google Play搜索软件名称"iTwin Capture",下载安装软件。 您也可以在Bentley官网下载对应的iTwin Capture版本。 二、软件安装 点击下载后的安装包,根据提示完成安装…

NR SDAP

在NR系统的核心网中,业务不再以EPS承载的形式下发到接入网,而是以QoS flow的形式下发到接入网。在核心网引入QoS flow之后,可以提供比EPS承载更好的QoS粒度,从而更好地对IP数据流进行管理。一个QoS flow由一个或多干IP data stream聚合而成。因此,在核心网中,IP flow映射…

git 统计(命令)

查询某人某个时刻提交了多少代码 added 添加代码 removed 删除代码 total 总代码 git log --author刘俊秦 --since2023-08-01 00:00:00 --until2023-08-23 23:00:00 --prettytformat: --numstat | awk { add $1; subs $2; loc $1 - $2 } END { printf "added lines: %s…

JW0818近电报警芯片

JW0818 市电感应报警电路适用于电业人员和电信行业施工人员的安全保护用品–近电预警器 报警电路。 特别注意芯片引脚6&#xff0c;输出信号是方波&#xff0c;而不是高低电平&#xff1b;在产品开发过程遇到这个坑。

C++中的抽象类和接口

面向对象中的抽象概念 在进行面向对象分析时&#xff0c;会发现一些抽象的概念&#xff01; 图形的面积如何计算&#xff1f; 什么是抽象类&#xff1f; 在现实中需要知道具体的图像类型才能求面积&#xff0c;所以对概念上的 "图形" 求面积是没有意义的&#xff…