贪心法(作业调度问题)

这篇博客,主要是来记录一下作业调度问题这一算法。完整代码会放在本文最后。

作业调度问题总的来说还是贪心算法,给定某一贪心策略,处理机处理的时间最少自然最好。本次算法中,我所选用的贪心策略是处理时间高的作业优先。

1.问题的已知:

已知m台机器,n个作业以及各作业的处理时间ti(i=1,2,…,n)。

2.所求目标:

每台处理机处理的作业的序列。

3.算法步骤

输入:1.处理机个数m。2.作业个数n。3.依次按序号输入作业的处理时间。

输出:一个列表里面嵌套列表的数据结构,嵌套的列表分别为这m台处理机对应的处理作业的序列。

步骤1:初始化一个列表ISHTAR,并用for循环跟据处理机的个数往ISHTAR里面添加空列表(有几个处理机就添加几个空列表),ISHTAR列表存的就是各个处理机处理的作业的序列。

步骤2:初始化一个变量rin,用python内置函数sorted()将字典dict1按照作业运行时间(值)的大小从大到小排序,最后将排序完的数据赋值给rin。

步骤3:由于是按照最长处理时间优先的策略,所以排序完的字典rin在机器刚开始工作时可以直接按照机器的个数m将前m个作业放进去处理。即用for循环将排序后的前m个作业的各自的处理时间赋值给dict2里m个机器键值对里面的值里面。

步骤4:使用for循环用来循环遍历字典rin,将第m+1个作业放入当前处理时间最少的处理机中。(这个处理时间最少的处理机是先用内置函数min()找出当前处理时间最小的值minnum,然后再用for循环遍历dict2的项,当值等于minnum时,就返回该值对应的处理机序号。)之后再进行dict2里面对应序号的处理机对应的值的加操作(当前处理时间+分配的作业对应的处理时间)。

步骤5:输出列表ISHTAR,里面的每个嵌套的列表就是该m个处理机对应的处理作业的序列。

4.具体实现:

1.m和n为用户输入,分别用于指定处理机和作业的个数。初始化两个字典dict1和dict2,用for循环循环输入两个字典中每个键值对的值,dict1的值都默认赋值为0(赋值为0是表示每台处理机的初始处理作业的时间都为0),dict2的值为用户自己输入。字典的键就跟据两个字典的长度从1开始赋值。dict1的键表示处理机的编号,dict2的键表示作业的序号。

m = int(input('请输入处理机的台数:'))
n = int(input('请输入作业的个数:'))

dict1 = {}
dict2 = {}
for i in range(1, m + 1):
    dict2[i] = 0

for j in range(1, n + 1):
    dict1[j] = int(input('请输入'+str(j)+'号作业的处理时间:'))

2.初始化一个列表ISHTAR,然后跟据dict2的长度(处理机个数)用for循环给ISHTAR嵌套相应数量的列表,ISHTAR的作用就是为了后边结果的输出,ISHTAR里面嵌套的每个子列表就代表着每台处理机的处理作业的序列。

注意这里面list1=[],这句代码一定要放在for循环里面,如果放外面的话ISHTAR里面的所有子列表都会共用一个内存空间,即一个子列表改变,其他的子列表也会相应的改变。

ISHTAR = []

for i in range(0, len(dict2)):
    list1 = []
    ISHTAR.append(list1)

3.用sorted()函数将作业按照处理时间从大到小排序。(按照值将字典dict1里面的项按照从大到小排序)

rin = sorted(dict1.items(), key=lambda x: x[1], reverse=True)

将排序完的数据结构赋值给自定义变量rin。注意:此时rin的数据结构并不是字典,而是列表,且里面的数据,也是一个个元组。

4.因为rin为把所有作业按照处理时间从大到小排序的结果,所以在第一次放置作业到处理机上时,直接按照处理机的个数将相同数量的作业放入处理机即可。

所以这一步做的就是把rin中前m(m为处理机个数)个作业对应的时间赋值给字典dict2(处理机)的每一项的值。

同时,将rin前m项对应的作业序号添加到列表ISHTAR中的各个子列表中(表示每台处理机处理的作业序列)。

for i in range(1, len(dict2) + 1):
    dict2[i] = rin[i - 1][1]
    ISHTAR[i - 1].append(str(rin[i - 1][0]))

5.用循环将剩下的作业依次判断处理,将作业序号添加到对应的处理机上。

for i in range(len(dict2), len(dict1)):
    listmin=[]
    for j in range(1, m+1):
        listmin.append(dict2[j])
    minnum = min(listmin)
    for key, value in dict2.items():
        if value == minnum:
            dict2[key] = dict2[key] + rin[i][1]
            ISHTAR[key - 1].append(str(rin[i][0]))
            break

上述代码中,listmin为我初始化的一个列表,它的作用是和min()函数搭配,找出每分配作业后处理作业总时间最小的处理机,这样才能保证每次的将作业分配给处理机这一过程最优。minnum即为找到的处理总时间最小的处理机的处理时间,之后再用循环遍历字典dict2,跟据最小值找到对应的处理机序号(如果多个处理机有相同的最小处理时间,则只找第一个处理机),将作业的处理时间加到该处理机的总时间上,再将作业序号添加到对应的处理机处理作业序列中。

最后输出结果。

例:

贪心法(作业调度问题)_第1张图片

 最后输出的这个就是结果,表示:

处理机1的处理的作业序号有:6

处理机2的处理的作业序号有:8

处理机3的处理的作业序号有:5,3,4

处理机4的处理的作业序号有:7,1,2

       这个算法其实并不复杂,虽然并不简洁,但我认为我写的这个应该是比较好理解的。如果代码有问题,还是希望能够指出来。

完整代码如下:

m = int(input('请输入处理机的台数:'))
n = int(input('请输入作业的个数:'))

dict1 = {}
dict2 = {}
for i in range(1, m + 1):
    dict2[i] = 0

for j in range(1, n + 1):
    dict1[j] = int(input('请输入'+str(j)+'号作业的处理时间:'))

ISHTAR = []

for i in range(0, len(dict2)):
    list1 = []
    ISHTAR.append(list1)

rin = sorted(dict1.items(), key=lambda x: x[1], reverse=True)


for i in range(1, len(dict2) + 1):
    dict2[i] = rin[i - 1][1]
    ISHTAR[i - 1].append(str(rin[i - 1][0]))

for i in range(len(dict2), len(dict1)):
    listmin=[]
    for j in range(1, m+1):
        listmin.append(dict2[j])
    minnum = min(listmin)
    for key, value in dict2.items():
        if value == minnum:
            dict2[key] = dict2[key] + rin[i][1]
            ISHTAR[key - 1].append(str(rin[i][0]))
            break
print(ISHTAR)

你可能感兴趣的:(python,pycharm,贪心算法)