一、实验内容
设计程序模拟四种动态分区分配算法:首次适应算法、循环首次适应算法、最佳适应算法和最坏适应算法的工作过程。假设内存中空闲分区个数为n,空闲分区大小分别为P1, … ,Pn,在动态分区分配过程中需要分配的进程个数为m(m≤n),它们需要的分区大小分别为S1, … ,Sm,分别利用四种动态分区分配算法将m个进程放入n个空闲分区,给出进程在空闲分区中的分配情况。
二、C++代码
#include<iostream>
#include<string>
#include<list>
using namespace std;
#define MaxNum 100
typedef struct Node{//每个分区用一个结点表示
int index;//表示该分区是第几分区,例如:第1分区、第2分区
list<string> process;//用来存放进程名
struct Node *next;//指向下一个分区
struct Node *before;//指向前一个分区
int orilen;//原始的分区大小
int length;//现在的分区大小
}Node,*NodeLink;
int index[MaxNum];
int pnum,snum;
string name[MaxNum];
int length[MaxNum];
void print(int pnum,int snum,string name[],int index[],NodeLink space){
//打印输出
Node *p = space,*q;
int count = 0;
for(int i=0;i<pnum;i++){
cout<<name[i]<<"在分区"<<index[i]<<endl;
}
do{
cout<<"第"<<p->index<<"分区有进程:";
list<string>::iterator itor;
itor = p->process.begin();
while(itor!=p->process.end()){
cout<< *itor++;//输出作业名
}
q = p;
p = p->next;
++count;
free(q);
cout<<endl;
} while (p != space && count != snum);
cout<<endl;
cout<<"-------------------------"<<endl;
}
NodeLink sort(NodeLink begin){
//对空闲分区进行从小到大的排序
Node *temp = begin->next,*p,*q,*node;
//将链表置空
node = begin;
begin->next = begin;
begin->before = begin;
bool tag;
while(temp!=node){
//保存原链表中temp的下一个节点
tag = true;
q = temp->next;
//找到temp插入的位置
for(p = begin;(p != begin || tag)&& p->length < temp->length ; p=p->next) {
tag = false;
}
//将temp插入到p之前
temp->next = p;
temp->before = p->before;
p->before->next = temp;
p->before = temp;
if (p == begin && p->length > temp->length){
begin = temp;
}
//将temp指向要插入的下一个节点
temp = q;
}
begin->before->next = begin;
return begin;
}
void FF(int pnum,int snum,string name[],int length[],Node *space){
//首次适应算法
Node *flag;//用来标志
for (int i = 0; i < pnum; i++){
flag = space;//从第一个分区开始查找
do{
if(length[i] <= flag->length){//分区内存是否够分配作业
flag->length -= length[i];//分区大小减去作业大小
index[i] = flag->index;//保存作业在位置
flag->process.push_back(name[i]);//保存进程名
break;
}else{
flag = flag->next;//下一个分区
}
} while (flag != space);//是否查找过所有的分区,避免出现死循环的情况
}
cout<<"首次适应算法"<<endl;
print(pnum,snum,name,index,space);//打印输出结果
}
void NF(int pnum,int snum,string name[],int length[],Node *space){
//循环适应算法
Node *flag = space,*end;//flag指向每一轮开始分配的分区,用于遍历分区,end用于保存flag开始的位置
bool tag;//用于区分以下两种情况
for (int i = 0; i < pnum; i++){
//flag == end有两种情况,
//一种是查找的第一个分区就能够分配作业
//另一种是查找过所有的分区了,而都不足以分配作业的情况
tag = true;
end = flag;//保存flag开始的位置
while (length[i] > flag->length){//查找分区内存够分配作业
flag = flag->next;
if (end == flag){//判断是否已经查找过所有的分区了,若是的话则退出,避免陷入死循环
tag = false;
break;
}
}
if (tag || flag != end){//找到可分配的分区
flag->length -= length[i];//分区大小减去作业大小
index[i] = flag->index;//保存作业在位置
flag->process.push_back(name[i]);//保存进程名
flag = flag ->next;//指向下一个分区
}
}
cout<<"循环适应算法"<<endl;
print(pnum,snum,name,index,space);
}
void BF(int pnum,int snum,string name[],int length[],Node *space){
//最佳适应算法
Node *flag,*temp;//flag用于遍历分区,temp用于重新进行分区的排序标记flag要插入的位置
bool tag;//用于区分以下两种情况
space = sort(space);//将分区按照从小到大进行排序
for (int i = 0; i < pnum; i++){
//flag == space有两种情况,
//一种是每一次查找的第一个分区就能够分配作业
//另一种是查找过所有的分区了,而都不足以分配作业的情况
tag = true;
flag = space;//指向最小的分区
//从最小的分区开始查找大小最适合的空闲分区
while (length[i] > flag->length){
flag = flag->next;
if (flag == space){//判断是否已经查找过所有的分区了,若是的话则退出,避免陷入死循环
tag = false;
break;
}
}
if (tag || flag != space){//找到可分配的分区
flag->length -= length[i];//分区大小减去作业大小
index[i] = flag->index;//保存作业在位置
flag->process.push_back(name[i]);//保存进程名
if (flag == space)continue;//若flag就是第一个分区,则不用再排序
//开始重新排序,不用sort()方法,因为没必要
temp = space;//从第一个分区开始往后查找
while(temp->length <= flag->length){//遍历分区,直到找到合适的位置
temp = temp->next;
}
//将flag指向的分区插入到刚才找到的位置
flag->before->next = flag->next;
flag->next->before = flag->before;
flag->before = temp->before;
flag->next = temp;
temp->before->next = flag;
temp->before = flag;
//判断temp是否是space,若是的话,说明flag指向的分区现在的大小是所有分区中最小的,要更改space的值
if (temp == space){
space = flag;
}
}
}
cout<<"最佳适应算法"<<endl;
print(pnum,snum,name,index,space);
}
void WF(int pnum,int snum,string name[],int length[],Node *space){
//最坏适应算法
Node *end,*p;
space = sort(space);//将分区按照从小到大进行排序
for (int i = 0; i < pnum; i++){
end = space ->before;//end指向最大的分区
if (end->length > length[i]){//若最大的分区可以分配内存给该作业
index[i] = end->index;//保存作业在位置
end->process.push_back(name[i]);//保存进程名
end->length -= length[i];//分区大小减去作业大小
for (p = end->before;p != end && p->length >= end->length;p = p->before){
//遍历分区,直到找到合适的位置
}
//判断p是否指向end,若是则说明end指向的分区现在的大小是所有分区中最小的,要更改space的值
if (p != end){
//将end指向的分区插入到刚才找到的位置
end->before->next = end->next;
end->next->before =end->before;
end->before->next = end->next;
end->next->before = end->before;
end->before = p;
end->next = p->next;
p->next->before = end;
p->next = end;
}else{
space = end;
}
}
}
cout<<"最坏适应算法"<<endl;
print(pnum,snum,name,index,space);
}
NodeLink create(int snum,int space[]){
//构造双向循环链表
Node *p,*node,*q;
int i;
for(i=0;i<snum;i++){
q = new Node;
// cin>>q->length;
q->length = space[i];
q->index = i + 1;
q->orilen = q->length;
if (i == 0){
q->before = NULL;
node = q;
p = q;
}else{
p->next = q;
q->before = p;
q->next = NULL;
p = q;
}
}
node->before = q;
q->next = node;
return node;
}
int main(int argc, char* argv[])
{
//int pnum = 3,snum = 4,slen,i;
int i;
cout<<"请输入待分配的作业数:";
cin>>pnum;
//string name[3] = {"a","b","c"};
//int length[3] = {8,12,35};
cout<<"请输入作业名称:";
for(i=0;i<pnum;i++){
cin>>name[i];
}
cout<<"请输入作业的大小:";
for(i=0;i<pnum;i++){
cin>>length[i];
}
cout<<"请输入空闲分区的个数:";
cin>>snum;
int space[MaxNum];
//= {64,8,16,32};3
cout<<"请输入空闲分区的大小:";
for(i=0;i<snum;i++){
cin>>space[i];
}
Node *node;
string temp;
for (i = 0; i < pnum; i++){
cout<<name[i]<<" "<<length[i]<<endl;
}
cout<<endl;
while (1){
cout<<"输入你要执行的操作:"<<endl;
cout<<"1-FF(首次适应算法),2-NF(循环首次适应算法),3-BF(最佳适应算法),4-WF(最坏适应算法),5-退出:";
cin>>i;
if (i == 1){
node = create(snum,space);
FF(pnum,snum,name,length,node);
}else if (i == 2){
node = create(snum,space);
NF(pnum,snum,name,length,node);
}else if (i == 3){
node = create(snum,space);
BF(pnum,snum,name,length,node);
}else if (i == 4){
node = create(snum,space);
WF(pnum,snum,name,length,node);
}else{
break;
}
}
return 0;
}