#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
#include<math.h>
#define Free 0 //空闲状态
#define Busy 1 //已用状态
#define OK 1 //成功
#define ERROR 0 //失败
#define ENC 40960 //空闲内存空间最大限
#define PNC 40960 //申请内存空间最大限制
#define TC 10 //测试次数
#define pi 3.1415926535897932384626 //pi值,正太分布函数
#define MAX_Length (256*1024) //最大内存空间256MB
#define MIN_Length (56*1024) //系统保留区
typedef unsigned long DIZHI;
void ChuShiHuaNC(DIZHI,DIZHI); //初始化内存
int ShenQingNC(unsigned long,int); //申请内存
int HuiShouNC(DIZHI); //回收内存
int First_fit(unsigned long); //首次适应算法
int Next_fit(unsigned long); //循环首次适应算法
int Best_fit(unsigned long); //最佳适应算法
int Worst_fit(unsigned long); //最坏适应算法
void Sort_Array(int); //排序
void Initblock(); //带头结点的内存空间链表
void InitNC(int); //初始化空闲分区表
void Print1(); //输出空闲分区表
void PrintID(int); //输出记录
void show(); //输出内存函数
void RandTest(); //产生测试随机数
double randn(double miu,double sigma, int min ,int max);
int m = 1; //选择条用哪个算法来处理
int TNC[5000] = {0};
int Tf[5000] = {0};
int sum11 = 0;
int id_flag_nf[10000] = {0};
int sx = 0,tx = 0;
int countnf[5000] = {0};
int countnfc = -1;
int count = 0; //记录分区号
int TCount = 0;
int id_flag_ff[5000] = {0};
int countff[5000] = {0};
int countffc = -1;
int sumsum = 0;
double sumt[5000] = {0};
int id_flag_bf[10000] = {0};
int countbf[5000] = {0};
int countbfc = -1;
int id_flag_wf[10000] = {0};
int countwf[5000] = {0};
int countwfc = -1;
int idf = 1;
int x = 10;
typedef struct FreeArea //空闲分区表结构
{
int ID,state; //状态
unsigned long size; // 分区大小
DIZHI address; //地址
}ElemType;
typedef struct DulNode //双向链表
{
ElemType data; //分区数据
struct DulNode * prior; //前驱指针
struct DulNode * next; //后继指针
}DulNode,*DulLinkList;
DulLinkList first_node; //头结点
DulLinkList last_node; //尾节点
DulLinkList r;
void Initblock() { //双链表初始化
first_node = (DulLinkList)malloc(sizeof(DulNode));
last_node = (DulLinkList)malloc(sizeof(DulNode));
first_node->prior = NULL;
first_node->next = last_node;
last_node->prior = first_node;
last_node->next = NULL;
first_node->data.ID = 0;
first_node->data.size = MIN_Length - 1; //0到56MB-1为系统保留区
first_node->data.state = Busy;
first_node->data.address = 0;
last_node->data.ID = 1;
last_node->data.size = MAX_Length - MIN_Length;
last_node->data.state = Free;
last_node->data.address = MIN_Length;
}
void clearNC()
{
DulLinkList d = first_node->next;
d = d->prior;
while(1)
{
if(d->next!=NULL)
{
first_node = first_node->next;
d = d->next;
free(first_node->prior);
}
else
{
//free(first_node);
break;
}
}
sum11 = 0;
count = 0;
sx = 0,tx = 0;
countnfc = -1;
TCount = 0;
countffc = -1;
sumsum = 0;
countbfc = -1;
countwfc = -1;
idf = 1;
int i =0;
for(i=0;i<5000;i++)
{
id_flag_nf[i] = 0;
id_flag_ff[i] = 0;
id_flag_bf[i] =0;
id_flag_wf[i] =0;
countbf[i] =0;
countff[i] =0;
countnf[i] =0;
countwf[i] =0;
sumt[i] =0;
}
}
void ChuShiHuaNC(DIZHI zKS_KYNC,DIZHI zJS_KYNC) { //空闲块链表建立
DulLinkList p = (DulLinkList)malloc(sizeof(DulNode));
p->data.address = zKS_KYNC;
p->data.ID = count + 1; //分区号从1开始
p->data.size = zJS_KYNC - zKS_KYNC;
p->data.state = Busy;
p->prior = last_node->prior; //双链表插入节点
last_node->prior->next = p;
p->next = last_node;
last_node->prior = p;
count = count + 1;
last_node->data.ID = count+1;
last_node->data.address = zJS_KYNC;
last_node->data.size = MAX_Length - zJS_KYNC;
last_node->data.state = Free;
TCount = count;
}
void show()
{
int i = 0;
DulLinkList sr = first_node->next;
sr = sr->prior;
printf("当前内存状况\n");
printf("ID\t内存大小\t内存地址\t状态\n");
for(i = 0;;i++)
{
if(sr!=NULL)
{
printf("%d\t%d\t\t%d\t\t%d\n",sr->data.ID,sr->data.size,sr->data.address,sr->data.state);
if(sr->next!=NULL)
sr = sr->next;
else
break;
}
}
}
void RandTest()
{
FILE* fileout;
fileout = fopen("申请内存大小.txt","wt");
int i = 0,a;
double miu = PNC / TC;
double sigma = (PNC - miu) / TC;
int min = 1;
int max = PNC;
srand(time(0)); //随机数种子
for(i = 0;i<x;i++)
{
a = (int)randn(miu,sigma,min,max); //正态分布产生随机种子
TNC[i] = a;
fprintf(fileout,"%d\n",TNC[i]);
Tf[i] = rand()% (MAX_Length - MIN_Length) + MIN_Length;
}
}
void InitNC(int m) //空闲分区链的建立
{
int i = 0,a = 0,sum = 0,c = 0,b,mh;
double decide;
double miu = PNC / TC;
double sigma = (PNC - miu) / TC;
int min = 1;
int max = PNC;
FILE *fileout1;
if(m == 1)
{
fileout1 = fopen("内存利用率ff.txt","wt");
}
if(m == 2)
{
fileout1 = fopen("内存利用率nf.txt","wt");
}
if(m == 3)
{
fileout1 = fopen("内存利用率bf.txt","wt");
}
if(m == 4)
{
fileout1 = fopen("内存利用率wf.txt","wt");
}
Initblock();
srand(time(0)); //随机数种子
for(i = 0;i<x;i++)
{
decide = rand()*1.0 / RAND_MAX;
if(decide > 0.5||i<3)
{
a = TNC[i];
printf("申请的内存大小为:%d\n",a);
//show();
b = ShenQingNC(a,m);
if(b == 1 && sum+a < MAX_Length - MIN_Length)
sum += a;
sumt[i] = sum*1.0 / (MAX_Length - MIN_Length);
fprintf(fileout1,"%f\n",sumt[i]);
}
else
{
c = Tf[i];
//c = rand()% (MAX_Length - MIN_Length) + MIN_Length; //保证回收地址为合法的地址空间
printf("回收地址为%d\n",c);
//show();
mh = HuiShouNC(c);
printf("\n");
if(sum - mh >0)
sum -= mh;
sumt[i] = sum*1.0 / (MAX_Length - MIN_Length);
fprintf(fileout1,"%f\n",sumt[i]);
}
}
}
int First_fit(unsigned long zDX) { //首次适应算法
DulLinkList g = first_node->next; //记录头结点
g = g->prior;
countffc ++;
while(zDX > 0)
{
countff[countffc] ++;
if(g->next != NULL)
{
g = g->next;
}
else
{
return ERROR;
break;
}
if(g->data.state == Free && g->data.size == zDX) //刚好相等,改变状态位
{
g->data.state = Busy;
id_flag_ff[g->data.ID] = id_flag_ff[g->data.ID] + 1;
return OK;
break;
}
if(g->data.state == Free && g->data.size > zDX) //有空闲,划分出去
{
id_flag_ff[g->data.ID] = id_flag_ff[g->data.ID] + 1;
if(g->data.ID == last_node->data.ID && sum11 < MAX_Length - MIN_Length)
{
sum11 += zDX;
ChuShiHuaNC(MIN_Length+sum11 - zDX,MIN_Length+sum11);
return OK;
break;
}
else
{
g->data.address = g->data.address + zDX;
g->data.size = g->data.size - zDX;
return OK;
break;
}
}
}
return ERROR;
}
int Next_fit(unsigned long zDX) //循环首次适应算法
{
if(sx == 0)
{
r = first_node->next; //初始化r
r = r->prior;
sx = 1;
}
countnfc++;
int st = 0;
while(zDX > 0)
{
countnf[countnfc]++;
if(r == NULL && tx == 0)
{
r = first_node->next; //回到开头
r = r->prior;
tx = 1;
}
else if(r == NULL&& tx == 1)
{
return ERROR;
break;
}
else if(r->next != NULL)
r = r->next;
if(r->data.state == Free && r->data.size == zDX) //刚好相等,改变状态位
{
r->data.state = Busy;
id_flag_nf[r->data.ID] = id_flag_nf[r->data.ID] + 1;
return OK;
break;
}
if(r->data.state == Free && r->data.size > zDX) //有空闲,划分出去
{
id_flag_nf[r->data.ID] = id_flag_nf[r->data.ID] + 1;
sum11 += zDX;
if(sum11 < MAX_Length - MIN_Length)
{
ChuShiHuaNC(MIN_Length+sum11 - zDX,MIN_Length+sum11);
return OK;
break;
}
else
{
r->data.address = r->data.address + zDX;
r->data.size = r->data.size - zDX;
return OK;
break;
}
}
if( r->data.size < zDX && r->data.ID == last_node->data.ID && st == 0)
{
r = first_node->next;
r = r->prior;
st = 1;
}
else
{
return ERROR;
break;
}
}
}
void Sort_Array(int ud) //排序,ud为1时为升序,ud为2时为降序,ud为3按id升序
{
int a1[10000];
int a2[10000];
int a3[10000];
int a4[10000];
int ch;
DulLinkList g = first_node->next; //记录头结点
g = g->prior;
int st = 0;
int i = 0,j = 0;
for(i = 0;g->next!=NULL;i++)
{
g = g->next;
a1[i+1] = g->data.ID;
a2[i+1] = g->data.size;
a3[i+1] = g->data.address;
a4[i+1] = g->data.state;
st++;
}
if(ud == 1) //升序排列
{
for(i=1;i<=st-1;i++)
{
for(j = i+1;j <=st;j++)
{
if(a2[i] >= a2[j])
{
ch = a1[i];
a1[i] = a1[j];
a1[j] = ch;
ch = a2[i];
a2[i] = a2[j];
a2[j] = ch;
ch = a3[i];
a3[i] = a3[j];
a3[j] = ch;
ch = a4[i];
a4[i] = a4[j];
a4[j] = ch;
}
}
}
}
if(ud == 2) //降序排列
{
for(i=1;i<=st-1;i++)
{
for(j = i+1;j <=st;j++)
{
if(a2[i] <= a2[j])
{
ch = a1[i];
a1[i] = a1[j];
a1[j] = ch;
ch = a2[i];
a2[i] = a2[j];
a2[j] = ch;
ch = a3[i];
a3[i] = a3[j];
a3[j] = ch;
ch = a4[i];
a4[i] = a4[j];
a4[j] = ch;
}
}
}
}
if(ud == 3)
{
for(i=1;i<=st-1;i++)
{
for(j = i+1;j <=st;j++)
{
if(a1[i] >= a1[j])
{
ch = a1[i];
a1[i] = a1[j];
a1[j] = ch;
ch = a2[i];
a2[i] = a2[j];
a2[j] = ch;
ch = a3[i];
a3[i] = a3[j];
a3[j] = ch;
ch = a4[i];
a4[i] = a4[j];
a4[j] = ch;
}
}
}
}
while(1)
{
if(first_node->next!=NULL)
{
first_node = first_node->next;
free(first_node->prior);
}
else
{
free(first_node);
break;
}
}
Initblock();
for(i = 1;i<= st;i++)
{
DulLinkList p = (DulLinkList)malloc(sizeof(DulNode));
p->data.address = a3[i];
p->data.ID = a1[i];
p->data.size = a2[i];
p->data.state = a4[i];
if(i == st)
{
last_node->data.ID = a1[i];
last_node->data.address = a3[i];
last_node->data.size = a2[i];
last_node->data.state = a4[i];
}
else
{
p->prior = last_node->prior; //双链表插入节点
last_node->prior->next = p;
p->next = last_node;
last_node->prior = p;
}
}
}
int Best_fit(unsigned long zDX) //最佳适应算法
{
Sort_Array(1); //升序排列
//printf("排序后");
//show();
//system("pause");
countbfc++;
DulLinkList u = first_node->next; //记录头结点
u = u->prior;
while(zDX > 0)
{
countbf[countbfc]++;
if(u->next != NULL)
{
u = u->next;
}
else
{
return ERROR;
break;
}
if(u ->data.size == zDX && u->data.state == Free)
{
u->data.state = Busy;
id_flag_bf[u->data.ID] = id_flag_bf[u->data.ID] + 1;
return OK;
break;
}
if(u->data.size > zDX && u->data.state == Free)
{
id_flag_bf[u->data.ID] += 1;
if(u->data.ID == idf && sum11 < MAX_Length - MIN_Length)
{
sum11 += zDX;
Sort_Array(3);
ChuShiHuaNC(MIN_Length+sum11 - zDX,MIN_Length+sum11);
idf = last_node->data.ID;
return OK;
break;
}
else
{
u->data.address = u->data.address + zDX;
u->data.size = u->data.size - zDX;
return OK;
break;
}
return OK;
break;
}
}
return ERROR;
}
int Worst_fit(unsigned long zDX) { //最坏适应算法
Sort_Array(2); //降序排列
//printf("排序后");
//show();
//system("pause");
DulLinkList h = first_node->next; //记录头结点
h = h->prior;
countwfc++;
while(zDX > 0)
{
countwf[countwfc]++;
if(h->next != NULL) //如果没有循环到最后就继续
{
h = h->next;
}
else
{
return ERROR;
break;
}
if(h->data.size < zDX && h->data.state == Free) //如果最大都不满足,则失败
{
return ERROR;
break;
}
if(h ->data.size == zDX && h->data.state == Free)
{
h->data.state = Busy;
id_flag_wf[h->data.ID] = id_flag_wf[h->data.ID] + 1;
return OK;
break;
}
if(h->data.size > zDX && h->data.state == Free)
{
id_flag_wf[h->data.ID] = id_flag_wf[h->data.ID] + 1;
if(h->data.ID == idf && sum11 < MAX_Length - MIN_Length)
{
sum11 += zDX;
Sort_Array(3);
ChuShiHuaNC(MIN_Length+sum11 - zDX,MIN_Length+sum11);
idf = last_node->data.ID;
return OK;
break;
}
else
{
h->data.address = h->data.address + zDX;
h->data.size = h->data.size - zDX;
return OK;
break;
}
return OK;
break;
}
}
return ERROR;
}
int ShenQingNC(unsigned long zDX,int m) //申请内存
{
if(m == 1) //首次适应
{
if(First_fit(zDX))
{
printf("申请内存成功\n\n");
return OK;
}
else
{
printf("申请内存失败\n\n");
return ERROR;
}
}
if(m == 2) //循环首次适应
{
if(Next_fit(zDX))
{
printf("申请内存成功\n\n");
return OK;
}
else
{
printf("申请内存失败\n\n");
return ERROR;
}
}
if(m == 3) //最佳适应
{
if(Best_fit(zDX))
{
printf("申请内存成功\n\n");
return OK;
}
else
{
printf("申请内存失败\n\n");
return ERROR;
}
}
if(m == 4) //最坏适应
{
if(Worst_fit(zDX))
{
printf("申请内存成功\n\n");
return OK;
}
else
{
printf("申请内存失败\n\n");
return ERROR;
}
}
return ERROR;
}
int HuiShouNC(DIZHI zKSDZ) //回收内存
{
int ght = 0;
if(m == 3 || m == 4)
Sort_Array(3);
DulLinkList t = first_node->next; //记录头结点
t = t->prior;
while(zKSDZ > MIN_Length)
{
if(t->next!=NULL)
t = t->next;
if(zKSDZ < t->data.address)
{
t = t->prior;
break;
}
if(t->next == NULL)
{
break;
}
}
if(t->data.ID == 0)
t = t->next;
if(t->data.state == Busy)
ght = t->data.size;
else if(t->next!=NULL)
ght = t->next->data.address - t->prior->data.address-t->prior->data.size - t->data.size;
else if(t->prior->data.ID != 0)
ght = MAX_Length - t->prior->data.address-t->prior->data.size - t->data.size;
else
ght = MAX_Length - MIN_Length - t->data.size;
if(t->prior->data.ID == 0&&t->next!=NULL) //头节点
{
if(t->next->data.state == Free&&t->next->next!=NULL)
{
t->data.size = t->next->next->data.address-t->prior->data.address-t->prior->data.size;
t->data.state = 0;
t->next = t->next->next;
t->next->prior = t->prior->next;
}
else
{
t->data.state = 0;
t->data.size = t->next->data.address - t->prior->data.address-t->prior->data.size;
}
}
else if(t->next == NULL&&t->prior->data.ID!=0) //尾节点
{
if(t->prior->data.ID == Free)
{
t = t->prior;
t->data.size = MAX_Length - t->prior->data.address-t->prior->data.size;
t->data.state = Free;
}
else
{
t->data.state = Free;
t->data.size = MAX_Length - t->data.address;
}
}
else if(t->prior->data.ID == 0 && t->next == NULL) //只有一个分区
{
t->data.state = 0;
}
else if(t->prior->data.state == Free && t->next->data.state == Busy) //与前一分区相连
{
t->data.state = Free;
t->prior->data.address = t->prior->prior->data.address+t->prior->prior->data.size;
t->prior->data.size = t->next->data.address-t->prior->prior->data.address- t->prior->prior->data.size;
t->prior->next = t->next;
t->next->prior = t->prior;
}
else if(t->next->data.state == Free && t->prior->data.state == Busy) //与后一分区相连
{
t->data.state = Free;
t->data.address = t->prior->data.address+t->prior->data.size;
if(t->next->next!=NULL)
{
t->data.size = t->next->next->data.address - t->prior->data.address - t->prior->data.size;
t->next->next->prior = t;
t->next = t->next->next;
}
else
{
t->next->data.size = MAX_Length - t->prior->data.address - t->prior->data.size;
t->prior->next = t->next;
t->next->prior = t->prior;
}
}
else if(t->next->data.state == Free && t->prior->data.state == Free) //与前后两分区相连
{
t->data.state = Free;
t->data.address = t->prior->data.address+t->prior->data.size;
if(t->next->next!=NULL)
{
t->prior->data.size = t->next->next->data.address-t->prior->prior->data.address- t->prior->prior->data.size;
t->prior->next = t->next->next;
t->next->prior = t->prior;
}
else
{
t->next->data.size =MAX_Length-t->prior->prior->data.address- t->prior->prior->data.size;
t->prior->prior->next = t->next;
t->next->prior = t->prior->prior;
}
}
else //都不相连
{
t->data.state = Free;
t->data.address = t->prior->data.address + t->prior->data.size;
t->data.size = t->next->data.address - t->data.address;
}
return ght;
}
void PrintID(int m)
{
int i = 1;
FILE *fileout,*fileout1;
if(m==1) //首次适应算法
{
fileout = fopen("分配记录IDff.txt","wt");
fileout1 = fopen("每次申请查询次数ff.txt","wt");
while(1)
{
if(id_flag_ff[i] > 0)
{
fprintf(fileout,"%d\t%d\n",i,id_flag_ff[i]);
}
else
break;
i++;
}
int sum1 = 0;
for(i = 0;i <= countffc;i++)
{
sum1 += countff[i];
fprintf(fileout1,"%d\n",countff[i]);
}
}
if(m == 2) //循环首次适应算法
{
fileout = fopen("分配记录IDnf.txt","wt");
fileout1 = fopen("每次申请查询次数nf.txt","wt");
while(1)
{
if(id_flag_nf[i] > 0)
{
fprintf(fileout,"%d\t%d\n",i,id_flag_nf[i]);
}
else
break;
i++;
}
int sum1 = 0;
for(i = 0;i <= countnfc;i++)
{
sum1 += countnf[i];
fprintf(fileout1,"%d\n",countnf[i]);
}
}
if(m == 3) //最佳适应
{
fileout = fopen("分配记录IDbf.txt","wt");
fileout1 = fopen("每次申请查询次数bf.txt","wt");
while(1)
{
if(id_flag_bf[i] > 0)
{
fprintf(fileout,"%d\t%d\n",i,id_flag_bf[i]);
}
i++;
if(i > 4000)
break;
}
int sum1 = 0;
for(i = 0;i <= countbfc;i++)
{
sum1 += countbf[i];
fprintf(fileout1,"%d\n",countbf[i]);
}
}
if(m == 4) //最坏适应
{
fileout = fopen("分配记录IDwf.txt","wt");
fileout1 = fopen("每次申请查询次数wf.txt","wt");
while(1)
{
if(id_flag_wf[i] > 0)
{
fprintf(fileout,"%d\t%d\n",i,id_flag_wf[i]);
}
i++;
if(i > 4000)
break;
}
int sum1 = 0;
for(i = 0;i <= countwfc;i++)
{
sum1 += countwf[i];
fprintf(fileout1,"%d\n",countwf[i]);
}
fprintf(fileout1,"%f",sum1*1.0/(countwfc+1));
}
fclose(fileout);
}
double Rand(int min,int max) //产生[min,max]区间的随机数
{
return min+(max-min)*rand()/(RAND_MAX+1.0);
}
double normal(double x, double miu,double sigma) //正太分布函数
{
return 1.0/sqrt(2*pi)/sigma*exp(-1*(x-miu)*(x-miu)/(2*sigma*sigma));
}
double randn(double miu,double sigma, int min ,int max)
{
double x,y,dNC;
do{
x=Rand(min,max); //产生随机数
y=normal(x,miu,sigma); //转化为正太分布
dNC=Rand(0.0,normal(miu,miu,sigma)); //产生正太分布的随机数
}while(dNC>y); //如果不是正太分布随机数就继续
return x; //返回产生的随机数
}
void Print1()
{
FILE *fileout;
fileout = fopen("最后内存分区表.txt","wt");
int i = 0;
fprintf (fileout,"分区号\t大小/KB\t起址/KB\t状态\n");
DulLinkList q = first_node->next; //记录头结点
q = q->prior;
for(i = 0;;i++)
{
if(q->next != NULL)
q = q->next;
else
break;
fprintf(fileout,"%d\t%d\t%d\t%d\n",q->data.ID,q->data.size,q->data.address,q->data.state);
}
fclose(fileout);
}
int main()
{
printf("请输入申请内存的次数\n");
scanf("%d",&x);
printf("\t\t请选择你要测试的分配算法:\n");
printf("**************************************************\n");
printf("\t1为首次适应算法\t2为循环首次适应算法\n");
printf("\t3为最佳适应算法\t4为最坏适应算法\n");
printf("**************************************************\n");
char yn;
RandTest();
while(1)
{
printf("请选择算法:");
scanf("%d",&m);
printf("\n");
InitNC(m);
Print1();
PrintID(m);
clearNC();
printf("执行成功,结果已存入工程根目录文件中\n");
system("pause");
printf("是否继续(Y/N)\n");
getchar();
while(1)
{
scanf("%c",&yn);
if(yn =='Y'|| yn =='y' || yn == 'N' || yn == 'n')
break;
else
printf("请选择是否继续\n");
}
if(yn == 'N'|| yn == 'n')
break;
}
system("pause");
return 0;
}