Python实现动态分区算法(首次适应算法、循环首次适应算法、最佳适应算法、最坏适应算法)

一、算法思想

  1. 分区的个数和大小不是固定不变的,而是可变的,随装入的作业动态划分,且不会产生内部碎片。
  2. 外部碎片:就是一些比较小的空闲分区,由于分区的大小太小,不能容纳作业,因而不能被分配,造成分区的浪费。
  3. 首次适应算法:在分配内存时,从链首开始顺序查找,直到找到一个大小能满足要求的空闲分区为止。然后按照作业的大小,从该分区中划出一块内存空间分配给请求者,余下的空闲分区仍保存在空闲链中。
  4. 循环首次适应算法:循环首次适应算法,不再是每次都要从链首开始查找,而是从上次找到的空闲分区的下一个空闲分区开始查找,直到找到一个能满足要求的空闲分区,然后划出一块与请求的大小相等的内存空间分配给作业。
  5. 最佳适应算法:首先将所有的空闲分区按其容量以从小到大的顺序,排成一个空闲分区链。这样,第一次找到的、能满足要求的空闲分区,必然是最佳的。
  6. 最坏适应算法:将虽有的空闲分区按容量以从大到小的顺序,排成一个空闲分区链。查找时,只看第一个分区是否能满足要求,同时避免了产生过多难以利用的碎片。

二、分区内存回收思想:

分区分配中的内存回收有四种情况:回收区与插入点的前一个空闲分区相邻接,此时应将回收区与插入点的前一个空闲分区合并,不必为回收分区分配新表项,而只需修改其前一分区的大小;回收区与插入点的后一个空闲分区相邻接,此时应将回收区与插入点的后一个空闲分区合并,需将回收区的起始地址作为新空闲区的起始地址,分区大小为两者之和;回收区同时与插入点的前、后两个分区邻接,此时将三个分区合并,使用插入点前的空闲分区的表项和起始地址,将插入点后的空闲分区表项取消,分区大小为三者之和;回收区既不与前分区相邻接,也不与后分区相邻接,此时应为回收区单独新建一个表项,填写回收区起始地址和大小。

三、代码实现:

1.text_fit.py:提示用户选择即将进行的操作,提示用户选择操作:1表示添加分区;2表示打印输出现有的分区表;3选择要使用的动态分区分配算法;4表示将某作业的空间回收;0表示退出该系统。

import text_fit_function

while(True):
    text_fit_function.show_menu()
    action_str = input("请输入要选择的操作:")
    # 123 表示对分区表的各种操作
    if action_str in ["1", "2", "3", "4"]:
        if action_str == "1":
            # 新增一个分区
            text_fit_function.new_area()
            continue
        elif action_str == "2":
            # 打印分区表
            text_fit_function.show_area()
            continue
        elif action_str == '3':
            text_fit_function.function_choice_menu()
            function_choice = input("请输入要选择的动态分区分配算法:")
            if function_choice in ["1", "2", "3", "4"]:
                if function_choice == "1":
                    # 使用的是 首次适应算法
                    text_fit_function.function_FF()
                    continue
                elif function_choice == '2':
                    # 使用的是 循环首次适应算法
                    text_fit_function.function_NF()
                    continue
                elif function_choice == '3':
                    # 使用 最佳适应算法
                    text_fit_function.function_BF()
                    continue
                else:
                    # 使用 最坏适应算法
                    text_fit_function.function_WF()
                    continue    
        elif action_str == '4':
            # 将某进程的内存回收
            text_fit_function.free_area()
            continue
        else:
            print("输入错误,请重新输入")
            continue

    # 0 表示退出系统
    elif action_str == "0":
        print("已退出,欢迎下次使用!!")
        break

    else:
        print("输入错误,请重新输入!")

2.text_fit_function.py文件中书写各函数,包括系统菜单show_menu()、添加分区函数new_area()、输出分区表函数show_area()、首次适应算法function_FF()、循环首次适应算法function_NF()、最佳适应算法function_BF()、最坏适应算法function_WF()、回收某进程算法free_area()。

# 数据结构的确定 : 每个分区的信息用字典存储,再用列表存储各个分区
area_list = []

def show_menu():
    # 功能菜单:
    print("~" * 50)
    print("欢迎使用【动态分区分配算法展示系统】 [V 1.0]")
    print("1. 新增分区;\n2. 打印所有分区;\n3. 选择使用的动态分区分配算法;\n4. 分区回收\n0. 退出系统;")
    print("~" * 50)


def new_area():
    # 新增一个分区
    print("-" * 50)
    # > 1 提示用户输入分区相关信息
    while True:
        area_size = input("请输入分区大小:")
        if area_size != "":
            break
        else:
            print("输入不能为空!")
    while True:
        area_begin = input("请输入分区起始地址:")
        if area_begin != "":
            break
        else:
            print("输入不能为空!")
    while True:
        area_status = input("请输入分区状态(0表示空闲 1表示已分配):")
        if area_status == '0' or area_status == '1':
            break
        else:
            print("输入不合法!")
    # 2. 将分区信息放入一个字典
    area_dict = {
        'area_size': area_size,
        'area_begin': area_begin,
        'area_status': area_status,
    }
    # 3. 将字典存储到area_list 列表中
    area_list.append(area_dict)
    # 4. 提示用户增加分区信息成功!
    print("新建分区信息成功!")


def show_area():
    # 显示分区表
    print("-" * 50)
    # 将 area_list 按起始地址进行排序
    area_list.sort(reverse=False, key=lambda s: (s["area_begin"]))

    if len(area_list) == 0:
        print("当前没有任何分区,请先添加新的分区!")
        return
    # > 1 将area_list中的所有分区输出,遍历list即可
    # 打印数据
    index = 0 # 序号
    print("空闲分区表:")
    print("-" * 50)
    for i in range(len(area_list)):
        if area_list[i]['area_status'] == '0':
            index+= 1
            print("分区号:%s   分区大小:%s   分区起始地址:%s    分区状态:%s" % 
                (index, area_list[i]["area_size"], area_list[i]["area_begin"], area_list[i]["area_status"]))
    print("-" * 50)
    index = 0

    print("分区使用表:")
    print("-" * 50)
    for i in range(len(area_list)):
        if area_list[i]['area_status'] == '1':
            index += 1
            print("作业号:%s   分区大小:%s   分区起始地址:%s    分区状态:%s" % 
                (index, area_list[i]["area_size"], area_list[i]["area_begin"], area_list[i]["area_status"]))
    print("-" * 50)


def function_choice_menu():
    # 选择动态分区算法
    print("~" * 50)
    print("【动态分区分配算法展示系统】 [V 1.0]\n")
    print("请选择要使用的动态分区分配算法:\n1. 首次适应算法;\n2. 循环首次适应算法;\n3. 最佳适应算法;\n4. 最坏适应算法;\n")
    print("~" * 50)


def function_FF():
    # 首次适应算法
    input_list = map(int, input("输入新作业的大小(中间用空格分隔):").split()) # 输入多个作业的大小

    for new_size in input_list: # 拿到每一个输入的作业 new_size
        for item in area_list:
            if item["area_status"] == '0':  # 某分区是否空闲
                if new_size <= int(item["area_size"]):  # 分区大小是否可以容纳新作业
                    new_area = {  # 在分区表中新建一个,标识为已分配的分区
                        'area_name': "作业",
                        'area_size': new_size,
                        'area_begin': item["area_begin"],
                        'area_status': '1',
                    }
                    # 对被使用的空白分区进行操作
                    item["area_size"] = str(int(item["area_size"]) - new_size)
                    item["area_begin"] = str(int(item["area_begin"]) + new_size)
                    area_list.append(new_area) # 将新分区加入分区表
                    item = 0 # 表示下一次依旧从第一项开始查找
                    break
    show_area()
    

def function_NF():
    # 循环首次适应算法
    input_list = map(int, input("输入新作业的大小(中间用空格分隔):").split()) # 输入多个作业的大小
    
    for new_size in input_list: # 拿到每一个输入的作业 new_size
        for item in area_list:
            if item["area_status"] == '0':  # 某分区是否空闲
                if new_size <= int(item["area_size"]):  # 分区大小是否可以容纳新作业
                    new_area = {  # 在分区表中新建一个,标识为已分配的分区
                        'area_name': "作业",
                        'area_size': new_size,
                        'area_begin': item["area_begin"],
                        'area_status': '1',
                    }
                    # 对被使用的空白分区进行操作
                    item["area_size"] = str(int(item["area_size"]) - new_size)
                    item["area_begin"] = str(int(item["area_begin"]) + new_size)
                    area_list.append(new_area) # 将新分区加入分区表

                    break
    show_area()


def function_BF(): # 最佳适应算法
    input_list = map(int, input("输入新作业的大小(中间用空格分隔):").split()) # 输入多个作业的大小

    for new_size in input_list: # 拿到每一个输入的作业 new_size
        # 使用冒泡排序,将空闲分区按容量 从小到大排序
        for i in range( len(area_list) - 1 ): # 将空闲分区重新排序
            for j in range( len(area_list) - i - 1 ):
                if area_list[j]["area_status"] == '0' and area_list[j + 1]["area_status"] == '0':
                    if area_list[j]["area_size"] > area_list[j + 1]["area_size"]:
                        area_list[j], area_list[j + 1] = area_list[j + 1], area_list[j]

        for item in area_list:
            if item["area_status"] == '0':  # 某分区是否空闲
                if new_size <= int(item["area_size"]):  # 分区大小是否可以容纳新作业
                    new_area = {  # 在分区表中新建一个,标识为已分配的分区
                        'area_name': "作业",
                        'area_size': new_size,
                        'area_begin': item["area_begin"],
                        'area_status': '1',
                    }
                    # 对被使用的空白分区进行操作
                    item["area_size"] = str(int(item["area_size"]) - new_size)
                    item["area_begin"] = str(int(item["area_begin"]) + new_size)
                    area_list.append(new_area) # 将新分区加入分区表
                    item = 0 # 表示下一次依旧从第一项开始查找
                    break
    show_area()


def function_WF(): # 最坏适应算法
    input_list = map(int, input("输入新作业的大小(中间用空格分隔):").split()) # 输入多个作业的大小

    for new_size in input_list: # 拿到每一个输入的作业 new_size
        # 使用冒泡排序,将空闲分区按容量 从小到大排序
        for i in range( len(area_list) - 1 ): # 将空闲分区重新排序
            for j in range( len(area_list) - i - 1 ):
                if area_list[j]["area_status"] == '0' and area_list[j + 1]["area_status"] == '0':
                    if area_list[j]["area_size"] < area_list[j + 1]["area_size"]:
                        area_list[j], area_list[j + 1] = area_list[j + 1], area_list[j]

        for item in area_list:
            if item["area_status"] == '0':  # 某分区是否空闲
                if new_size <= int(item["area_size"]):  # 分区大小是否可以容纳新作业
                    new_area = {  # 在分区表中新建一个,标识为已分配的分区
                        'area_name': "作业",
                        'area_size': new_size,
                        'area_begin': item["area_begin"],
                        'area_status': '1',
                    }
                    # 对被使用的空白分区进行操作
                    item["area_size"] = str(int(item["area_size"]) - new_size)
                    item["area_begin"] = str(int(item["area_begin"]) + new_size)
                    area_list.append(new_area) # 将新分区加入分区表
                    item = 0 # 表示下一次依旧从第一项开始查找
                    break
    show_area()


def free_area():
    # 释放作业
    index = 0 # 表示作业的序号
    choice = int(input("即将释放内存的作业号:"))
    if choice == '':
        print("输入不能为空")
        return 

    for i in range(len(area_list)): # 找到某个要释放的作业
        if area_list[i]["area_status"] == '1':
            index += 1
            if choice == index: # 找到那个作业了,序号就是 i
                area_list[i]["area_status"] = '0'
                if i == 0: # 这个作业位于分区列表的首位,前面没有其他分区
                    if area_list[i + 1]["area_status"] == '0': # 判断是否与后面的可用分区相连
                        area_list[i]["area_size"] =  int(area_list[i]["area_size"]) + int(area_list[i + 1]["area_size"])
                        area_list.remove(area_list[i + 1])
                        break
                    else: # 位于首位,且不与后面的空表分区相连
                        break
                else: # 该分区序号不为 1
                    if area_list[i - 1]["area_status"] == '0':
                        # 不是第一个表目且与前一个可用表区相邻,将两者合并为一个空闲分区
                        area_list[i - 1]["area_size"] =  int(area_list[i - 1]["area_size"]) + int(area_list[i]["area_size"])
                        area_list.remove(area_list[i]) # 将这个已释放的作业区删除
                    
                        if i < len(area_list): # 分区已经与前面相连 判断是否是最后一个分区
                            if area_list[i]["area_status"] == '0': # 判断是否与后面的可用分区相连
                                area_list[i - 1]["area_size"] =  int(area_list[i - 1]["area_size"]) + int(area_list[i]["area_size"])
                                area_list.remove(area_list[i])
                                break
                            else: # 后面连接不上
                                break
                        else: # 这是最后一个分区,不存在后面的分区
                            break
                    else: # 前者不是空白分区  不与前面的可用表区相连
                        if i < len(area_list) - 1: # 不是最后一个分区
                            if area_list[i + 1]["area_status"] == '0': # 判断是否与后面的可用分区相连
                                area_list[i]["area_size"] =  int(area_list[i]["area_size"]) + int(area_list[i + 1]["area_size"])
                                area_list.remove(area_list[i + 1])
                                break
                            else: # 后面不是空闲分区
                                break
                        else: # 这是最后一个分区,不存在i+1个分区
                            break
        
    show_area()

四、源码下载:

百度网盘:百度网盘

提取码:iuxp

可能有误,欢迎指出。

你可能感兴趣的:(Python的使用,算法,python)