假设我们有一组任务要完成,并且有些任务要在其它任务完成之后才能开始,所以我们必须非常小心这些任务的执行顺序。
如果这些任务的执行顺序足够简单的话,我们可以用链表来存储它们,这是一个很好的方案,让我们可以准确知道任务的执行顺序。问题是有时候不同任务之间的关系是非常复杂的,有些任务依赖于两个甚至更多的任务,或者反过来很多任务依赖自己。
因此我们不能通过链表或者树的数据结构来对这个问题建模。对这类问题唯一合理的数据结构就是图。我们需要哪种图呢?很显然,我们需要有向图来描述这种关系,而且是不能循环的有向图,我们称之为有向无环图。
要通过拓扑排序对图形进行排序,这些图必须是不能循环和有向的。
为什么这些图不能循环呢?答案很明显,如果图形是循环的,我们无法知道哪个任务该优先执行,也不可能对任务进行排序。
现在我们一要做的是对图中的每个节点排序,组成一条条边(u,v),u在v之前执行。然后我们就可以得到所有任务的线性顺序,并按这种顺序执行任务就一切都OK了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
class G { protected $_g = array( array( 0 , 1 , 1 , 0 , 0 , 0 , 0 ), array( 0 , 0 , 0 , 1 , 0 , 0 , 0 ), array( 0 , 0 , 0 , 0 , 1 , 0 , 0 ), array( 0 , 0 , 0 , 0 , 1 , 0 , 0 ), array( 0 , 0 , 0 , 0 , 0 , 0 , 1 ), array( 0 , 0 , 0 , 0 , 0 , 0 , 1 ), array( 0 , 0 , 0 , 0 , 0 , 0 , 0 ), ); protected $_list = array(); protected $_ts = array(); protected $_len = null ; public function __construct() { $ this ->_len = count($ this ->_g); // 找到没有依赖节点的节点 $sum = 0 ; for ($i = 0 ; $i < $ this ->_len; $i++) { for ($j = 0 ; $j < $ this ->_len; $j++) { $sum += $ this ->_g[$j][$i]; } if (!$sum) { //把它放入_list中 array_push($ this ->_list, $i); } $sum = 0 ; } } public function topologicalSort() { while ($ this ->_list) { $t = array_shift($ this ->_list); array_push($ this ->_ts, $t); foreach ($ this ->_g[$t] as $key => $vertex) { if ($vertex == 1 ) { $ this ->_g[$t][$key] = 0 ; $sum = 0 ; for ($i = 0 ; $i < $ this ->_len; $i++) { $sum += $ this ->_g[$i][$key]; } if (!$sum) { array_push($ this ->_list, $key); } } $sum = 0 ; } } print_r($ this ->_ts); } } |
原文地址:http://www.cnblogs.com/chenying99/p/3836811.html