请添加图片描述
我参考的这篇文章,点这里
最先适应算法(First Fit)简介
首次适应算法(First Fit):该算法从空闲分区链首开始查找,直至找到一个能满足其大小要求的空闲分区为止。然后再按照作业的大小,从该分区中划出一块内存分配给请求者,余下的空闲分区仍留在空闲分区链中。
特点: 该算法倾向于使用内存中低地址部分的空闲区,在高地址部分的空闲区很少被利用,从而保留了高地址部分的大空闲区。显然为以后到达的大作业分配大的内存空间创造了条件。
缺点:低地址部分不断被划分,留下许多难以利用、很小的空闲区,而每次查找又都从低地址部分开始,会增加查找的开销。
思路:
我理论懂,但是代码不会写我参考的别人的,采用双向链表,开始有两个节点,一个是头结点,不存储任何信息,还有一个主节点,大小为你设置的最大值,后续所有节点都是在这个节点的基础上划分。从这个结点开始,空间大小<你需要的,不满足条件,空间大小>你需要的,只占用了块的一部分,我们只占用块的前半部分,后面的部分还是空闲,空闲块要新生成,位于当前节点和当前节点的下一节点之间,空间大小==你需要的,直接全占用。
回收内存时要注意前后块是否空闲,空闲的话要合并,当前后快都空闲时,我是先合并的后面块,在合并前面块。
代码:
/*
* @Author: robot-cmy
* @Date: 2021-11-22 17:08:50
* @Last Modified by: robot-cmy
* @Last Modified time: 2021-11-22 18:01:48
*/
//参考了下方的代码
// https://blog.csdn.net/weixin_39924920/article/details/81054205?ops_request_misc=&request_id=&biz_id=102&utm_term=%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E6%9C%80%E5%85%88%E9%80%82%E5%BA%94%E7%AE%97%E6%B3%95&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-81054205.first_rank_v2_pc_rank_v29&spm=1018.2226.3001.4187
#include <iostream>
using namespace std;
#define MAX_MEMORY 666 //假设最大内存
void init(); //初始化函数,对初始节点初始化
void showInfo(); //显示分配信息
bool firstFit( int id, int memorySize ); //最先适应算法
void allocate(); //内存分配
void recycle(); //内存回收
//链表数据块
struct Area {
int id; //作业id
int size; //作业大小
int address; //作业起始地址
bool flag; //=1表示被占用 =0表示未被占用
};
//采用双链表表示法
typedef struct Node {
Area data; //节点数段块
Node *pre; //前指针
Node *next; //后指针
} * LinkList;
//firstPointer时链头 lastPointer实际节点,所有数据分配都是基于这个节点
LinkList firstPointer, lastPointer;
//为两个头结点分配空间并初始化
void init() {
firstPointer = new Node;
lastPointer = new Node;
firstPointer->pre = NULL; //头结点前指针为空
firstPointer->next = lastPointer;
firstPointer->data.size = 0;
lastPointer->pre = firstPointer;
lastPointer->next = NULL;
lastPointer->data.address = 0; //我们实际操作都基于lastPointer节点,所以设这个起始地址为0
lastPointer->data.size = MAX_MEMORY; //同理,size也设为最大
lastPointer->data.id = 0;
lastPointer->data.flag = 0;
}
//打印内存分配情况
void showInfo() {
Node *p = firstPointer->next; //指针p指向实际的第一个节点
cout << "------------------------\n";
//不为空一直遍历
while( p ) {
cout << "分区号:";
if( p->data.id ) {
cout << p->data.id << endl;
} else {
cout << "空闲分区" << endl;
}
cout << "分区地址:" << p->data.address << endl;
cout << "分区大小:" << p->data.size << endl;
cout << "分区状态:";
//flag=1表示被占用,=0表示未占用
if( p->data.flag ) {
cout << "分区被占用" << endl;
} else {
cout << "分区空闲" << endl;
}
p = p->next;
cout << "------------------------\n";
}
}
//最先适应算法 id为输入的作业编号 memorySize为输入的作业大小
bool firstFit( int id, int memorySize ) {
Node *p = firstPointer->next; //指针p指向实际的第一个节点
while( p ) {
//当前块未被占用且空间>=需要的空间大小
if( !p->data.flag && p->data.size >= memorySize ) {
//当前块刚好等于所需要的大小,直接分配
if( p->data.size == memorySize ) {
p->data.id = id;
p->data.flag = 1;
return true;
} else { //当前块大于需要的,只分当前块的前半部分,后半部分还是空闲
LinkList temp = new Node; //后面的空闲块
temp->data.size = p->data.size - memorySize; //空闲块大小=原来块大小-需要的
temp->data.address = p->data.address + memorySize; //地址=原来块的地址+需要的大小
temp->data.flag = 0; //表示未被占用
temp->data.id = 0;
temp->pre = p; //相当于在p和p->next之间插入了一个新空闲块
temp->next = p->next;
//原节点此时被完全占用
p->data.size = memorySize;
p->data.id = id;
p->data.flag = 1;
p->next = temp;
return true;
}
}
p = p->next;
}
return false; //没有找到可用空闲块
}
//作业内存分配
void allocate() {
int id, memorySize;
cout << "输入作业编号和申请内存大小:";
cin >> id >> memorySize;
bool sign = firstFit( id, memorySize );
if( sign ) {
cout << "分配成功\n";
} else {
cout << "内存不足,分配失败\n";
}
}
//作业内存回收,前面的块空闲要与前面块合并,后面的块空闲要与后面的块合并
void recycle() {
int id;
Node *p = firstPointer->next; //指针p指向实际的第一个节点
cout << "输入要释放的进程序号:";
cin >> id;
while( p ) {
//找到了内存块
if( p->data.id == id ) {
p->data.id = 0; //id=0表示内存卡未被使用
p->data.flag = 0; // 1占用 0空闲
//与前一个块合并时要考虑先合并后面的块,这样才能不出错
if( !p->pre->data.flag ) {
//合并后面的块
if( !p->next->data.flag ) {
p->data.size += p->next->data.size; //当前块大小+后面块大小
p->next = p->next->next; //对应指针改变,前后两个指针都要变
p->next->next->pre = p;
}
//合并前面块
p->pre->data.size += p->data.size;
p->pre->next = p->next;
p->next->pre = p->pre;
}
//合并后面块
if( !p->next->data.flag ) {
p->data.size += p->next->data.size;
p->next = p->next->next;
p->next->next->pre = p;
}
}
p = p->next;
}
}
int main() {
init();//初始化
int choice;
cout << "*** 1.分配空间\t2.回收空间\t3.显示内存分配情况\t其余按键均为退出***\n\n" ;
while( 1 ) {
cout << "输入选项:";
cin >> choice;
switch( choice ) {
case 1:
allocate();
break;
case 2:
recycle();
break;
case 3:
showInfo();
break;
default:
return 0;
break;
}
}
return 0;
}