问题的描述:
带有期限的作业排序要解决的是操作系统中单机、无资源约束且每个作业可在等量的时间内完成的作业调度问题。把这个问题形式化描述为:
①要在一台机器上处理n个作业,每个作业可以在单位时间内完成
②每个作业i都有一个期限值di,di>0
③当作业在它规定的期限值前完成,就可以获得的效益pi,pi>0
问题求解的目标是:问题的可行解是这n个作业的一个子集合J。J中的每个作业都能在各自的截止期限前完成后,产生一个作业效益之和
。我们的目标就是找到一个子集J,J中的每个作业都能在各自的截止期限前完成,并且使得作业效益值的和最大。这个作业的一个子集合J就是所求的最优解。
带有期限的作业排序的一个例子:
例3.2 n=4,(p1,p2,p3,p4)=(100,10,15,20),(d1,d2,d3,d4)=(2,1,2,1)。这个问题的最优解为第7个,所允许的处理顺序是:先处理作业4,在处理作业1。在时间0开始处理作业4而在时间2完成对作业1的处理。 可行解 处理顺序 效益值
1 {1} 1 100
2 {2} 2 10
3 {3} 3 15
4 {4} 4 20
5 {1,2} 2,1 110
6 {1,3} 1,3或3,1 115
7 {1,4} 4,1 120
8 {2,3} 2,3 25
9 {3,4} 4,3 35
带有期限的作业排序贪心算法度量标准的选取:
我们的目标是作业效益值的和最大,因此首先把目标函数作为度量标准。首先把作业按照它们的效益值作一个非增次序的排序。以例3.2来说,作业根据效益值排序后为作业1、4、3、2。求解时首先把作业1计入J,由于作业1的期限值是2,所以J={1}是一个可行解。接下来计入作业4。由于作业4的期限值是1而作业1的期限值是2,可以先完成作业4后再完成作业1,所以J={1, 4}是一个可行的解。然后考虑作业3,但是作业3的期限值是2,计入J后就没有办法保证J中的每一个作业都在期限值内完成,因此计入作业3后不能构成一个可行解。同理计入2后也不能构成一个可行解。由分析可知,把目标函数作为度量标准能够得到问题的最优解。
作业排序算法的概略描述:
算法3.3
procedure GREEDY-JOB(D,J,n)
//作业按照p1≥p2≥…≥pn的次序输入,它们的期限值D(i) ≥1, 1≤i≤n, n≥1。J是在它们的截止期限前完成的作业集合。
J←{1}
For i←2 to n do
If J∪{i}的所有作业都能在它们的截止期限前完成
Then J←J∪{i}
Endif
Repeat
End GREEDY-JOB
在这个概略的算法中需要解决的关键是如何判断作业i并入J后仍然能够保证J中的所有作业都能够在它们的截止期限前完成。在做这个判断之前先看两个定理。
定理3.2:算法3.3所描述的贪心方法对于作业排序问题总是得到一个最优解。
定理3.3:设J是k个作业的集合,б=i1i2…ik是J中作业的一种排列,它使得di1≤di2≤…≤dik。J是一个可行解,当且仅当J中的作业可以按照б的次序而又不违反任何一个期限的情况来处理。
这两个定理的证明留给读者自行证明。可以参看(《计算机算法基础》(第二版)——余祥宣 崔国华 邹海明著)。
可定义一个数组J,它存放纳入集合J中的作业。假设已经处理了i-1个作业,并且有k个作业已经计入数组J中,分别是J(1), J(2), …, J(k),且有D(J(1))≤D(J(2)) ≤…≤D(J(k))。注意D(J(r))(1≤r≤k)表示计入数组J中的作业r(也就是J(r)表示的那个作业)的期限值。因为已经处理了i-1个作业,所以现在要考虑的是作业i是否可以并入到J中形成一个可行解。根据定理3.3,要判断作业i是否可以并入到J中形成一个可行解,就要看能否在数组J中找到一个位置,使i插入后仍然能保证J中的所有k+1个作业都在它们的期限之前完成,而且有D(J(1))≤D(J(2))≤…≤D(J(k+1)),即在数组J中插入后,它的期限值要比在它前一个位置的那个作业的期限值大而比在它后一个位置的那个作业的期限值小。现在的关键问题变成了如何能够为作业i找到这样一个位置。于是接下来的任务是分析找这个位置的判断标准。
因为这里考虑的作业都能够在单位时间内完成,所以判断i是否可以纳入J中作为一个可行解的标准有以下三个:
①作业i可能的存储位置可以这样进行:将已经计入J中的作业从第k个作业开始,把作业i的期限值逐个与作业k、作业k-1、作业k-2、…、作业1做比较,直到找到一个位置q,这个位置q上的作业的期限值小于等与作业i的期限值,而位置q+1上的作业的期限值大于i的期限值,形式化描述位D(J(q))≤D(J(i))< D(J(q+1))。所以把位置q+1到位置k上的作业都后移一个位置,把位置q+1腾出后就是作业i可能插入的位置。做这样的处理后能够使D(J(1))≤D(J(2))≤…≤D(J(k+1))得到满足。因此第一个判断标准就是在数组J中找到第一个期限值小于作业i的期限值的那个作业的所在位置q。
②找到作业i的插入位置并把它插入数组J后,还要考虑i并入后是否能够保证已经在J中的所有作业能在期限值之内完成。由于作业i插入位置前的所有作业的位置都没有动过,因此它们肯定能在期限值规定时间内完成。这里主要考虑的是作业i插入位置后的那些移动位置的作业。这些作业往后移动一个位置,这就意味着轮到它们的执行时间往后推了一个单位时间。一个可行解应该是这些作业的执行时间往后推一个单位时间后,还能在它们各自的期限值之间完成。因此如果一个作业r的限期值等于它在数组中的所在位置,即D(J(r))=r,这样的作业是不能往后推的。因为如果后推后,它的新位置是r+1,而这个作业的期限值D(J(r))=r,后移后就不能使这个作业在有效期内得到完成。
综上两条,判断一个作业i应该的插入位置,应该从已经在J中作业的最后一个作业k开始往第1个作业扫描,用一个变量r表示正在扫描的那个作业。用D(J(r))>D(i) and D(J(r))≠r判断,如果条件不成立则表明要么找到了第一个期限值小于作业i的期限值的作业,要么发现了某个作业的D(J(r))=r它不保证J中的所有作业在它们的截止期限前完成的判断分析:
能后移;如果条件成立则继续往J中前面的作业扫描。当条件不成立的时候,就可以确定出某个位置r。
③通过以上两步的处理判断得到的位置r,就是确定的作业i的插入位置。但是找到这个位置并不意味着作业i能够插入形成可行解,因为如果作业i的期限值小于这个位置值r,即D(i)
带有期限和效益的单位时间的作业排序贪心算法及说明:
由以上的分析可以写出以下的关于带有期限和效益的单位时间的作业排序的贪心算法如下: procedure JS(D, J,n, k)
1 integer D(0:n), J(0:n), i, k, n, r //数组D存放n个作业的期限值,这些存放在数组中的作业是按照它们产生的效益值非递减排序过的;数组J存放纳入成为可行解的作业;k代表已经处理放入J中的作业数量;i指示当前正在处理的作业;r表示扫描数组J时的当前扫描位置
2 D(0)←j(0)←0 //引入虚构作业0,是为了便于处理将作业插入位置1
3 K←1; J(1) ←1 //初始化时,把第1个作业放入J中,则当前已经处理放入J中的作业数量k为1 4 for i←2 to n do //第1个作业已经处理了,因此需要处理的作业是第2个到第n个
5 r←k // 从已经纳入J中的最后一个位置k的作业开始往前扫描
6 while D(J(r))>D(i) and D(J(r))≠r do //while循环判断寻找当前处理的作业i适合的插入位置 7 r←r-1
8 repeat
9 if D(J(r))≤D(i) and D(i)>r then //判断如果作业放在位置r后一个位置是否能够在期限值规定内完成
10 for i←k to r+1 by –1 do //用for循环把从位置r+1到位置k上的作业都往后移动一个位置。把r+1的位置空出来存放作业i
11 J(i+1) ←J(i)
12 repeat
13 J(r+1) ←i; k←k+1//把作业i放入r+1的位置上,总共处理放入J中的作业数目增加1 14 endif
15 repeat
end JS
算法分析:
对于JS,有两个测量复杂度的参数,即作业数n和包含在解中的作业数s。第6-8行的循环至多迭代k次,每次迭代的时间为O(1)。若第9行的条件为真,则执行10-13行。这些要求O(k-r)时间去插入作业i。因此,对于4-15行的循环,其每次迭代的总时间是O(k)。该循环共迭代n-1次。如果s是k的最终值,即s是最后所得解的作业数,则算法JS所需要的总时间是O(sn)。由于s≤n,因此JS的最坏情况时间是O(n)。这种情况在p1=d1=n-i+1时就会出现。进而可以证明最坏情况时间为H(n)。在计算空间方面,除了D所需要的空间外,为了存放J,还需要H(s)的空间量。
转载自:http://www.njliaohua.com/lhd_65c1f0hi9y3sk4u08kf5_1.html