首次适配,最佳适配,最差适配算法实现-java

首次适应算法:

首次适应算法从空闲分区表的第一个表目起查找该表,把最先能够满足要求的空闲区分配给作业,这种方法目的在于减少查找时间。为适应这种算法,空闲分区表(空闲区链)中的空闲分区要按地址由低到高进行排序。该算法优先使用低址部分空闲区,在低址空间造成许多小的空闲区,在高地址空间保留大的空闲区。

代码实现

import java.util.*;

public class FF {
    private static class Node {
        int id;    // 作业id,为-1代表空闲分区;大于0代表已分配
        int start; // 初始地址
        int size;  // 大小

        public String toString() {
            return String.format("[%4d, %4d, %4d]", id, start, size);
        }
    }

    private static final int SIZE = 4; // 定义碎片大小
    private static Scanner sc = new Scanner(System.in);

    // 返回分区链表
    private static List<Node> init() {
        List<Node> list = new ArrayList<>();
        Node node = new Node();

        // 初始化,为整个内存空间分配一个空闲节点
        node.id = -1;
        node.start = 0;
        System.out.print("请输入内存空间大小: ");
        node.size = sc.nextInt();
        list.add(node);

        return list;
    }

    // 为作业id在分区链表list中分配大小为size的内存
    private static boolean add(List<Node> list, int id, int size) {
        Node p = null;
        int i;

        // 找到第一个未分配且大于size的内存空间节点p,i为其下标
        for (i = 0; i < list.size(); i++) {
            p = list.get(i);
            if (p.id == -1 && p.size >= size)
                break;
        }

        if (i == list.size()) return false; // 不存在未分配且大于或等于size的内存空间节点,分配失败

        // 当原来节点的大小大于size+SIZE时需要创建一个新节点temp保留余下的分区,并插在p的后面
        if (p.size - size > SIZE) {
            Node temp = new Node();
            temp.id = -1;
            temp.start = p.start + size;
            temp.size = p.size - size;
            list.add(i + 1, temp);
        }
        // 将原来节点变成已分配的节点,当剩余空间大于SIZE时,该节点大小为size;当剩余空间小于或等于SIZE时,该节点大小不变,因为剩余大小已经不够再次分配任务;
        p.id = id;
        p.size = (p.size - size > SIZE ? size : p.size);

        return true;
    }

    // 回收作业id的内存,并合并相邻的空闲分区
    private static boolean del(List<Node> list, int id) {
        Node p = null;
        int i;

        // 找到作业id所在的节点p,i为其下标
        for (i = 0; i < list.size(); i++) {
            p = list.get(i);
            if (p.id == id) break;
        }
        if (i == list.size()) return false;//此作业id不存在

        p.id = -1; // 回收分区

        Node a, b;
        if (i != 0) { // 若第i-1个节点和第i个节点相邻,合并两个分区
            a = list.get(i - 1);
            b = list.get(i);
            if (a.id == -1 && b.id == -1 && a.start + a.size == b.start) {
                a.size += b.size;
                list.remove(i);
                i--;
            }
            // i--是因为可能存在合并后的节点可能与后一个节点相邻
        }
        if (i != list.size() - 1) { // 若第i个节点和第i+1个节点相邻,合并两个分区
            a = list.get(i);
            b = list.get(i + 1);
            if (a.id == -1 && b.id == -1 && a.start + a.size == b.start) {
                a.size += b.size;
                list.remove(i + 1);
            }
        }

        return true;
    }

    private static void show(List<Node> list) {
        System.out.println("已分配分区:");
        int i = 1;
        for (Node temp : list) {
            if (temp.id != -1) System.out.println("分区号:" + i + " 分配情况:" + temp);
            i++;
        }
        i = 1;
        System.out.println("未分配分区:");
        for (Node temp : list) {
            if (temp.id == -1) System.out.println("分区号:" + i + " 分配情况:" + temp);
            i++;
        }
//        System.out.println(list);
    }

    public static void main(String[] args) {
        List<Node> list = init();
        int id, size, op;
        while (true) {
            System.out.println("\n************************************************");
            System.out.println("   1: 为新作业分配内存        2: 撤销作业释放内存");
            System.out.println("   3: 查看FF算法内存分配      4: 退出");
            System.out.print("请输入操作: ");
            op = sc.nextInt();
            switch (op) {
                case 1:
                    System.out.print("请输入作业id和作业大小size: ");
                    id = sc.nextInt();
                    size = sc.nextInt();
                    if (add(list, id, size)) System.out.println("分配成功");
                    else System.out.println("分配失败");
                    break;
                case 2:
                    System.out.print("请输入需要撤销的作业id: ");
                    id = sc.nextInt();
                    if (del(list, id)) System.out.println("撤销成功");
                    else System.out.println("撤销失败,此作业id不存在");
                    break;
                case 3:
                    show(list);
                    break;
                case 4:
                    return;
            }
        }
    }
}

最佳适应和最差适应算法:

最佳适应算法(Best Fit):

它从全部空闲区中找出能满足作业要求的、且大小最小的空闲分区,这种方法能使碎片尽量小。为适应此算法,空闲分区表(空闲区链)中的空闲分区要按从小到大进行排序,自表头开始查找到第一个满足要求的自由分区分配。该算法保留大的空闲区,但造成许多小的空闲区。

 

 

最差适应算法(Worst Fit)

也称最差适配算法:

它从全部空闲区中找出能满足作业要求的、且大小最大的空闲分区,从而使链表中的结点大小趋于均匀,适用于请求分配的内存大小范围较窄的系统。为适应此算法,空闲分区表(空闲区链)中的空闲分区要按大小从大到小进行排序,自表头开始查找到第一个满足要求的自由分区分配。该算法保留小的空闲区,尽量减少小的碎片产生。

代码实现(其中将Integer.compare(this.size, node.size)中的两个参数互换位置即为WF(最差适应)算法)

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class BF {
    private static class Node implements Comparable {
        int id;    // 作业id,为-1代表空闲分区;大于0代表已分配
        int start; // 初始地址
        int size;  // 大小

        public String toString() {
            return String.format("[分区:%d, 起始地址:%d, 分区大小%d]", id, start, size);
        }

        @Override
        public int compareTo(Object o) {
            Node node = (Node) o;
            return Integer.compare(this.size, node.size);//升序,此处将compare中的参数颠倒顺序传入即可实现最差适应算法
        }
    }

    private static final int SIZE = 4;
    private static Scanner sc = new Scanner(System.in);

    //返回分区表
    public static List<Node> init() {
        List<Node> list = new ArrayList<>();
        System.out.println("请输入分区总大小:");
        Node node = new Node();
        node.size = sc.nextInt();
        node.start = 0;
        node.id = -1;
        list.add(node);
        return list;
    }

    //为作业分配分区
    public static boolean add(List<Node> list, int id, int size) {
        Node p = null;
        list.sort(Node::compareTo);
        //找到空闲分区最小且大于碎片大小的分区
        int i;
        for (i = 0; i < list.size(); i++) {
            p = list.get(i);
            if (p.size >= size && p.id == -1)
                break;
        }

        if (i == list.size())
            return false;

        // 当原来节点的大小大于size+SIZE时需要创建一个新节点temp保留余下的分区,并插在p的后面
        if (p.size - size > SIZE) {
            Node tNode = new Node();
            tNode.start = p.start + size;
            tNode.id = -1;
            tNode.size = p.size - size;
            list.add(i + 1, tNode);
        }

        //修改p中的值
        p.id = id;
        p.size = (p.size - size > SIZE ? size : p.size);

        return true;
    }

    //撤销作业释放分区
    public static boolean delete(List<Node> list, int id) {
        Node p = null;
        Node t = null;
        int i, j;
        for (i = 0; i < list.size(); i++) {
            p = list.get(i);
            if (p.id == id)
                break;
        }

        if (i == list.size())
            return false;//此作业id不存在

        p.id = -1;//回收作业

        //合并分区
        int count = 0;
        for (j = 0; j < list.size(); j++) {
            t = list.get(j);
            //合并p前面的分区
            if (t.start + t.size == p.start && t.id == -1) {
                p.start = t.start;
                p.size += t.size;
                list.remove(j);
                count++;
                if (count == 2)
                    break;
            }
            //合并p后面的分区
            if (p.start + p.size == t.start && t.id == -1) {
                p.size += t.size;
                list.remove(j);
                count++;
                if (count == 2)
                    break;
            }
        }
        return true;//撤销成功
    }

    private static void show(List<Node> list) {
        System.out.println("已分配分区:");
        for (Node t : list) {
            if (t.id != -1) {
                System.out.println("分配情况" + t);
            }
        }
        System.out.println("未分配分区:");
        for (Node t : list) {
            if (t.id == -1) {
                System.out.println("分配情况" + t);
            }
        }
    }

//    public static List<Node>

    public static void main(String[] args) {
        List<Node> list = init();
        int id, size, op;
        while (true) {
            System.out.println("\n************************************************");
            System.out.println("   1: 为新作业分配分区        2: 撤销作业释放内存");
            System.out.println("   3: 查看内存分区情况        4: 退出");
            System.out.print("请输入操作: ");
            op = sc.nextInt();
            switch (op) {
                case 1:
                    System.out.print("请输入作业id和作业大小size: ");
                    id = sc.nextInt();
                    size = sc.nextInt();
                    if (add(list, id, size)) System.out.println("分配成功");
                    else System.out.println("分配失败");
                    break;
                case 2:
                    System.out.print("请输入撤销的作业id: ");
                    id = sc.nextInt();
                    if (delete(list, id)) System.out.println("撤销成功");
                    else System.out.println("撤销失败,此作业id不存在");
                    break;
                case 3:
                    show(list);
                    break;
                case 4:
                    return;
            }
        }
    }
}

 

  • 5
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值