有以下四种算法:
最佳适应法
最坏适应法
首次适应法
下次适应法(循环首次适应法)
1)首次适应法
从空闲分区表的第一个表目起查找该表,把最先能够满足要求的空闲区分配给作业,这种方法目的在于减少查找时间。为适应这种算法,空闲分区表(空闲区链)中的空闲分区要按地址由低到高进行排序。该算法优先使用低址部分空闲区,在低址空间造成许多小的空闲区,在高地址空间保留大的空闲区。
特点
该算法倾向于优先利用内存中低址部分的空闲分区,从而保留了高址部分的大空闲区,这为以后到达的大作业分配大的内存空间创造了条件。
缺点
低址部分不断被划分,会留下许多难以利用的,很小的空闲分区,称为碎片。而每次查找又都是从低址部分开始的,这无疑又会增加查找可用空闲分区时的开销
它从全部空闲区中找出能满足作业要求的、且大小最小的空闲分区,这种方法能使碎片尽量小。为适应此算法,空闲分区表(空闲区链)中的空闲分区要按从小到大进行排序,自表头开始查找到第一个满足要求的自由分区分配。该算法保留大的空闲区,但造成许多小的空闲区。
Best fit算法等价于装箱问题,举例如下:
装箱问题:有体积为V的箱子N个,体积为Vi的物品M个,求使得物品全部能够装入箱子,箱子数量的最小值。
假设 V=6 N=10,V1,V2,...,V10分别为:3 4 4 3 5 1 2 5 3 1。计算过程如下:
第一步按物品体积降序排序:5 5 4 4 3 3 3 2 1 1
第二步:取未装箱的最大值5装入第一个箱子。
第三步:判断第一个箱子是否已满,不满且剩余空间为1,搜寻剩下体积小于等于1的物品填入箱子1,箱子1填满。
第四步:重复第二,第三步,直到所有物品装入箱子为止,得到箱子数量为6.
6即时本例N的最小值。
4)最坏适应法
最坏适应分配算法要扫描整个空闲分区或链表,总是挑选一个最大的空闲分区分割给作业使用。该算法要求将所有的空闲分区按其容量从大到小的顺序形成一空闲分区链,查找时只要看第一个分区能否满足作业要求。
优点:可使剩下的空闲分区不至于太小,产生碎片的几率最小,对中、小作业有利,同时该算法查找效率很高。
缺点:会使存储器中缺乏大的空闲分区。
最佳适应法
最坏适应法
首次适应法
下次适应法(循环首次适应法)
1)首次适应法
从空闲分区表的第一个表目起查找该表,把最先能够满足要求的空闲区分配给作业,这种方法目的在于减少查找时间。为适应这种算法,空闲分区表(空闲区链)中的空闲分区要按地址由低到高进行排序。该算法优先使用低址部分空闲区,在低址空间造成许多小的空闲区,在高地址空间保留大的空闲区。
特点
该算法倾向于优先利用内存中低址部分的空闲分区,从而保留了高址部分的大空闲区,这为以后到达的大作业分配大的内存空间创造了条件。
缺点
低址部分不断被划分,会留下许多难以利用的,很小的空闲分区,称为碎片。而每次查找又都是从低址部分开始的,这无疑又会增加查找可用空闲分区时的开销
2)下次适应法(循环首次适应法)
称“临近适应”算法,其工作方式和最先适应算法相同(最先适应也称首次适应算法。它总是最先找到的、满足存储要求的那个空闲分区作为分配对象。),不同的是每次找到合适的空闲的分区时就记住它的位置,以便下次就从该位置开始往下查找,而不是每次都像最先适应算法那样从头开始查找。这种算法的总体结果通常要比最先适应算法差。由于它经常会在内存的末尾分配存储分区,使位于存储空间末尾的最大分区被撕裂称小的外部碎片,因此必须经常不断地进行存储紧凑。在该算法中应采取循环查找方式,即最后上个空闲区的大小仍不能满足要求时,应再从第一个空闲区开始查找,故又称为循环造就算法。
3)最佳适应法它从全部空闲区中找出能满足作业要求的、且大小最小的空闲分区,这种方法能使碎片尽量小。为适应此算法,空闲分区表(空闲区链)中的空闲分区要按从小到大进行排序,自表头开始查找到第一个满足要求的自由分区分配。该算法保留大的空闲区,但造成许多小的空闲区。
Best fit算法等价于装箱问题,举例如下:
装箱问题:有体积为V的箱子N个,体积为Vi的物品M个,求使得物品全部能够装入箱子,箱子数量的最小值。
假设 V=6 N=10,V1,V2,...,V10分别为:3 4 4 3 5 1 2 5 3 1。计算过程如下:
第一步按物品体积降序排序:5 5 4 4 3 3 3 2 1 1
第二步:取未装箱的最大值5装入第一个箱子。
第三步:判断第一个箱子是否已满,不满且剩余空间为1,搜寻剩下体积小于等于1的物品填入箱子1,箱子1填满。
第四步:重复第二,第三步,直到所有物品装入箱子为止,得到箱子数量为6.
6即时本例N的最小值。
4)最坏适应法
最坏适应分配算法要扫描整个空闲分区或链表,总是挑选一个最大的空闲分区分割给作业使用。该算法要求将所有的空闲分区按其容量从大到小的顺序形成一空闲分区链,查找时只要看第一个分区能否满足作业要求。
优点:可使剩下的空闲分区不至于太小,产生碎片的几率最小,对中、小作业有利,同时该算法查找效率很高。
缺点:会使存储器中缺乏大的空闲分区。
最坏适应算法与首次适应算法、循环首次适应算法、最佳适应算法一起,也称为顺序搜索法。
1.
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
#define MAXNUMBER 100
static int PartitionNum; //内存中空闲分区的个数
static int ProcessNum; //需要分配的进程个数
static int FreePartition[MAXNUMBER]; //空闲分区对应的内存
static int ProcessNeed[MAXNUMBER]; //需要分配的进程大小
static int LeftFreePartition[MAXNUMBER];
static int LeftProcessNeed[MAXNUMBER];
static char ProcessName[MAXNUMBER];
static char NameProcessToPartition[MAXNUMBER][MAXNUMBER];
typedef struct
{
int partitionSize;
int id;
}sortNeed;
void readDataFunction();
void display();
void FirstFit();
void NextFit();
void BestFit();
void WorstFit();
void selectAlgorithm(int chooceAlgorithm);
void display();
void readDataFunction()
{
ifstream readData;
readData.open("data.txt");
readData>>PartitionNum;
for (int i=0;i<PartitionNum;i++)
{
readData>>FreePartition[i];
}
readData>>ProcessNum;
for ( i=0;i<ProcessNum;i++)
{
readData>>ProcessName[i];
}
for ( i=0;i<ProcessNum;i++)
{
readData>>ProcessNeed[i];
}
}
void initial()
{
readDataFunction(); //读取原始数据
for (int i=0;i<ProcessNum;i++)
{
for (int j =0;j<PartitionNum;j++)
{
NameProcessToPartition[i][j] =NULL;
LeftFreePartition[j] = FreePartition[j];
}
}
for ( i = 0;i<ProcessNum;i++)
{
LeftProcessNeed[i] = ProcessNeed[i];
}
}
void FirstFit()
{
cout<<"***********首次适应算法***********"<<endl;
initial();
int i,j;
for (i = 0;i<ProcessNum;i++) //逐个遍历每个进程
{
for (j = 0;j<PartitionNum;j++) //每次都从分区的首地址开始查找
{
if (LeftProcessNeed[i] <= LeftFreePartition[j] && LeftFreePartition!=0) //当系统内存分区足够大的时候,即分配给进程资源
{
LeftFreePartition[j] -= LeftProcessNeed[i]; //扣除分配给进程的资源
LeftProcessNeed[i] = 0; //当且仅当系统内存分区足够时才执行,即当前进程大小置0
NameProcessToPartition[i][j] = ProcessName[i]; //存储各个进程所在的分区位置
break; //!!!很重要,一个进程分区完后,应该立即break,进行下一个进程的判断
}
}
}
display();
}
void NextFit()
{
cout<<"***********循环首次适应算法***********"<<endl;
initial();
int i,nextPoint = 0;
bool isWhile;
for (i = 0;i<ProcessNum;i++)
{
isWhile = true;
while(isWhile) //每次都从当前分区的下一个分区开始查找
{
if (LeftFreePartition[nextPoint] >= LeftProcessNeed[i])
{
LeftFreePartition[nextPoint] -= LeftProcessNeed[i];
LeftProcessNeed[i] = 0;
NameProcessToPartition[i][nextPoint] = ProcessName[i];
nextPoint++;
if (nextPoint > PartitionNum - 1)
{
nextPoint = 0; //当j遍历到分区末尾的时候,返回首位置
}
isWhile = false;
}
else
nextPoint++;
}
}
display();
}
void BestFit()
{
//思想:利用冒泡排序对分区大小进行排序,但不改变原分区的位置
//创建一个结构体,包括分区大小和所对应的id,排序过程中,每改变顺序一次,id随着改变
//关键:每次分配完一个进程的内存大小后,都要重新排序
cout<<"***********最佳适应算法***********"<<endl;
initial();
int i,j,temp,tempID;
sortNeed best[MAXNUMBER];
for (i = 0;i<PartitionNum;i++)
{
//初始化结构体
best[i].partitionSize = FreePartition[i];
best[i].id = i;
}
//int count2 = 0;
for (i = 0;i<ProcessNum;i++)
{
for (int s = PartitionNum - 1;s > 0;s--) //冒泡排序(每次分配完一个进程后,都需要重新排序)
{
for (int t = 0;t < s;t++)
{
if (best[s].partitionSize < best[t].partitionSize)
{
temp = best[s].partitionSize;
best[s].partitionSize = best[t].partitionSize;
best[t].partitionSize = temp;
tempID = best[s].id;
best[s].id = best[t].id;
best[t].id = tempID;
}
}
}
for (j = 0;j<PartitionNum;j++)
{
if (LeftProcessNeed[i] <= best[j].partitionSize)
{
best[j].partitionSize -= LeftProcessNeed[i];
LeftProcessNeed[i] = 0;
NameProcessToPartition[i][best[j].id] = ProcessName[i];
//count2++;
break;
}
}
LeftFreePartition[best[j].id] = best[j].partitionSize;
}
//cout<<count2<<endl;
display();
}
void WorstFit()
{
cout<<"***********最坏适应算法***********"<<endl;
initial();
int i,j,s,t,tempSize,tempID;
sortNeed Worst[MAXNUMBER];
for (i = 0;i<PartitionNum;i++)
{
Worst[i].partitionSize = FreePartition[i];
Worst[i].id = i;
}
for (i = 0;i<ProcessNum;i++)
{
for (s = PartitionNum - 1;s>0;s--)
{
for (t = 0; t<s;t++)
{
if (Worst[s].partitionSize > Worst[t].partitionSize)
{
tempSize = Worst[s].partitionSize;
Worst[s].partitionSize = Worst[t].partitionSize;
Worst[t].partitionSize = tempSize;
tempID = Worst[s].id;
Worst[s].id = Worst[t].id;
Worst[t].id = tempID;
}
}
}
for (j = 0;j<PartitionNum;j++)
{
if (LeftProcessNeed[i] <= Worst[j].partitionSize)
{
Worst[j].partitionSize -= LeftProcessNeed[i];
LeftProcessNeed[j] = 0;
NameProcessToPartition[i][Worst[j].id] = ProcessName[i];
break;
}
}
LeftFreePartition[Worst[j].id] = Worst[j].partitionSize;
}
display();
}
void selectAlgorithm(int chooseAlgorithm)
{
switch(chooseAlgorithm)
{
case 0:break;
case 1:FirstFit();break;
case 2:NextFit();break;
case 3:BestFit();break;
case 4:WorstFit();break;
default:cout<<"请输入正确的序号:"<<endl;
}
}
void display()
{
int i;
cout<<"需要分配内存的进程名:"<<setw(10);
for (i = 0;i<ProcessNum;i++)
{
cout<<ProcessName[i]<<setw(6);
}
cout<<endl;
cout<<"需要分配内存的进程分区大小:"<<setw(4);
for (i = 0;i<ProcessNum;i++)
{
cout<<ProcessNeed[i]<<setw(6);
}
cout<<endl;
cout<<"分配结果:"<<endl;
cout<<"分区序号:";
for (i = 0;i<PartitionNum;i++)
{
cout<<"分区"<<i+1<<" ";
}
cout<<endl<<"分区大小:";
for (i = 0;i<PartitionNum;i++)
{
cout<<FreePartition[i]<<" ";
}
cout<<endl<<"剩余大小:";
for (i = 0;i<PartitionNum;i++)
{
cout<<LeftFreePartition[i]<<" ";
}
cout<<endl<<"分配进程情况:"<<endl;
for (i = 0;i<PartitionNum;i++)
{
for (int j = 0;j<ProcessNum;j++)
{
if (NameProcessToPartition[j][i]!=NULL)
{
cout<<NameProcessToPartition[j][i]<<": (分区"<<i+1<<")"<<endl;
}
}
}
cout<<endl<<"********结束**********"<<endl;
}
int main()
{
int chooseAlgorithm = 5;
while(chooseAlgorithm)
{
cout<<"请选择实现的算法:"<<endl;
cout<<"***** 1 - 首次适应算法 *****"<<endl;
cout<<"***** 2 - 循环首次适应算法 *****"<<endl;
cout<<"***** 3 - 最佳适应算法 *****"<<endl;
cout<<"***** 4 - 最坏适应算法 *****"<<endl;
cout<<"***** 0 - 结束 *****"<<endl;
cout<<"chooseAlgorithm = ";
cin>>chooseAlgorithm;
selectAlgorithm(chooseAlgorithm);
}
system("pause");
return 0;
}
2.(可以运行)
#include <stdio.h>
#define L 10
struct Free_node
{
int ID;//空闲区的序号
int address;//空闲区的起始地址
int size;//空闲区的大小
int state;//分配状态:0表示未分配,1表示已分配
}Free_node[10]={{1,0,50,1},{2,150,100,1},{3,300,120,1},{4,350,150,1},{5,550,200,1},{6,800,250,1}};
int main()
{ void FirstFit();//首次适应算法
void NextFit();//循环首次适应算法
void BestFit();//最佳适应算法
void WorstFit();//最差适应算法
void recycle();//回收
void print();//打印
int sortaddress();//将空闲区按地址从小到大排列
void sortrise();//将空闲区按容量从小到大排列
int sortdown();//将空闲区按容量从大到小排列
printf("模拟动态分区分配算法以下为:");
printf("\n1、首次适应算法\n2、循环首次适应算法");
printf("\n3、最坏适应算法\n4、最佳适应算法");
printf("\n5、回收内存\n6、打印空闲分区表\n");
printf("请选择算法1~6,按enter键开始:");
while(getchar())
{int i;
scanf("%d",&i);
switch(i)
{
case 1:
FirstFit();
break;
case 2:
NextFit();
break;
case 3:
BestFit();
break;
case 4:
WorstFit();
break;
case 5:
recycle();
break;
case 6:
print();
break;
default:
printf("您的输入有误!\n");
}
}
}
int sortaddress()//将空闲区按地址从小到大排
{
int i,j;
struct Free_node t;
for(j=0;j<9;j++)
{
for(i=0;i<9-j;i++)
{
if(Free_node[i].address>Free_node[i+1].address)
{
t=Free_node[i];
Free_node[i]=Free_node[i+1];
Free_node[i+1]=t;
}
}
}
for(i=0;i<10;i++)
{
if(Free_node[i].size==0)
{
Free_node[i]=Free_node[i+1];
}
else
return 1;
}
return 0;
}
void sortrise()
{
int i,j;
struct Free_node t;
for(j=0;j<9;j++)
{
for(i=0;i<9-j;i++)
{
if(Free_node[i].size>Free_node[i+1].size)
{
t=Free_node[i];
Free_node[i]=Free_node[i+1];
Free_node[i+1]=t;
}
}
}
}
int sortdown()
{
int i,j;
struct Free_node t;
for(j=0;j<9;j++)
{
for(i=0;i<9-j;i++)
{
if(Free_node[i].size<Free_node[i+1].size)
{
t=Free_node[i];
Free_node[i]=Free_node[i+1];
Free_node[i+1]=t;
}
}
}
for(i=0;i<10;i++)
{
if(Free_node[i].size==0)
{
Free_node[i]=Free_node[i+1];
}
else
return 1;
}
return 0;
}
//首次适应算法
void FirstFit()
{
int applyarea;
int i;
printf("请输入作业申请量:\n");
scanf("%d",&applyarea);
for(i=0;i<6;i++)
{
if(Free_node[i].state==1&&Free_node[i].size>applyarea)
{
printf("申请的作业的起始地址为:%d\n",Free_node[i].address);
printf("内存分配成功!\n");
Free_node[i].address=Free_node[i].address+applyarea;
Free_node[i].size=Free_node[i].size-applyarea;
break;
}
else if(Free_node[i].state==1&&Free_node[i].size==applyarea)
{
Free_node[i].state=0;
printf("申请的作业的起始地址为:%d\n",Free_node[i].address);
printf("内存分配成功!\n");
break;
}
}
if(i==6)
{
printf("输入的作业量过大,内存分配失败!\n");
}
}
//循环首次适应算法
void NextFit()
{
int s,i,applyarea;
printf("请输入作业申请量:\n");
scanf("%d",&applyarea);
for(i=0;i<6;i++)
{
if( Free_node[i].state==0)
{
s=i;
break;
}
}
for(i=s+1;i<6;i++)//从上一个分配后的内存找下一个空闲区
{
if(Free_node[i].state==1&&Free_node[i].size>applyarea)
{
printf("申请的作业的起始地址为:%d\n",Free_node[i].address);
printf("内存分配成功!\n");
Free_node[i].address=Free_node[i].address+applyarea;
Free_node[i].size=Free_node[i].size-applyarea;
break;
}
else if(Free_node[i].state==1&&Free_node[i].size==applyarea)
{
Free_node[i].state=0;
printf("申请的作业的起始地址为:%d\n",Free_node[i].address);
printf("内存分配成功!\n");
break;
}
}
if(i==6)
{
printf("输入的作业量过大,内存分配失败!\n");
}
}
//最佳适应算法
void BestFit()
{
sortrise();
int applyarea;
int i;
printf("请输入作业申请量:\n");
scanf("%d",&applyarea);
for(i=0;i<6;i++)
{
if(Free_node[i].state==1&&Free_node[i].size>applyarea)
{
printf("申请的作业的起始地址为:%d\n",Free_node[i].address);
printf("内存分配成功!\n");
Free_node[i].address=Free_node[i].address+applyarea;
Free_node[i].size=Free_node[i].size-applyarea;
break;
}
else if(Free_node[i].state==1&&Free_node[i].size==applyarea)
{
printf("申请的作业的起始地址为:%d\n",Free_node[i].address);
printf("内存分配成功!\n");
Free_node[i]=Free_node[i+1];//如果该空闲区全部被分配,则从表中删除
break;
}
}
if(i==6)
{
printf("输入的作业量过大,内存分配失败!\n");
}
}
//最坏适应算法
void WorstFit()
{
sortdown();
int applyarea;
int i;
printf("请输入作业申请量:\n");
scanf("%d",&applyarea);
for(i=0;i<6;i++)
{
if(Free_node[i].state==1&&Free_node[i].size>applyarea)
{
printf("申请的作业的起始地址为:%d\n",Free_node[i].address);
printf("内存分配成功!\n");
Free_node[i].address=Free_node[i].address+applyarea;
Free_node[i].size=Free_node[i].size-applyarea;
break;
}
else if(Free_node[i].state==1&&Free_node[i].size==applyarea)
{
printf("申请的作业的起始地址为:%d\n",Free_node[i].address);
printf("内存分配成功!\n");
Free_node[i]=Free_node[i+1];//如果该空闲区全部被分配,则从表中删除
break;
}
}
if(i==6)
{
printf("输入的作业量过大,内存分配失败!\n");
}
}
void recycle()//回收
{
sortaddress();//先按地址大小给排序
int a,s;
int i,j;
printf("请输入需要回收的内存起始地址:");
scanf("%d",&a);
printf("请输入需要回收的内存大小:");
scanf("%d",&s);
for(i=0;i<10;i++)
{
if((Free_node[i].address==a+s)&&(Free_node[i].state==1))//回收区与下一个空闲区相邻
{
if(Free_node[i-1].address+Free_node[i-1].size ==a)//回收区与上一个空闲区也相邻
{
Free_node[i-1].size=Free_node[i-1].size+s+Free_node[i].size;
for(j=i;j<10;j++)
{
Free_node[j]=Free_node[j+1];
}break;
}
else
{
Free_node[i].address=a;
Free_node[i].size=Free_node[i].size+s;break;
}
}
else if(Free_node[i].address+Free_node[i].size ==a&&(Free_node[i].state==1))//回收区与上一个空闲区相邻
{
if(Free_node[i+1].address==a+s)
{
Free_node[i].size=Free_node[i].size+s+Free_node[i+1].size;
for(j=i+1;j<10;j++)
{
Free_node[j]=Free_node[j+1];
}break;
}
else
{
Free_node[i].size=Free_node[i].size+s;break;
}
}
}
if(i==10)//回收区无相邻的空闲区
{
for(i=0;i<10;i++)
{
if(Free_node[i].ID==0)//建立新表项
{
Free_node[i].ID=i+1;
Free_node[i].address=a;
Free_node[i].size=s;
Free_node[i].state=1;
break;
}
}
}
}
void print()//打印
{
printf("为作业分配内存后,空闲分区为:\n");
printf(" 序号 起始地址 空闲区大小\n");
int i;
sortaddress();
for(i=0;i<10;i++)
{
if(Free_node[i].state==1)
{
printf(" %d %3d %d\n",Free_node[i].ID,Free_node[i].address,Free_node[i].size);
}
}
}