7-1 内存分区分配--首次适应算法 (100 分)

总结

对于面试还是要好好准备的,尤其是有些问题还是很容易挖坑的,例如你为什么离开现在的公司(你当然不应该抱怨现在的公司有哪些不好的地方,更多的应该表明自己想要寻找更好的发展机会,自己的一些现实因素,比如对于我而言是现在应聘的公司离自己的家更近,又或者是自己工作到达了迷茫期,想跳出迷茫期等等)

image

Java面试精选题、架构实战文档

整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~

你的支持,我的动力;祝各位前程似锦,offer不断!

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

C 150

2

D 250

2

E 200

2

F 150

4

0

结尾无空行

输出样例3:

在这里给出相应的输出。例如:

1.初始化

2.分配

3.回收

4.显示

0.退出

请选择:

分配成功!

分配成功!

分配成功!

分配成功!

分配成功!

剩余空间不足,不予分配。

分区号 分区 起始地址 结束地址 大小 当前状态

1 A 0 99 100 已分配

2 B 100 299 200 已分配

3 C 300 449 150 已分配

4 D 450 699 250 已分配

5 E 700 899 200 已分配

6 void 900 999 100 空闲

结尾无空行

输入样例4:

在这里给出一组输入。例如:

1

1000 5

2

A 100

2

B 200

2

C 150

2

D 250

2

E 200

2

F 150

3

A

4

0

结尾无空行

输出样例4:

在这里给出相应的输出。例如:

1.初始化

2.分配

3.回收

4.显示

0.退出

请选择:

分配成功!

分配成功!

分配成功!

分配成功!

分配成功!

剩余空间不足,不予分配。

回收成功!

分区号 分区 起始地址 结束地址 大小 当前状态

1 void 0 99 100 空闲

2 B 100 299 200 已分配

3 C 300 449 150 已分配

4 D 450 699 250 已分配

5 E 700 899 200 已分配

6 void 900 999 100 空闲

结尾无空行

输入样例5:

在这里给出一组输入。例如:

1

1000 5

2

A 100

2

B 200

2

C 150

2

D 250

2

E 200

2

F 150

3

A

2

X 150

Y

4

0

结尾无空行

输出样例5:

在这里给出相应的输出。例如:

1.初始化

2.分配

3.回收

4.显示

0.退出

请选择:

分配成功!

分配成功!

分配成功!

分配成功!

分配成功!

剩余空间不足,不予分配。

回收成功!

是否通过紧凑技术,重新划分?(Y/N)

分配成功!

分区号 分区 起始地址 结束地址 大小 当前状态

1 B 0 199 200 已分配

2 C 200 349 150 已分配

3 D 350 599 250 已分配

4 E 600 799 200 已分配

5 X 800 949 150 已分配

6 void 950 999 50 空闲

二:思路

===================================================================

思路:

1.解释算法:动态分区分配-首次适应算法:

<1>:动态分区分配是根据进程的实际需要,动态的为之分配内存的空间,

<2>:那么首次适应算法首次适应算法,要求空闲分区链以地址递增的次序链接,

在分配内存时,从链首开始顺序查找,直到找到一个大小能满足要求的

空闲分区为止,然后再按照作业的大小,

从该分区中划出一块内存空间分给请求者,余下的空闲分区仍停留在空闲链中。

2.写码思路:先将整个框架写好,然后挨个写功能

3.选择数据结构:因为每组数据有多个,所以我们选择结构体数组

4.输入的要求

<1>.初始化:输入内存的大小和阈值minsize,初始状态下空闲分区名字为“void”。

<2>.分配:输入申请进程的名字、大小。

若可以分配,显示“分配成功!”;

若剩余空间不足,显示不分配原因“剩余空间不足,不予分配。”;

若剩余的空间通过紧凑技术,可以再分配,提示“是否通过紧凑技术,

重新划分?(Y/N)”若选择“Y”,通过紧凑技术重新划分并分配,成功后,

显示“分配成功!”若选择“N”,则输出“没有合适的剩余空间,不予分配。”

<3>.回收:输入回收进程的名字,若有相邻空闲分区,需要合并,并输出“回收成功!”;

若输入错误,提示“查无此分区!”

<4>.显示:显示当前内存的分配状态。

<0>.退出

其他:输出“输入错误,请重新输入。”

5.注意如果输入的进程没有占满内存,需要将剩下的内存也得输出来 并表示为空闲状态;

三:演示流程

=====================================================================

在这里插入图片描述

四:debug(贴心杰的建议方式)

================================================================================

1:每实现一个功能就测试,不要等都写完了在去测试

2:整个码都码完了,那就挨个测试给出的示例,

3:如果上方还为未测试出你的bug,那么你就还是用给出的示例 但有一点,每当我们测试完一个用例后,不要退出,直接用功能 3 回收各个进程,然后再测试下一个用例

4:如果还没有,那就用PTA自带的测试用例,可以测你的格式是否正确,这道题最狗的还有是你输出的一定要跟样例一样,包括标点符号

五:上码(有些没用的注解 懒得删了 嘻嘻)

====================================================================================

/**

思路:

1.解释算法:动态分区分配-首次适应算法:

<1>:动态分区分配是根据进程的实际需要,动态的为之分配内存的空间,

<2>:那么首次适应算法首次适应算法,要求空闲分区链以地址递增的次序链接,

在分配内存时,从链首开始顺序查找,直到找到一个大小能满足要求的

空闲分区为止,然后再按照作业的大小,

从该分区中划出一块内存空间分给请求者,余下的空闲分区仍停留在空闲链中。

2.写码思路:先将整个框架写好,然后挨个写功能

3.选择数据结构:因为每组数据有多个,所以我们选择结构体数组

4.输入的要求

<1>.初始化:输入内存的大小和阈值minsize,初始状态下空闲分区名字为“void”。

<2>.分配:输入申请进程的名字、大小。

若可以分配,显示“分配成功!”;

若剩余空间不足,显示不分配原因“剩余空间不足,不予分配。”;

若剩余的空间通过紧凑技术,可以再分配,提示“是否通过紧凑技术,

重新划分?(Y/N)”若选择“Y”,通过紧凑技术重新划分并分配,成功后,

显示“分配成功!”若选择“N”,则输出“没有合适的剩余空间,不予分配。”

<3>.回收:输入回收进程的名字,若有相邻空闲分区,需要合并,并输出“回收成功!”;

若输入错误,提示“查无此分区!”

<4>.显示:显示当前内存的分配状态。

<0>.退出

其他:输出“输入错误,请重新输入。”

5.注意如果输入的进程没有占满内存,需要将剩下的内存也得输出来 并表示为空闲状态;

**/

#include<bits/stdc++.h>

using namespace std;

struct Node{

int id;//id号

string partition = “void”;//分区

int start;//起始地址

int end; //结束地址

int size;//大小

string state = “空闲”;//当前的状态

}node[1000];

int cnt = 0;

int memory,minsize;//内存的大小和阙值

int sumSize = 0;//记录累计的容量

//1.初始化

void Initialize(){

cin >> memory >> minsize;

node[cnt].id = 1;

node[cnt].start = 0;

node[cnt].end = memory - 1;

node[cnt].size = memory;

}

//2.分配

//分区号 分区 起始地址 结束地址 大小 当前状态

//1 void 0 1023 1024 空闲

//分区号 分区 起始地址 结束地址 大小 当前状态

//1 A 0 99 100 已分配

//2 B 100 299 200 已分配

//3 C 300 449 150 已分配

void distribution(){

string processName;

int processSize;

cin >> processName >> processSize;

if(cnt == 0){//这里主要是处理首个进程的计算

node[cnt].end = -1;

}

int temp1 = memory - node[cnt].end - 1;//这里是求出容器距离上一次的结束地址 还剩的空间大小

int temp2 = memory - sumSize;//这里是总的剩余内存的大小

//考虑阙值

int temp3 = temp1 - processSize;

if(temp3 <= minsize && temp3 >= 0){ //如果剩余的空间小于阙值,那么的话我们就将剩下的空间全给其进程

processSize = temp1;

}

if(temp1 >= processSize){

cnt++;

node[cnt].id = cnt;

node[cnt].partition = processName;

if(cnt == 1){

node[cnt].start = 0;

}else{

node[cnt].start = node[cnt-1].start + node[cnt-1].size;//本次的开始地址等于上次的开始地址加其大小

}

node[cnt].end = node[cnt].start + processSize - 1;//本次的结束地址为开始地址+其大小减一

node[cnt].size = processSize;

node[cnt].state = “已分配”;

sumSize += processSize;

cout << “分配成功!” << endl;

}else if(temp2 >= processSize){//如果第一个条件不满足,那么的话就判断剩余的总内存,也就是紧凑

cout << “是否通过紧凑技术,重新划分?(Y/N)” << endl;

char ch;

cin >> ch;

/*如果我们的第一个if条件已经满足的话根本就不用考虑是否紧凑,那么好,如果我们要

紧凑的话,只能说明在这个容器的前面还有空间,那么容器的前面有空间就说明发生了回收

这时候如果我们选择 Y 那么的话我们就要更新前面的id…,如果是 N,那就不用更新

*/

if(ch == ‘Y’){

//更新前面的空闲区,将非空的进程赋值给前面空的进程,紧凑出空间给新的进程

for(int i = 1; i <= cnt; i++) {

if(node[i].partition == “void”){

int value = node[i].size;//记录下来空闲区的大小

int j = i;

bool temp = false;

for( ; j < cnt; j++){

node[j].id = j;

node[j].partition = node[j+1].partition;

node[j].start = node[j+1].start - value;

node[j].end = node[j+1].end - value;

node[j].size = node[j+1].size;

node[j].state = node[j+1].state;

temp = true;

}

cnt–;//这时候腾出一个空间,所以结构体数组的大小减一

i = 0;//再从头开始遍历空闲区,因为空闲区可能不止一个

if(temp == false)//说明要紧凑的空间是最后一个,那么直接跳出循环

break;

}

}

//这时候考虑我们的阙值 因为当没有紧凑的时候根本没有空间来判断剩余空间的大小

//跟阙值的关系

int laterTemp1 = memory - node[cnt].end - 1;//紧凑后的空间大小

int laterTemp3 = laterTemp1 - processSize;

if(laterTemp3 <= minsize){

processSize = laterTemp1;

}

//赋值,当上方完成后这时候就腾出一个大的size

cnt++;

node[cnt].id = cnt;

node[cnt].partition = processName;

if(cnt == 1){

node[cnt].start = 0;

}else{

node[cnt].start = node[cnt-1].start + node[cnt-1].size;//本次的开始地址等于上次的开始地址加其大小

}

node[cnt].end = node[cnt].start + processSize - 1;

node[cnt].size = processSize;

node[cnt].state = “已分配”;

sumSize += processSize;

cout << “分配成功!” << endl;

}else if (ch == ‘N’){

cout << “没有合适的剩余空间,不予分配。” << endl;

}

}else{

cout << “剩余空间不足,不予分配。” << endl;

}

}

//3.回收

void recycling(){

/*

如果发生回收的话,要将 分区改为 void,其状态为空闲,其他均不变;

分为四种情况:

<1>:如果其上下均无空闲区,那么该回收的进程就单独成一行

<2>:如果该回收的进程上放有一个空的空闲区,那么就要和其上方进行合并,修改上方的结束地址和空间大小

<3>:如果该回收的进程的下方有一个空闲区,那么就修改回收进程的大小和结束地址即可

<4>:如果该回收的进程上下都有空闲区,那么的话我们就修改最上方的空闲区的大小和结束地址即可

*/

string processName;

int flag = 0;

cin >> processName;

for(int i = 1; i <= cnt; i++) {

if(processName == node[i].partition){

node[i].partition = “void”;

node[i].state = “空闲”;

sumSize -= node[i].size;//一旦发生回收那么这个累计的容量就要减去回收的容量

flag = 1;

break;

}

}

if(flag == 1){

cout << “回收成功!” << endl;

/*

这里我们在合并空闲区的时候只需要当发现一个空闲区的时候,看看下一个分区是否是空闲区

如果是就合并

*/

for(int i = 1; i < cnt; i++){

if(node[i].partition == “void” && node[i+1].partition == “void”){

node[i].size += node[i+1].size;//其大小为两个分区的和

node[i].end = node[i+1].end;//其结束地址为下一个空闲区的结束地址

//因为分区少了一个所以要更新后面分区的id号

int j = i+2;

for( ; j <= cnt; j++){

node[j-1].id = j - 1;

node[j-1].partition = node[j].partition;

node[j-1].start = node[j].start;

node[j-1].end = node[j].end;

node[j-1].size = node[j].size;

node[j-1].state = node[j].state;

}

cnt–;//分区少一个

i = 0;//再从头开始遍历 因为可能有多个空闲区

}

}

}else{

cout << “查无此分区!” << endl;

}

}

//4.显示

void show(){

cout << “分区号 分区 起始地址 结束地址 大小 当前状态” << endl;

if (cnt == 0) {

for(int i = 0; i <= cnt; i++){

cout << node[i].id << ’ ’

<< node[i].partition << ’ ’

<< node[i].start << ’ ’

<< node[i].end << ’ ’

<< node[i].size << ’ ’

<< node[i].state;

}

} else {

//这里需要将剩余的空间也得输出一下

int remainTemp = memory - node[cnt].end - 1;

//这里写大于0 是因为上方我已经处理 minsize;

if(remainTemp > 0){

cnt++;

node[cnt].id = cnt;

node[cnt].partition = “void”;

if(cnt == 1){

node[cnt].start = 0;

}else{

node[cnt].start = node[cnt-1].start + node[cnt-1].size;//本次的开始地址等于上次的开始地址加其大小

}

node[cnt].end = node[cnt].start + remainTemp - 1;

node[cnt].size = remainTemp;

node[cnt].state = “空闲”;

}

分享

1、算法大厂——字节跳动面试题

2、2000页互联网Java面试题大全

3、高阶必备,算法学习

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

<< node[i].partition << ’ ’

<< node[i].start << ’ ’

<< node[i].end << ’ ’

<< node[i].size << ’ ’

<< node[i].state;

}

} else {

//这里需要将剩余的空间也得输出一下

int remainTemp = memory - node[cnt].end - 1;

//这里写大于0 是因为上方我已经处理 minsize;

if(remainTemp > 0){

cnt++;

node[cnt].id = cnt;

node[cnt].partition = “void”;

if(cnt == 1){

node[cnt].start = 0;

}else{

node[cnt].start = node[cnt-1].start + node[cnt-1].size;//本次的开始地址等于上次的开始地址加其大小

}

node[cnt].end = node[cnt].start + remainTemp - 1;

node[cnt].size = remainTemp;

node[cnt].state = “空闲”;

}

分享

1、算法大厂——字节跳动面试题

[外链图片转存中…(img-u5XyW65O-1715798779734)]

2、2000页互联网Java面试题大全

[外链图片转存中…(img-BNhHp4Hs-1715798779734)]

3、高阶必备,算法学习

[外链图片转存中…(img-Zyu5fMO8-1715798779734)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值