头歌实验8:动态分区算法(编程实验)

第一关

任务:
假设初始状态下可用的内存空间为55MB,并有如下的请求序列:
作业1申请15MB
作业2申请30MB
作业1释放15MB
作业3分配8MB
作业4分配6MB
作业2释放30MB
请采用首次适应算法进行内存块的分配和回收,并打印出空闲内存分区链的情况

上答案:

bool first_fit(int id, int m_size)//首次适应算法,id为作业号,m_size为作业大小 
{
	//请补充使用首次适应算法给作业分配内存的函数代码
	DuLinkList p = new DuNode;
	
	p->data.ID = id;
	p->data.size = m_size;
	p->data.address = (m_last->prior->data.address) + (m_last->prior->data.size);
	
	m_last->data.size -= p->data.size;
	if (m_last->data.size < 0)
		return false;
		
	p->next = m_last;
	p->prior = m_last->prior;
	m_last->prior->next = p;
	m_last->prior = p;

	m_last->data.address = (p->data.address) + (p->data.size);//更新m_last信息

	p->data.flag = true;
	return true;
}


void recycle(int id)//回收内存,id为释放内存的作业号 
{
	//请补充回收作业内存的代码
	DuNode* f = m_head->next;
	while (f->data.ID == id)
	{
		f = f->next;
	}
	if(f==nullptr)return;
	DuNode* p = f->next;
	
	p->prior = f->prior;
	f->prior->next = p;
	f->next = NULL;
	
	while (p)
	{
		p->data.address = (p->prior->data.address) + (p->prior->data.size);
		
		p = p->next;
	}
	m_last->data.size += f->data.size;
	f->data.flag = false;
	delete(f);
	f = NULL;
}

第二关

任务:
假设初始状态下可用的内存空间为55MB,并有如下的请求序列:
作业1申请15MB
作业2申请30MB
作业1释放15MB
作业3分配8MB
作业4分配6MB
作业2释放30MB
请采用最佳适应算法进行内存块的分配和回收,并打印出空闲内存分区链的情况

上答案:

bool best_fit(int id, int m_size)//最佳适应算法,其中需要查找最佳的存放位置
{
	//请补充使用最佳适应算法给作业分配内存的函数代码
	DuNode* p = m_head->next;
	DuNode* t = nullptr;
	while (p)
	{
		if (p->data.flag == 0 && p->data.size >= m_size)
			if (t == nullptr || t->data.size > p->data.size)
				t = p;
		p = p->next;
	}
	if (t == nullptr)
		return false;

	if (t->data.size == m_size)
	{
		t->data.flag = 1;
		t->data.ID = id;
	}

	else {
		DuNode* ans = new DuNode;
		
		ans->prior = t->prior;
		ans->next = t;
		t->prior->next = ans;
		t->prior = ans;

		ans->data.ID = id;
		ans->data.size = m_size;
		ans->data.flag = 1;
		ans->data.address = ans->prior->data.address + ans->prior->data.size;

		ans->next->data.address = ans->data.address + ans->data.size;
		ans->next->data.size -= ans->data.size;
	}
	return true;
}

void recycle(int id)//回收内存,id为释放内存的作业号 
{
	//请补充回收作业内存的函数代码
	DuNode* f = m_head->next;
	while (f->data.ID != id)
	{
		f = f->next;
	}
	if (f == nullptr)
		return;
	
	f->data.ID = 0;
	f->data.flag = 0;

	DuNode* fp = f->prior;
	DuNode* fn = f->next;

	if (fp != m_head && fp->data.flag == 0)
	{
		f->prior = fp->prior;
		fp->prior->next = f;
		
		f->data.address = fp->data.address;
		f->data.size += fp->data.size;
		delete fp;
	}

	if (fn != nullptr  && fn->data.flag == 0)
	{
		f->next = fn->next;
		fn->next->prior = f;
		f->data.size += fn->data.size;
		delete fn;
	}
}

相关说明

还在研究中,先把答案发出来呜
这次拖得有些久,我的锅现在发
状态有些小不好,所以代码有些逻辑混乱,对不住了各位,现在已经改正

双向链表的插入操作

这里给大伙们解释解释,我也复习复习
下图为最开始的模样,我们要将D插入A,B之间
1

D->prior=A;
D->next=B;

如下,D就和A,B榜上关系了
也就是我们可以通过D的prior和next分别访问到A,B
2
然而此时A,B还不认识D,就要进行以下操作

A->next = D;
B->prior = D;

如下,A,B,D之间就有紧密联系了~
3

双向链表的删除节点操作

如下图,我们要删除p节点
4
其实很简单,我们只需要挑拨离间

p->prior->next=p->next;
p->next->prior=p->prior;

就这样,p前后的节点搭上关系了,也就是不需要p这个中间商了
在这里插入图片描述

delete p;

这样就删除了p,没有中间商赚差价
5

首次适应算法

这个就很单纯,直接看看有没有足够空间开个分区给作业用
怎么说呢,就是单纯开,直接加,没有什么套路。
回收空间也差不多这样得单纯。
以下为代码以及解释

首次适应算法函数:

bool first_fit(int id, int m_size)//首次适应算法,id为作业号,m_size为作业大小 
{
	//请补充使用首次适应算法给作业分配内存的函数代码
	DuLinkList p = new DuNode;//开新分区
	
	p->data.ID = id;
	p->data.size = m_size;
	p->data.address = (m_last->prior->data.address) + (m_last->prior->data.size);
	//此时p的数据也已经设置完毕,开始将P插入
	
	m_last->data.size -= p->data.size;
	if (m_last->data.size < 0)
		return false;
	//这里先判断一下,看是否有足够空间
	//插入操作
	p->next = m_last;
	p->prior = m_last->prior;
	m_last->prior->next = p;
	m_last->prior = p;

	m_last->data.address = (p->data.address) + (p->data.size);//更新m_last信息

	p->data.flag = true;
	return true;
}

首次适应算法的回收函数:

这里的回收也很直接
也就是直接将要回收的作业“删掉”,然后将释放出来的空间全部加入m_last中

void recycle(int id)//回收内存,id为释放内存的作业号 
{
	//请补充回收作业内存的代码
	DuNode* f = m_head->next;
	while (f->data.ID != id)
	{
		f = f->next;
	}
	//这个while循环就是为了找到那个点
	//当然,找到这个点后也要进行后面结点的数据更新操作
	if(f==nullptr)return;//没找到,再见
	DuNode* p = f->next;//我们就新定义一个p来操作
	//此时p是f后面的一个点
	
	p->prior = f->prior;
	f->prior->next = p;
	f->next = NULL;
	
	while (p)
	{
		p->data.address = (p->prior->data.address) + (p->prior->data.size);
		//更新点数据
		p = p->next;
	}
	m_last->data.size += f->data.size;
	f->data.flag = false;
	delete(f);
	f = NULL;//此时删除f
}

最佳适应算法

去仔细想了想,才发现自己之前没有理解到

总是把能满足要求、又是最小的空闲分区分配给作业,
避免“大材小用”
若从链首到链尾都找不到一个能满足要求的分区,
则表明系统没有足够大的内存分配给该进程,内存分配失败返回。 

这里也就是说明着我们在要分配作业时要先找
先找空闲的,在空闲分区里找最小的,同时这个最小的大小一定要

最佳适应算法函数:

bool best_fit(int id, int m_size)//最佳适应算法,其中需要查找最佳的存放位置
{
	//请补充使用最佳适应算法给作业分配内存的函数代码
	DuNode* p = m_head->next;//寻找
	DuNode* t = nullptr;//结果
	while (p)
	{
		if (p->data.flag == 0 && p->data.size >= m_size)//这个是判断这个空闲分区是否是满足大小条件的
			if (t == nullptr || t->data.size > p->data.size)//这个是找最小的空闲分区
				t = p;
		p = p->next;
	}
	//经过while循环后,如果t还是空,那么也就只能说明没有足够大的空闲分区了
	if (t == nullptr)
		return false;//此时退出

	//以下是t不为空,也就是有满足要求的空闲分区的情况
	if (t->data.size == m_size)
	{
		t->data.flag = 1;
		t->data.ID = id;
	}//如果t的大小刚好合适,那就改名直接拿来用

	else {
		//这是那个空闲分区的大小大了
		//我们就直接开一个新的分区
		//把这个分区插在空闲分区前面
		DuNode* ans = new DuNode;
		
		//插入操作
		ans->prior = t->prior;
		ans->next = t;
		t->prior->next = ans;
		t->prior = ans;

		//设置新开的分区的值操作
		ans->data.ID = id;
		ans->data.size = m_size;
		ans->data.flag = 1;
		ans->data.address = ans->prior->data.address + ans->prior->data.size;

		//设置新开分区后面的空闲分区的值的操作
		ans->next->data.address = ans->data.address + ans->data.size;
		ans->next->data.size -= ans->data.size;
	}
	return true;
}

最佳适应算法的回收函数:

这里的回收就有要稍稍按题目要求来回收
题目意思差不多是

1,如果这个回收区的前面有空闲分区而后面没有,
	那就把回收区回收的资源都加在空闲分区上
2,如果这个回收区后面有空闲分区而前面没有,
	那就把后面的空闲分区合并在回收区上
3,如果这个回收区前后都有空闲的,就都并上
4,如果前后都没有,那就单独建个回收区

直到打完以上的意思后,我才看懂了这个第二个的回收函数代码,真是太奇妙了

void recycle(int id)//回收内存,id为释放内存的作业号 
{
	//请补充回收作业内存的函数代码
	DuNode* f = m_head->next;
	while (f->data.ID != id)
	{
		f = f->next;
	}//寻找这个分区
	if (f == nullptr)
		return;//找不到,就跑
	
	//以下为找到了

	//先直接将这个区变成空闲的
	f->data.ID = 0;
	f->data.flag = 0;

	//把f的前后区都先弄出来,就好写些
	DuNode* fp = f->prior;
	DuNode* fn = f->next;

	//判定f的前面是不是空闲区
	if (fp != m_head && fp->data.flag == 0)
	{
		f->prior = fp->prior;
		fp->prior->next = f;
		/*也相当于
		* f->prior=f->prior->prior;
		* f->prior->prior->next=f;
		*/
		f->data.address = fp->data.address;
		f->data.size += fp->data.size;
		delete fp;
	}

	//接下来再判定f的后面是不是空闲区
	//如果f->next为空,那么或多或少也就代表着f已经是m_last了,也就是后面没东西了
	//如果
	if (fn != nullptr  && fn->data.flag == 0)
	{
		f->next = fn->next;
		fn->next->prior = f;
		f->data.size += fn->data.size;
		delete fn;
	}
}

结束

  • 22
    点赞
  • 77
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

泉绮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值