头歌——首次适应算法

任务描述
假设初始状态下可用的内存空间为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为作业大小 
{	
    //请补充使用首次适应算法给作业分配内存的函数代码
    DuNode *p = m_head->next,*q = new DuNode();
    
    while(p)
    {
    	if(p->data.size> m_size&&p->data.flag==0)
    	{
    			q->data.ID=id;
   				q->data.size=m_size;
   				q->data.flag=1;
    			q->data.address=p->data.address;
    			
    			p->data.address+=q->data.size;
    			p->data.size-=m_size;
    			
    			q->prior=p->prior;
    			p->prior->next=q;
    			q->next=p;
    			p->prior=q;
    			
 
    			break; 
		}
		
		else	p=p->next;
	}
}


void recycle(int id)//回收内存,id为释放内存的作业号 
{	
    //请补充回收作业内存的代码

    DuNode *p=m_head->next,*q=m_head;
    
    while(p)
    {
    	if(p->data.ID==id)
    	{
    		if(p->prior->data.flag==0&&p!=m_head->next)	//不是第一个与前一个分区相邻 
    		{
    			p->data.ID=0;
    			p->data.size+=q->data.size;
    			p->data.address=q->data.address;
    			p->data.flag=0;
    			
    			q->prior->next=q->next;
    			q->next->prior=q->prior;
    			
    			q=p->prior;
			}
			if(p->next->data.flag==0)				//不是第一个,与后一个相邻 
			{
				p->next->data.ID=0;
    			p->next->data.size+=p->data.size;
    			p->next->data.address=p->data.address;
    			
    			p->prior->next=p->next;
    			p->next->prior=p->prior;
    			
    			p=q->next;
			}
			
			else if((p->prior->data.flag=1&&p->next->data.flag==1)||(p->next->data.flag==1&&p==m_head))				//都不相邻 
			{
				p->data.ID=0;
    			p->data.flag=0;
			}

		}
		else
		{
			p=p->next;
			q=q->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;
} 
//插入第二次6占了15空间, 


  • 9
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值