转载文章
原文链接: dzone 翻译: ImportNew.com - 陈 秋林
译文链接: http://www.importnew.com/9719.html
[ 转载请保留原文出处、译者和译文链接。]
感谢作者的奉献精神;
介绍
假设我们有一组任务要完成,并且有些任务要在其它任务完成之后才能开始,所以我们必须非常小心这些任务的执行顺序。
如果这些任务的执行顺序足够简单的话,我们可以用链表来存储它们,这是一个很好的方案,让我们可以准确知道任务的执行顺序。问题是有时候不同任务之间的关系是非常复杂的,有些任务依赖于两个甚至更多的任务,或者反过来很多任务依赖自己。
因此我们不能通过链表或者树的数据结构来对这个问题建模。对这类问题唯一合理的数据结构就是图。我们需要哪种图呢?很显然,我们需要有向图来描述这种关系,而且是不能循环的有向图,我们称之为有向无环图。
要通过拓扑排序对图形进行排序,这些图必须是不能循环和有向的。
为什么这些图不能循环呢?答案很明显,如果图形是循环的,我们无法知道哪个任务该优先执行,也不可能对任务进行排序。
现在我们一要做的是对图中的每个节点排序,组成一条条边(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);
}
}
|