最坏适应算法的模拟(c++实现)

实验要求

1)实现一个完整的(可变)动态分区管理器,包括分配,回收,分区碎片整理等。希望同学们实现如下功能:

2)初始化功能:内存状态设置为初始状态。

3)分配功能:采用最佳适应算法进行分配。

4)回收功能:对不用的作业进行回收。

5)空闲块的合并:即紧凑功能,用以消除碎片。当做碎片整理时,需要跟踪分配的空间,修改其引用以保证引用的正确性。

6)显示当前内存的使用状态,可以使用表格或图形。

设计思路

  动态分区管理可以用两种数据结构实现,一种是已分配区表和空闲区表,也就是用预先定义好的系统空间来存放空间分配信息。设置了两个结构体分别来表示已分配区表和空闲区表,其中blanks用来表示空闲区表,其中有分区大小、起始地址两个参数。Job用来表示存放在内存中的作业,其中有作业名字、大小、起始地址三个参数。

  空闲分区表中的空闲分区按大小从大到小排列,作业调入时会先从表头(下标为0)开始寻找,因此每次分配的都是可以满足作业大小需求的最大空白分区,实现了最坏适应算法的模拟。

实验结果与分析

设置内存总大小为1024KB,进入程序后有四种选项,插入作业请输入1,回收作业请输入0,紧凑请输入2, 查看内存信息请输入3,退出程序请输入4。

图4-1 程序选项图

输入1后,程序可作业进行内存分配

图4-2 内存分配

并且展示当前内存信息

图4-3 当前内存信息

插入a、b、c三个作业后,内存信息如下所示

图4-4 三个作业

此时输入0,将b作业收回,程序运行效果如下

图4-5 收回b作业

此时已经产生了碎片,输入2,进行紧凑操作,程序进行重定位,自动改变了当前内存中作业的起始地址

图4-6 紧凑效果

当内存各分区中都无大小大于该作业的可用区时,判断空闲分区总和是否大于该作业的大小,若满足条件,则在紧凑后放入。如下图所示,此时若插入一个大小为130KB的作业,则必须进行紧凑后才能放入

图4-7 当前内存信息

插入一个名字为jincou的作业,大小为130KB,根据程序运行结果可以发现是经过了紧凑的,说明程序运行正确。

图4-8 紧凑后插入成功

空闲分区表中的空闲分区按大小从大到小排列,作业调入时会先从表头(下标为0)开始寻找,因此每次分配的都是可以满足作业大小需求的最大空白分区,实现了最坏适应算法的模拟。

图4-9 按照分区大小排列

流程图

   程序总体流程图:

图4-10最坏适应算法整体流程图

分配算法流程图

图4-11 分配算法流程图

   回收算法流程图

图4-12 回收算法流程图

源程序

#include<iostream>
#include<algorithm>

using namespace std;

const int N = 50, SIZE = 1024;
int M, K;//M当前空闲分区数, K 当前内存中作业数 

struct blank //用表来存储空闲分区 
{
	int size;//分区大小
	int start;//起始地址 
	
	bool operator < (const blank &w)//最大的空白区放最前面 
	{
		return size > w.size;	
	} 
}blanks[N];

struct job//用来存放内存中的作业 
{
	string name;//作业名字
	int size;//大小
	int start;//起始地址 
}jobs[N]; 

void init()//初始化 
{
	blanks[0].size = SIZE;
	blanks[0].start = 0;
	M ++;
}

void tight()//紧凑 
{
	int sum = 0;//空闲分区总和
	for(int i = 0; i < M; i ++)
		sum += blanks[i].size;
	blanks[0].size = sum;
	blanks[0].start = SIZE - sum;
	M = 1;
	
	int address = 0;//动态重定位 
	for(int i = 0; i < K; i ++)
	{
		jobs[i].start = address;
		address += jobs[i].size;
	}
} 

bool fenpei(string name, int size)//按动态分区方式进行分配,成功分配返回true,否则返回false
{
	for(int i = 0; i < M; i ++)
	{
		if(size <= blanks[i].size)//找到可以放下该作业的空闲分区 
		{
	
			jobs[K].size = size;
			jobs[K].name = name;
			jobs[K ++].start = blanks[i].start;//将该作业调入内存,插入job表中 
			
			cout << "作业 " << name << " 被分配到第 " << i << " 分区" << endl; 
			
			if(size == blanks[i].size)//如果大小相等就将该空白分区删除 
			{
				for(int j = i + 1; j < M; j ++)//覆盖法 
					blanks[j - 1] = blanks[j];  
				M --;
			} 
			else//大小不相等,改变空白分区的大小和起始位置 
			{
				blanks[i].size = blanks[i].size - size;
				blanks[i].start = blanks[i].start + size;	
			}
			
			tight();//紧凑 
			
			return true;//分配完成,返回
		}
	}
	return false;
}

void add()
{
	cout << "请输入作业名、作业大小" << endl;
	string name;
	int size;
	cin >> name >> size;
	 
	if(fenpei(name, size)) return ;

	int sum = 0;//空闲分区总和
	for(int i = 0; i < M; i ++)
		sum += blanks[i].size;
	
	if(sum < size)//空闲分区总和小于该作业大小
		cout << "作业过大,无法分配" << endl;
	else
	{
		tight();//紧凑
		fenpei(name, size);
	} 
}

void recycle()
{
	cout << "请输入作业名" << endl;
	string name;
	cin >> name;
	
	int i;
	bool flag = false;//是否找到该作业 
	for(i = 0; i < K; i ++)
	{
		if(jobs[i].name == name)//找到该作业的下标 
		{
			flag = true;
			break;
		}		
	}
	if(!flag) 
	{
		cout << "该作业不存在,输入有误!" << endl;
		return ;
	}
	
	int start = jobs[i].start, end = jobs[i].size + jobs[i].start;//该作业占用的开始点和结束点
	
	flag = false;//该回收区是否有后邻接区 
	for(int j = 0; j < M; j ++)
	{
		int blank_start = blanks[j].start, blank_end = blanks[j].size + blanks[j].start;
		if(blank_start == end)//找到后邻接区 
		{
			flag = true;
			
			blanks[j].start = start;
			blanks[j].size = blanks[j].size + jobs[i].size;//更新后邻接区
			
			if(j > 0 && start == blanks[j - 1].size + blanks[j - 1].start)//有前邻接区
			{
				blanks[j].start = blanks[j - 1].start;
				blanks[j].size = blanks[j].size + blanks[j - 1].size;
				
				for(int j = i + 1; j < M; j ++)//覆盖法 
					blanks[j - 1] = blanks[j];  
				M --;	
			} 
		}
	}
	
	if(!flag)//没有后邻接区,检查是否有前邻接区                 
	{
		
		for(int j = 0; j < M; j ++)
		{
			int blank_start = blanks[j].start, blank_end = blanks[j].size + blanks[j].start;
			if(start == blank_end)//找到前邻接区 
			{
				flag = true;
				
				blanks[j].size = blanks[j].start + blanks[j].size + jobs[i].size;//更新后邻接区
			}
		}
		
		if(!flag)//既没前邻接区也没有后邻接区, 要插入一个新的空白区 
		{
			int k;//找到该作业该插入的位置 
			for(k = 0; k < M; k ++) 
				if(start < jobs[k].start) break;
			k --;
			
			for(int j = M - 1; j >= k; j --)
				blanks[j + 1] = blanks[j];
			
			blanks[k].size = jobs[i].size;
			blanks[k].start = jobs[i].start;
				
			M ++;
		}
	
	}
	
	for(int j = i + 1; j < K; j ++)//覆盖法,从内存中的作业队列中删除它 
		jobs[j - 1] = jobs[j];
	K --;
}

void show()
{
	cout << "----------------------当前内存信息----------------------" << endl; 
	
	cout << "空白分区表:" << endl; 
	for(int i = 0; i < M; i ++)
		cout << "第 " << i << " 空白分区 :" << "起始地址 " << blanks[i].start << " 分区大小 " << blanks[i].size << endl;
	cout << "已分配区表: " << endl;
	for(int i = 0; i < K; i ++)
			cout << "第 " << i << " 已分配分区 :" << "分配作业名 " << jobs[i].name << " 起始地址 " << jobs[i].start << " 分区大小 " << jobs[i].size << endl;
	cout << "----------------------当前内存信息----------------------" << endl; 
	cout << endl; 
}

int main()
{
	cout << "最坏适应算法的模拟,内存总大小为1024KB" << endl;
	
	init();
	
	while(1)
	{
		int op;
		cout << "插入作业请输入1,回收作业请输入0,紧凑请输入2, 查看内存信息请输入3,退出程序请输入4" << endl;
		cin >> op;
		if(op == 4) return 0;
		
		if(op == 1) 
		{
			add();//插入作业 	
			sort(blanks, blanks + M);//按size从小到大排序 
		}
		else if(op == 0) 
		{
			recycle();//回收作业
			sort(blanks, blanks + M);//按size从小到大排序 
		}
		else if(op == 2) tight();//紧凑 
		else if(op == 3) show();//显示内存信息 
		show();//显示内存信息 
	}
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值