欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

动态内存分配算法(详解加代码)

程序员文章站 2022-05-02 14:03:45
...

动态内存分配主要有四种算法:
(1) 首次适应算法:每次都从低地址开始查找,找到第一个能满足大小的空闲分区。
(2) 循环首次适应算法:首次适应算法每次要从头找,增加了查找的开销,也可能在低地
址上产生难以利用的小碎片。循环首次适应算法从上一次结束的位置开始查找。
(3) 最佳适应算法:为了保证当“大进程”到来时能有连续的大片空间,可以尽可能的多
留下大片空闲区,即,优先使用更小的空闲区。
(4) 最坏适应算法:为了解决最佳适应算法的问题——留下太多难以利用的小碎片。可以优先使用最大的连续空闲区。

各自的优缺点:
(1) 首次适应算法:综合看性能最好。算法开销小,回收分区后一般不需要对空闲分区队列重新排序。
(2) 循环首次适应算法:不用每次都从低地址的小分区开始检索。算法开销小,但会使高地址的大分区也被用完。
(3) 最佳适应算法:会有更多的大分区被保留下来,更能满足大进程的需求。但会产生很多太小的、难以利用的碎片;算法开销大,回收分区后可能需要对空闲分区队列重新排序。
(4) 最坏适应算法:可以减少难以利用的小碎片。但大分区容易被利用完,不利于大进程,算法开销大。

这里我们说说代码的构造:
你要有一个分区块的类,用来保存分区块的起始地址,大小,和状态

class Zone{                      //分区结点信息类
        private int size;           //分区大小
        private int head;           //分区起始位置
        private boolean isFree;    //空闲状态

        public Zone(int head, int size) {
            this.head = head;
            this.size = size;
            this.isFree = true;
        }
    }

之外嵌套我们的主类:

private int size;                     //总内存大小
    private LinkedList<Zone> zones;   //保存内存分区
    private int pointer;             //上次分配的空闲区位置

代码逻辑图:
动态内存分配算法(详解加代码)1、我们先初始化内存的大小
2、进入主界面

  1. 输入作业
  2. 回收内存
  3. 显示分区

3、输入作业后,先输入大小,然后选择分配的算法

  1. 首次适应算法
  2. 循环首次算法
  3. 最佳适应算法
  4. 最坏适应算法

下面是源码阶段:

package Experiment;

import java.util.LinkedList;
import java.util.Scanner;
public class Test2{
    private int size;                 //内存大小
    private LinkedList<Zone> zones;   //内存分区
    private int pointer;             //上次分配的空闲区位置

    class Zone{                      //分区结点信息类
        private int size;           //分区大小
        private int head;           //分区起始位置
        private boolean isFree;    //空闲状态

        public Zone(int head, int size) {
            this.head = head;
            this.size = size;
            this.isFree = true;
        }
    }
    public Test2(){
        this.size = 400;
        this.pointer = 0;
        this.zones = new LinkedList<>();
        zones.add(new Zone(0, size));
    }
    public Test2(int size) {
        this.size = size;
        this.pointer = 0;
        this.zones = new LinkedList<>();
        zones.add(new Zone(0, size));
    }

    private void doAlloc(int size, int location, Zone tmp) {
        //size 作业大小 location 内存位置 tmp可用空闲区
        Zone newHome = new Zone(tmp.head + size, tmp.size - size);
        //产生一个新空闲区;
        zones.add(location + 1, newHome);//插入新节点
        tmp.size = size;
        tmp.isFree = false;
        System.out.println("成功分配 " + size + "KB 内存!");
    }
    public void FirstFit(int size){
        //将point赋值为零 从头开始找
        for (pointer = 0; pointer < zones.size(); pointer++){
            Zone tmp = zones.get(pointer);
            //找到可用分区(空闲且大小足够)
            if (tmp.isFree && (tmp.size > size)){
                doAlloc(size, pointer, tmp);
                return;
            }
        }
        //遍历结束后未找到可用分区, 则内存分配失败
        System.out.println("无可用内存空间!");
    }
    public void NextFit(int size){
        //直接获得上次point位置,开始遍历分区链表
        Zone tmp = zones.get(pointer);
        if (tmp.isFree && (tmp.size > size)){
            doAlloc(size, pointer, tmp);
            return;//查看当前块是否符合要求
        }
        int len = zones.size();
        int i = (pointer + 1) % len; //循环的过程,
        for (; i != pointer; i = (i+1) % len){
            tmp = zones.get(i);
            //找到可用分区(空闲且大小足够)
            if (tmp.isFree && (tmp.size > size)){
                doAlloc(size, i, tmp);
                return;
            }
        }
        //遍历结束后未找到可用分区, 则内存分配失败
        System.out.println("无可用内存空间!");
    }
    public void BestFit(int size){
        //最佳适应算法
        int flag = -1;//记录位置
        int min = this.size;//初始化为内存长度,用来保存最小碎片大小;
        for (pointer = 0; pointer < zones.size(); pointer++){//从头开始遍历;
            Zone tmp = zones.get(pointer);
            if (tmp.isFree && (tmp.size > size)){//找到合适条件的内存区
                if (min > tmp.size - size){//如果产生的碎片小于上一个最小值,就重新标记最小值位置
                    min = tmp.size - size;
                    flag = pointer;//更新位置
                }
            }
        }
        if (flag == -1){//初始值,没找到
            System.out.println("无可用内存空间!");
        }else {
            doAlloc(size, flag, zones.get(flag));
        }
    }
    public void WorstFit(int size){//最坏适应算法
        int flag = -1;
        int max = 0;//类似于最佳算法
        for (pointer = 0; pointer < zones.size(); pointer++){
            Zone tmp = zones.get(pointer);
            if (tmp.isFree && (tmp.size > size)){
                if (max < tmp.size - size){
                    max = tmp.size - size;
                    flag = pointer;
                }
            }
        }
        if (flag == -1){
            System.out.println("无可用内存空间!");
        }else {
            doAlloc(size, flag, zones.get(flag));
        }
    }
    public void collection(int id){//id 指定要回收的分区号
        if (id >= zones.size()){
            System.out.println("无此分区编号!");
            return;
        }
        Zone tmp = zones.get(id);//找到分区块
        int size = tmp.size;//取出大小
        if (tmp.isFree) {//判断状态
            System.out.println("指定分区未被分配, 无需回收");
            return;
        }

        //检查前面是否空闲,是则合并
        if (id > 0 && zones.get(id - 1).isFree){
            Zone fronKuer = zones.get(id - 1);
            fronKuer.size += tmp.size;
            zones.remove(id);
            id--;
        }

        //检查后面是否空闲,是则合并
        if (id < zones.size() - 1 && zones.get(id + 1).isFree){
            Zone nextKuer = zones.get(id + 1);//取到下一个区块
            tmp.size += nextKuer.size;
            zones.remove(nextKuer);
        }
        zones.get(id).isFree = true;
        System.out.println("内存回收成功!, 本次回收了 " + size + "KB 空间!");
    }
    public void showZones(){//展示内存分区状况
        System.out.println("***************************************");
        System.out.println("*分区编号 分区始址 分区大小 空闲状态  *");
        for (int i = 0; i < zones.size(); i++){
            Zone tmp = zones.get(i);
            System.out.println("*  "+i + "          "
                                   + tmp.head + "      "
                                   + tmp.size + "      "
                                   + tmp.isFree+"    *");
        }
        System.out.println("****************************************");
    }

}

这是我们算法的类,下面是调用的类

package Experiment;

import java.util.Scanner;

public class Main {
    public static Test2 user; //声明一个用户;
    public static void Init(){ //初始化内存大小
        System.out.println("请输入内存大小(如果输入0,则按默认400分配)");
        Scanner scanner=new Scanner(System.in);
        int choose=scanner.nextInt();
        if(choose==0){
            user=new Test2();
        }else {
            user=new Test2(choose);
        }
    }
    public static void mainMenu(){
        System.out.println("***********************");
        System.out.println("*     1.输入作业      *");
        System.out.println("*     2.回收内存块    *");
        System.out.println("*     3.展示分区情况  *");
        System.out.println("*     4.退出系统      *");
        System.out.println("***********************");
        System.out.println("请输入你要进行的操作:");
    }
    public static void algorithmMenu(int size){
        System.out.println("请选择分配算法:");
        System.out.println("1.首次适应算法");
        System.out.println("2.循环首次算法");
        System.out.println("3.最佳适应算法");
        System.out.println("4.最坏适应算法");
        Scanner in = new Scanner(System.in);
        int choose = in.nextInt();
        switch (choose){
            case 1:
                user.FirstFit(size);break;
            case 2:
                user.NextFit(size);break;
            case 3:
                user.BestFit(size);break;
            case 4:
                user.WorstFit(size);break;
            default:
                System.out.println("请重新选择!");
        }
    }
    public static void main(String[] args) {
        Init();     //初始化内存条大小
        Scanner sc=new Scanner(System.in);

        while(true){
            mainMenu();             //主菜单
            int choice=sc.nextInt();
            if(choice == 4){
               return;
            }else if(choice == 1){
               System.out.println("请输入你要插入的内存块大小");
               int length=sc.nextInt();
               algorithmMenu(length);
            }else if(choice==2){
                System.out.println("请输入你要回收的分区号码");
                int ID=sc.nextInt();
                user.collection(ID);
            }else if(choice == 3){
                user.showZones();
            }else{
               System.out.println("输入错误,请检查");
           }
        }
    }

}

注释写得很清楚,有什么不懂可以私信。

相关标签: Java SE