Ubuntu22.2下C语言编程实现,首次,最佳适应算法

news2025/7/23 23:48:48

参考目录:

  • 1.题目要求
  • 2.分析设计
  • 3.程序代码
  • 4.运行截图
  • 5.程序说明

1.题目要求

编写C语言程序,模拟实现首次/最佳/最坏适应算法(选择其中之一即可)的内存块分配和回收,要求每次分配和回收后显示出空闲分区和已分配分区的情况。假设初始状态下,可用的内存空间为640KB。
假设下列作业请求序列:
(1)作业1 申请130 KB (2)作业2 申请60 KB (3)作业3 申请100 KB
(4)作业2 释放60 KB (5)作业3 释放100 KB (6)作业1 释放130 KB
显示每次作业申请或释放后当前内存情况。

2.分析设计

根据题目,分析设计如下:
(1)程序初始需要提供用户选择方式。选择首次适应算法,还是最佳是适应算法,选择作业的回收,作业的展示,程序的退出能。
(2)当用户选择首次适应算法或者最佳适应算法,需要用户输入分配内存的大小。在输入大小时在根据算法的设计进行分配。
(3)当内存分配过后,如果分配成功就需要提示成功,如果失败则需要提示失败。
(4)内存回收需要用户输入回收作业的ID,根据作业的ID对内存进行回收。在回收时要分多种情况进行判断。
(5)作业展示,需要向用户展示,作业的ID,起始地址,内存大小,状态是已分配还是空闲。
(6)一个作业需要用到数据结构中的双向列表,用一个双向列表来表示节点。

3.程序代码

#include <stdio.h>
#include <stdlib.h>

struct area
{
  int id;             // 编号
  int addr_front;     //首地址
  int addr_end;      //结束地址
  int size;           //分区大小
  int flag;           //分配标志,0表示空闲,1表示占用
  struct area *front; //上一分区
  struct area *next;  //下一分区
};

typedef struct area partion;

partion *head = NULL; //分区队列头节点
int need;             //需求
int choice = 1;       //操作选项

partion *createPartion(int id, int addr_front, int size, int flag); //生成一个节点
void inputNeed();                                                   //输入需求量
void assign(partion *ptr, int need);                                //分配分区
void first_fit();                                                   //首次适应算法
void best_fit();                                                    //最佳适应算法
void showMemoryInfo();                                              //打印分区分配状况
void recovery();                                                    //分区回收
void changeIdValue(partion *ptr, int delta);                        //改变从ptr开始所有节点的id值

int main(void)
{
  head = createPartion(0, 0, 640, 0);
  while (choice != 0)
  {
    puts("-------------------\n请选择操作:\n1:首次适应;\n2:最佳适应;\n3:内存回收;\n4:展示详细信息;\n0:推出......\n-------------------");
    scanf("%d", &choice);
    switch (choice)
    {
    case 1:
      inputNeed();
      first_fit();
      break;
    case 2:
      inputNeed();
      best_fit();
      break;
    case 3:
      recovery();
      showMemoryInfo();
      break;
    case 4:
      showMemoryInfo();
      break;
    case 0:
      puts("byebye");
      break;
    default:
      break;
    }
  }

  return 0;
}

//创建一个节点
partion *createPartion(int id, int addr_front, int size, int flag)
{
  partion *p = (partion *)malloc(sizeof(partion));
  p->id = id;
  p->addr_front = addr_front;
  p->addr_end=addr_front+size-1;
  p->size = size;
  p->flag = flag;
  p->front = NULL;
  p->next = NULL;
  return p;
}

void inputNeed()
{
  printf("请输入需要的内存大小:");
  scanf("%d", &need);
}

void first_fit()
{
  partion *fit = NULL;
  partion *ptr = head;
  while (ptr != NULL)
  {
    if (ptr->size >= need && ptr->flag == 0)//如果是空闲并且大小大于则给予分配
    {
      fit = ptr;
      break;
    }
    ptr = ptr->next;
  }
  if (fit != NULL)
  {
    assign(fit, need);
    printf("内存分配成功,分配如下:\n");
    showMemoryInfo();
  }
  else
  {
    puts("抱歉,内存分配失败!");
    free(fit);
  }
}

void best_fit()
{
  partion *fit = NULL;
  partion *ptr = head;
  int flag = 0; //flag 表示是否找到可分配的分区
  while (ptr != NULL)
  {
    if (ptr->flag == 0 && ptr->size >= need)
    {
      if (flag == 0)
      {
        //只有遇到的第一个可分配分区会执行此操作
        fit = ptr;
        flag = 1;
      }
      else
      {
        //若遇到可分配且分区更小即更适合的则更新
        if (ptr->size < fit->size)
        {
          fit = ptr;
        }
      }
    }
    ptr = ptr->next;
  }
  //先处理没找到合适分区的情况
  if (flag == 0)
  {
    puts("抱歉,未找到合适的分区!");
    free(fit);
    return;
  }
  //找到则分配
  assign(fit, need);
  puts("内存分配成功,分配如下:\n!");
  showMemoryInfo();
}

void showMemoryInfo()
{
  partion *ptr = head;
  puts("\n\n---------------------------------------------");
  puts("总内存分配情况如下:");
  puts("---------------------------------------------");
  puts("序号ID****开始地址****结束地址****内存大小****状态****");
  while (ptr != NULL)
  {
    printf("%-12d%-12d%-12d%-12d",ptr->id,ptr->addr_front,ptr->addr_end,ptr->size);
   // printf("序号id:%21d%10c\n开始地址:%10d%10c\n", ptr->id, '|', ptr->addr_front, '|');
    //printf("结束地址:%10d%10c\n", ptr->addr_end, '|');
    //printf("内存大小:%11d%10c\n", ptr->size, '|');
    printf("%-12s\n", ptr->flag == 0 ? "空闲" : "已分配");
    puts("-----------------------------------------------------");
    ptr = ptr->next;
  }
  puts("---------------------------------------------\n\n");
}

void assign(partion *ptr, int need)
{

  if (need == ptr->size)//空闲的空间恰好等同需要的空间
  {
    ptr->flag = 1;
    return;
  }
  //空闲的空间大于需要的空间
  partion *assigned = createPartion(ptr->id, ptr->addr_front, need, 1);
  assigned->next = ptr;
  assigned->front = ptr->front;
  changeIdValue(ptr, 1);//把后面的节点的id值都增加1
  ptr->addr_front += need;
  ptr->size -= need;
  if (ptr->front != NULL)//空闲区的头不空,就在前一个节点后面添加分配的节点
  {
    ptr->front->next = assigned;
  }
  else//空闲节点前没有节点
  {
    head = assigned;
  }

  ptr->front = assigned;//空闲节点的头指向新分配的
}

void recovery()
{
  printf("请输入需要回收作业的ID号:");
  int id, flag = 0;
  scanf("%d", &id);
  partion *ptr = head;
  while (ptr != NULL)
  {
    if (id == ptr->id)
    {
      flag = 1;
      break;
    }
    ptr = ptr->next;
  }
  if (flag == 0)
  {
    puts("没有找到你需要回收的作业!");
    return;
  }
  if (ptr->flag == 0)
  {
    puts("该ID已经是空闲的了");
    return;
  }
  if (ptr->front == NULL)
  {
    //第一个分区

    if (ptr->next == NULL || ptr->next->flag == 1)
    {
      //后面不空或后面没有
      ptr->flag = 0;
      return;
    }
    if (ptr->next->flag == 0)
    {
      //后面空
      ptr->size += ptr->next->size;
      ptr->flag = 0;//标记为空闲
      if (ptr->next->next != NULL)//把下一个节点的头指向该节点
      {
        ptr->next->next->front = ptr;
      }
      ptr->next = ptr->next->next;//合并两个节点

      free(ptr->next);//真实释放节点
      return;
    }
  }
  if (ptr->next == NULL)
  {
    //最后一个分区
    if (ptr->front == NULL || ptr->front->flag == 1)
    {
      //前面不空或者前没有
      ptr->flag = 0;
      return;
    }
    if (ptr->front->flag == 0)
    {
      //前面为空
      ptr->front->size += ptr->size;
      ptr->front->next = NULL;
      free(ptr);
      return;
    }
  }
  if (ptr->front->flag == 0 && ptr->next->flag == 0)
  {
    //上下都空
    ptr->front->size += ptr->size + ptr->next->size;
    ptr->front->next = ptr->next->next;
    if (ptr->next->next != NULL)
    {
      ptr->next->next->front = ptr->front;
    }
    changeIdValue(ptr->front->next, -2); //更改id
    free(ptr->next);
    free(ptr);
    return;
  }
  if (ptr->front->flag == 0 && ptr->next->flag == 1)
  {
    //上空下不空
    ptr->front->size += ptr->size;
    ptr->front->next = ptr->next;
    ptr->next->front = ptr->front;
    changeIdValue(ptr->front->next, -1);
    free(ptr);
    return;
  }
  if (ptr->front->flag == 1 && ptr->next->flag == 0)
  {
    //上不空下空
    ptr->size += ptr->next->size;
    if (ptr->next->next != NULL)
    {
      ptr->next->next->front = ptr;
    }
    partion *p_next = ptr->next;  //保存一下下方为空的那个分区,以便一会释放 
    ptr->next = ptr->next->next;
    ptr->flag = 0;
    changeIdValue(ptr->next, -1);
    free(p_next);
    return;
  }
  if (ptr->front->flag == 1 && ptr->next->flag == 1)
  {
    //上下都不空
    ptr->flag = 0;
    return;
  }  
}

void changeIdValue(partion *ptr, int delta)
{
  while (ptr != NULL)
  {
    ptr->id += delta;
    ptr = ptr->next;
  }
}

4.运行截图

首次适应算法
开始
在这里插入图片描述
(1)作业1 申请130 KB
在这里插入图片描述

(2)作业2 申请60 KB
在这里插入图片描述

(3)作业3 申请100 KB
在这里插入图片描述

(4)作业2 释放60 KB
在这里插入图片描述

(5)作业3 释放100 KB
在这里插入图片描述

(6)作业1 释放130 KB

在这里插入图片描述

最佳适应算法
开始:
在这里插入图片描述

(1)作业1 申请130 KB
在这里插入图片描述

(2)作业2 申请60 KB
在这里插入图片描述

(3)作业3 申请100 KB
在这里插入图片描述

(4)作业2 释放60 KB
在这里插入图片描述

(5)作业3 释放100 KB
在这里插入图片描述

(6)作业1 释放130 KB
在这里插入图片描述

5.程序说明

总流程图:
在这里插入图片描述

总流程图是提供程序开始运行的界面图,供用户选择,其中用户可以选择的选项有,首次适应算法,最佳适应算法,内存回收,内存作业的显示。每选择一个功能就执行相应的函数代码。

首次适应算法流程图:
在这里插入图片描述

首次适应算法,首先用户输入作业需要的内存大小,然后程序从低地址向高地址寻找空间空间,如果找到空闲空间,如果空闲空间的大小比作业需要的空间大则进行分配,如果空闲空间比作业需要的空间小,则继续寻找下一个空闲空间。如果所有的空闲空间都寻找完也没有符合要求的,那么作业的内存分配失败。

最佳适应算法流程图
在这里插入图片描述

最佳适应算法,首页用户输入作业需要的内存空间,程序从低地址开始寻找空闲空间,如果第一次找合适的空间分配,就临时存储这个空间地址,继续向下继续寻找符合的地址空间,如果寻找到合适的空间空间范围,且新的空间大小比临时存储的空间大小还小,则新的符合空间更新为临时符合空间,依次类推到最后。如果程序没有临时最佳的地址空间,则并没有分配到内存,所以作业内存分配失败。如果有临时最佳空间地址,则把最佳的地址空间分配给作业。

内存回收流程图:
在这里插入图片描述

作业回收,首先需要需要输入回收作业的ID,先判断作业ID是否存在,存在才能进行释放,在ID存在的前提下判断,该ID的作业状态,只有为已分配状态猜才进行释放。释放则的分情况讨论。释放的节点分为头部,中间,尾部。如果释放的节点前后已经有空闲空间,就需要进行合并。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/35480.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot整合redis+mysql

SpringBoot整合Redis 测试连接 添加相关依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation&qu…

【TFS-CLUB社区 第7期赠书活动】〖从零开始利用Excel与Python进行数据分析 自动化办公实战宝典〗等你来拿,参与评论,即可有机获得

文章目录❤️‍&#x1f525; 赠书活动 - 《从零开始利用Excel与Python进行数据分析 自动化办公实战宝典》❤️‍&#x1f525; 编辑推荐❤️‍&#x1f525; 抽奖方式与截止时间❤️‍&#x1f525; 赠书活动 → 获奖名单❤️‍&#x1f525; 赠书活动 - 《从零开始利用Excel与…

【数据结构】二叉树的前中后序遍历

二叉树的三种遍历1. 创建一棵简单的二叉树1.1 二叉树结构体实现1.2 创造一个二叉树结点的函数1.3 手动创造一棵二叉树2.为什么要遍历&#xff1f;3.最重要的知识&#xff1a;由二叉树引出的子问题分析4.遍历4.1 前序遍历4.2 中序遍历4.3 后序遍历5.总结1. 创建一棵简单的二叉树…

基于springboot车辆充电桩设计与实现的源码+文档

摘 要 随着信息化时代的到来&#xff0c;管理系统都趋向于智能化、系统化&#xff0c;车辆充电桩管理系统也不例外&#xff0c;但目前国内仍都使用人工管理&#xff0c;市场规模越来越大&#xff0c;同时信息量也越来越庞大&#xff0c;人工管理显然已无法应对时代的变化&…

18.3 内存池概念、代码实现和详细分析

一&#xff1a;内存池的概念和实现原理概述 malloc&#xff1a;内存浪费&#xff0c;频繁分配小块内存&#xff0c;浪费更加明显。 “内存池”要解决什么问题&#xff1f; 1、减少malloc()的次数&#xff0c;减少malloc()调用次数就意味着减少对内存的浪费 2、减少malloc()的…

JavaEE高阶---SpringBoot的创建和使用

一 : 什么是SpringBoot? Spring的诞生是为了简化 Java 程序的开发的,Spring Boot 的诞生是为了简化 Spring 程序开发的.Spring Boot 是所有基于 Spring 开发的项目的起点 . Spring Boot 的设计是为了让你尽可能快的跑起来 Spring 应用程序并且尽可能减少你的配置文件 . Sprin…

深度学习系列2——Pytorch 图像分类(AlexNet)

1. 概述 本文主要是参照 B 站 UP 主 霹雳吧啦Wz 的视频学习笔记&#xff0c;参考的相关资料在文末参照栏给出&#xff0c;包括实现代码和文中用的一些图片。 整个工程已经上传个人的 github https://github.com/lovewinds13/QYQXDeepLearning &#xff0c;下载即可直接测试&a…

你了解PMP考试新考纲的内容吗?

2021年新版PMP考纲变化趋势 随着时代发展&#xff0c;PMP认证本身也通过改版不断调整定位&#xff0c;与全球项目管理趋势相匹配&#xff0c;确保在全球项目管理专业领域保持“黄金标准”。 新版本变化如下&#xff1a; 五大过程组变为三大板块。之前一直沿用的“启动、规划…

Transformer时间序列预测

介绍&#xff1a; 提示&#xff1a;Transformer-decoder 总体介绍 本文将介绍一个 Transformer-decoder 架构&#xff0c;用于预测Woodsense提供的湿度时间序列数据集。该项目是先前项目的后续项目&#xff0c;该项目涉及在同一数据集上训练一个简单的 LSTM。人们认为 LSTM 在…

阿里P8总结的Nacos入门笔记,从安装到进阶小白也能轻松学会

前言 都说程序员工资高、待遇好&#xff0c; 2022 金九银十到了&#xff0c;你的小目标是 30K、40K&#xff0c;还是 16薪的 20K&#xff1f;作为一名 Java 开发工程师&#xff0c;当能力可以满足公司业务需求时&#xff0c;拿到超预期的 Offer 并不算难。然而&#xff0c;提升…

GPC规范-SCP02

SPC02 流程 SPC02 指令 命令&#xff1a; 响应&#xff1a; 举例回复&#xff1a; 密钥分散数据&#xff1a; 0000FFFFFFFFFFFFFFFF Key Info&#xff1a; 20 02&#xff08;scp02&#xff09; Card挑战数&#xff1a; 001AC6619BE83082 Card加密值&#xff1a; 7…

leetcode刷题(133)——剑指 Offer 07. 重建二叉树

输入某二叉树的前序遍历和中序遍历的结果&#xff0c;请构建该二叉树并返回其根节点。 假设输入的前序遍历和中序遍历的结果中都不含重复的数字。 示例 1: Input: preorder [3,9,20,15,7], inorder [9,3,15,20,7] Output: [3,9,20,null,null,15,7]示例 2: Input: preord…

(十一)笔记.net学习表达式目录树Expression

&#xff08;十一&#xff09;笔记.net学习表达式目录树Expression1.什么是表达式目录树&#xff08;1&#xff09;Func和表达式的不同&#xff08;2&#xff09;表达式树拆解&#xff08;3&#xff09;自己拼装表达式目录2.动态拼装表达式目录和扩展应用3.解析表达式目录&…

阿里云服务器采用AMD CPU处理器ECS实例规格详解

阿里云服务器有AMD CPU处理器&#xff0c;阿里云服务器ECS通用型g7a、计算型c7a和内存型r7a采用2.55 GHz主频的AMD EPYCTM MILAN处理器&#xff0c;单核睿频最高3.5 GHz&#xff1b;通用型g6a、计算型c6a和内存型r6a采用2.6 GHz主频的AMD EPYCTM ROME处理器&#xff0c;睿频3.3…

MySQL读取的记录和我想象的不一致——事物隔离级别和MVCC

本篇是《MySQL是怎样运行的》读书笔记&#xff0c;主要分析并发的事务在运行过程中会出现一些可能引发一致性问题的现象。 文章目录1.事务的特性简介1.1 原子性&#xff08;Atomicity&#xff09;1.2 隔离性&#xff08;Isolation&#xff09;1.3 一致性&#xff08;Consistenc…

JUC基础

synchronized 复习虚假唤醒什么是虚假唤醒虚假唤醒产生的原因&#xff1f;解决虚假唤醒&#xff1f;Lock接口ReentrantLock 和 synchronized 的区别Lock 实现线程通信Lock 实现线程定制化通信集合线程安全ArrayListHashSetHashMapsynchronized 锁的范围多线程锁公平锁和非公平锁…

CameraMetadata 知识学习整理

一、涉及的相关代码路径 system/media/camera/src/camera_metadata.c // metadata的核心内容&#xff0c;包含metadata内存分配&#xff0c;扩容规则&#xff0c;update, find等 system/media/camera/src/camera_metadata_tag_info.c // 所有android原生tag的在内存里面sect…

22/11/24

1&#xff0c;单调队列&#xff1b; (76条消息) 单调队列专题_Dull丶的博客-CSDN博客 2&#xff0c;kmp算法&#xff1b; 先是自己和自己匹配&#xff0c;求出ne数组&#xff0c;然后和另一串匹配&#xff0c;进行求解&#xff1b; 循环里三步&#xff1a;while&#xff0c…

【Lilishop商城】No2-3.确定软件架构搭建二(本篇包括接口规范、日志处理)

仅涉及后端&#xff0c;全部目录看顶部专栏&#xff0c;代码、文档、接口路径在&#xff1a; 【Lilishop商城】记录一下B2B2C商城系统学习笔记~_清晨敲代码的博客-CSDN博客 全篇只介绍重点架构逻辑&#xff0c;具体编写看源代码就行&#xff0c;读起来也不复杂~ 谨慎&#xf…

【数据聚类】基于粒子群、遗传和差分算法实现数据聚类附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …