一个不知名大学生,江湖人称菜狗
original author: Jacky Li
Email : 3435673055@qq.comTime of completion:2024.04.09
Last edited: 2024.04.09
目录
动态分区算法
第1关:首次适应算法
任务描述
相关知识
内存分配
内存回收
编程要求
测试说明
代码如下
第2关:最佳适应算法
相关知识
内存分配
内存回收
编程要求
测试说明
代码如下
动态分区算法
第1关:首次适应算法
任务描述
假设初始状态下可用的内存空间为55MB,并有如下的请求序列: 作业1申请15MB 作业2申请30MB 作业1释放15MB 作业3分配8MB 作业4分配6MB 作业2释放30MB 请采用首次适应算法进行内存块的分配和回收,并打印出空闲内存分区链的情况
相关知识
为了完成本关任务,你需要掌握使用首次适应算法进行内存块的分配与回收。
内存分配
空闲分区链按地址递增的顺序链接。在分配内存时,从链首开始顺序查找,直至找到一个大小能满足要求的空闲分区。然后再按照作业的大小,从该分区中划出一块内存空间,分配给请求者,余下的空闲分区仍留在空闲链中。若从链首到链尾都找不到一个能满足要求的分区,则表明系统没有足够大的内存分配给该进程,内存分配失败返回。
内存回收
当进程运行完毕释放内存时,系统根据回收区的首址,从空闲区链(表)中找到相应的插入点,此时可能出现以下四种情况之一: (1) 回收区与插入点的前一个空闲分区F1相邻接,此时应将回收区与插入点的前一分区合并,不必为回收分区分配新表项,而只需修改其前一分区F1的大小。 (2) 回收分区与插入点的后一空闲分区F2相邻接,此时也可将两分区合并,形成新的空闲分区,但用回收区的首址作为新空闲区的首址,大小为两者之和。 (3) 回收区同时与插入点的前、后两个分区F1和F2邻接,此时将三个分区合并,使用F1的表项和F1的首址,取消F2的表项,大小为三者之和。 (4) 回收区前后没有空闲分区。这时应为回收区单独建立一个新表项,填写回收区的首址和大小,并根据其首址插入到空闲链中的适当位置
编程要求
空闲分区采用带头结点的双向链表来管理,主函数、链表初始化函数和打印函数已实现,只需要补充首次适应算法分配内存的函数 first_fit以及内存回收的函数recycle()即可。
bool first_fit(int id,int m_size)//使用首次适应算法给作业分配内存,id为作业号,m_size为作业大小 void recycle(int id)//回收内存,id为释放内存的作业号
测试说明
平台会对你编写的代码进行测试:
代码如下
#include <stdio.h>
#include <stdlib.h>
const int Max_length=55;//最大内存
struct areaNode//管理分区的结构体
{
int ID;//分区号
int size;//分区大小
int address;//分区地址
int flag;//使用状态,0为未占用,1为已占用
};
typedef struct DuNode//双向链表结点
{
struct areaNode data;//数据域
struct DuNode *prior;//指针域
struct DuNode *next;
}*DuLinkList;
DuLinkList m_head = new DuNode, m_last = new DuNode;//双向链表首尾指针
void init()//分区链表初始化
{
m_head->prior = NULL;
m_head->next = m_last;
m_last->prior = m_head;
m_last->next = NULL;
m_head->data.size = 0;
m_last->data.address = 0;
m_last->data.size = Max_length;
m_last->data.ID = 0;
m_last->data.flag = 0;
}
void show()
{
DuNode *p = m_head->next;//指向空闲区队列的首地址
printf("+++++++++++++++++++++++++++++++++++++++\n");
while (p)
{
printf("分区号:");
if (p->data.ID == 0)
printf("FREE\n");
else
printf("%d\n",p->data.ID);
printf("分区起始地址:%d\n",p->data.address);
printf("分区大小:%d\n",p->data.size);
printf("分区状态:");
if (p->data.flag)
printf("已被占用\n");
else
printf("空闲\n");
printf("——————————————————\n");
p = p->next;
}
}
bool first_fit(int id,int m_size)//首次适应算法,id为作业号,m_size为作业大小
{
//请补充使用首次适应算法给作业分配内存的函数代码
DuLinkList temp=(DuLinkList)malloc(sizeof(DuNode));//申请双向链表指针节点temp(*a.b=a->b)
DuNode *p=m_head->next;
temp->data.ID=id;//*temp.data.ID
temp->data.size=m_size;
temp->data.flag=1;
while(p){//循环查找
if(p->data.flag==0&&p->data.size==m_size){//p节点未占用,并且空间刚好满足
p->data.flag=1;
p->data.ID=id;
return false;
}
if(p->data.flag==0&&p->data.size>m_size){//p节点未占用,且空间大于所需
temp->next=p;
temp->prior=p->prior;//temp 插入p之前
temp->data.address=p->data.address;//分区起始地址
p->prior->next=temp;
p->prior=temp;
p->data.address=temp->data.address+temp->data.size;
p->data.size-=m_size;
return false;
}
p=p->next;
}
return true;
}
void recycle(int id)//回收内存,id为释放内存的作业号
{
//请补充回收作业内存的代码
DuLinkList n=m_head->next ;
while(n)
{
DuLinkList q=n->next;
if(n->data.ID==id)
{
if(n->prior!=m_head&&n->prior->data.flag==0&&n->next->data.flag==0)
{
n->prior->data.size = n->prior->data.size+q->data.size+n->data.size;
q->prior= n->prior;
n->prior->next=q;
if(q==m_last)
{
n->prior->next=NULL;
n->prior->data.ID=0;
}
delete(n);
}
else if(n->prior!=m_head&&n->prior->data.flag==0&&n->next->data.flag != 0)
{
n->prior->data.size+=n->data.size;
n->prior->next=q;
q->prior=n->prior;
delete n;
break;
}
else if(n->next->data.flag==0&&n->prior->data.flag!=0&&n->prior!=m_head)
{
n->data.size+=q->data.size;
n->next=q->next;
n->data.flag=0;
q->next->prior=n;
delete q;
break;
}
else
{
n->data.flag=0;
break;
}
}
n=n->next;
}
}
int main()
{
init();
printf("首次适应算法:\n");
first_fit(1,15);
first_fit(2,30);
recycle(1);
first_fit(3,8);
first_fit(4,6);
recycle(2);
show();
DuNode *p = m_head;
while(p != NULL)
{
DuNode *temp = p;
p = p->next;
delete(temp);
temp = NULL;
}
return 0;
}
第2关:最佳适应算法
假设初始状态下可用的内存空间为55MB,并有如下的请求序列: 作业1申请15MB 作业2申请30MB 作业1释放15MB 作业3分配8MB 作业4分配6MB 作业2释放30MB 请采用最佳适应算法进行内存块的分配和回收,并打印出空闲内存分区链的情况
相关知识
为了完成本关任务,你需要掌握使用最佳适应算法进行内存块的分配与回收。
内存分配
每次为作业分配内存时,总是把能满足要求、又是最小的空闲分区分配给作业,避免“大材小用”。若从链首到链尾都找不到一个能满足要求的分区,则表明系统没有足够大的内存分配给该进程,内存分配失败返回。
内存回收
当进程运行完毕释放内存时,系统根据回收区的首址,从空闲区链(表)中找到相应的插入点,此时可能出现以下四种情况之一: (1) 回收区与插入点的前一个空闲分区F1相邻接,此时应将回收区与插入点的前一分区合并,不必为回收分区分配新表项,而只需修改其前一分区F1的大小。 (2) 回收分区与插入点的后一空闲分区F2相邻接,此时也可将两分区合并,形成新的空闲分区,但用回收区的首址作为新空闲区的首址,大小为两者之和。 (3) 回收区同时与插入点的前、后两个分区F1和F2邻接,此时将三个分区合并,使用F1的表项和F1的首址,取消F2的表项,大小为三者之和。 (4) 回收区前后没有空闲分区。这时应为回收区单独建立一个新表项,填写回收区的首址和大小,并根据其首址插入到空闲链中的适当位置
编程要求
空闲分区采用带头结点的双向链表来管理,主函数、链表初始化函数和打印函数已实现,只需要补充最佳适应算法分配内存的函数 best_fit以及内存回收的函数recycle()即可。
bool best_fit(int id,int m_size)//使用最佳适应算法给作业分配内存,id为作业号,m_size为作业大小 void recycle(int id)//回收内存,id为释放内存的作业号
测试说明
平台会对你编写的代码进行测试:
代码如下
#include <stdio.h>
#include <stdlib.h>
const int Max_length=55;//最大内存
struct areaNode//管理分区的结构体
{
int ID;//分区号
int size;//分区大小
int address;//分区地址
int flag;//使用状态,0为未占用,1为已占用
};
typedef struct DuNode//双向链表结点
{
struct areaNode data;//数据域
struct DuNode *prior;//指针域
struct DuNode *next;
}*DuLinkList;
DuLinkList m_head = new DuNode, m_last = new DuNode;//双向链表首尾指针
void init()//分区链表初始化
{
m_head->prior = NULL;
m_head->next = m_last;
m_last->prior = m_head;
m_last->next = NULL;
m_head->data.size = 0;
m_last->data.address = 0;
m_last->data.size = Max_length;
m_last->data.ID = 0;
m_last->data.flag = 0;
}
void show()
{
DuNode *p = m_head->next;//指向空闲区队列的首地址
printf("+++++++++++++++++++++++++++++++++++++++\n");
while (p)
{
printf("分区号:");
if (p->data.ID == 0)
printf("FREE\n");
else
printf("%d\n",p->data.ID);
printf("分区起始地址:%d\n",p->data.address);
printf("分区大小:%d\n",p->data.size);
printf("分区状态:");
if (p->data.flag)
printf("已被占用\n");
else
printf("空闲\n");
printf("——————————————————\n");
p = p->next;
}
}
bool best_fit(int id, int m_size)//最佳适应算法,其中需要查找最佳的存放位置
{
//请补充使用最佳适应算法给作业分配内存的函数代码
DuLinkList m = new DuNode;
DuNode *p = m_head->next;
DuNode *q;
int min=1000;
while(p)
{
if(p->data.flag==0)
{
int size=p->data.size-m_size;
if(size<min&&size>0)
{
q=p;
min = size;
}
}
p=p->next;
}
m->prior= q->prior;
q->prior->next=m;
m->next=q;
q->prior =m;
m->data.flag=1;
if(m->prior==m_head)
m->data.address= 0;
else
m->data.address=m->prior->data.address+m->prior->data.size;
m->data.ID=id;
m->data.size=m_size;
q->data.address=m->data.address+m->data.size;
q->data.ID=0;
q->data.size = q->data.size-m_size;
}
void recycle(int id)//回收内存,id为释放内存的作业号
{
//请补充回收作业内存的函数代码
DuLinkList n=m_head->next ;
while(n)
{
DuLinkList q=n->next;
if(n->data.ID==id)
{
if(n->prior!=m_head&&n->prior->data.flag==0&&n->next->data.flag==0)
{
n->prior->data.size = n->prior->data.size+q->data.size+n->data.size;
q->prior= n->prior;
n->prior->next=q;
if(q==m_last)
{
n->prior->next=NULL;
n->prior->data.ID=0;
}
delete(n);
}
else if(n->prior!=m_head&&n->prior->data.flag==0&&n->next->data.flag != 0)
{
n->prior->data.size+=n->data.size;
n->prior->next=q;
q->prior=n->prior;
delete n;
break;
}
else if(n->next->data.flag==0&&n->prior->data.flag!=0&&n->prior!=m_head)
{
n->data.size+=q->data.size;
n->next=q->next;
n->data.flag=0;
q->next->prior=n;
delete q;
break;
}
else
{
n->data.flag=0;
break;
}
}
n=n->next;
}
}
int main()
{
init();
//最佳适应算法
printf("最佳适应算法:\n");
init();
best_fit(1,15);
best_fit(2,30);
recycle(1);
best_fit(3,8);
best_fit(4,6);
recycle(2);
show();
DuNode *p = m_head;
while(p != NULL)
{
DuNode *temp = p;
p = p->next;
delete(temp);
temp = NULL;
}
return 0;
}