仅仅是一个最简单的内存模拟……
规 则:
我们拥有长度为m字节的内存,输入的第一行是两个整数,分别代表对内存的操作次数以及m的大小,输入的第二行是一个字符串,也就程序中所支持的三种操作:
1.alloc n – 分配n字节的连续内存,并输出被分配的内存块的id;
2.erase x – 释放id为x的内存块;
3.defragment – 对内存进行碎片整理。
首先我们来规定:
1.第一块成功分配的内存的id为1,第二块为2,以此类推;
2.执行alloc操作所开盘的内存必须是连续的,如果有多块符合这一条件的内存块,选择最靠前的那块来分配。如果不能分配这个大小的连续空闲内存块,则输
出“提示信息”;
3.erase操作释放完的内存可以重新使用,如果要释放的内存块在内存中没有找到,则返回“该内存块未找到”的提示信息,如果分配成功则不输出任何东西;
4.defragment操作将使所有内存尽量向前靠近,不打乱他们原本的顺序。
模拟内存分配(链表实现)
- 既然是链表实现,一定少不了这个咯!每一个节点记录此处的ID以及该区域内存大小data,布尔型变量t代表这里是否已被占用。
struct ab
{
int data;
int id;
bool t;
struct ab* next;
};
- 主程序呢,比较简单,主要是提示信息以及控制操作次数和输入,部分变量已定义为全局变量,比如mail。最重要的功能还在mallo/search/bing这几个函数里面!
int main()
{
int n;
cout<<"Please enter the number of operations and total memory size"<<endl;
cin>>n>>mall;
struct ab *head=NULL;
while(n--)
{
string a;
int size,id;
struct ab *aa=head;
cout<<"Please enter the operation to be performed: ";
cin>>a;
if(a=="alloc")
{
cout<<"Please enter the size you want to allocate memory: ";
cin>>size;
aa=mallo(head,size);
if(aa==NULL)cout<<"\n\nNULL\tCould not find the assigned area.\n"<<endl;
else head=aa;
}
else if(a=="erase")
{
cout<<"Please enter a ID that needs to be freed: ";
cin>>id;
if(search(head,id)==0)cout<<"\nThe ID does not exist.\n"<<endl;
}
else if(a=="defragment")
head=bing(head);
if(aa!=NULL)print(head);
}
return 0;
}
- 这是mallo函数,之前在主函数里面定义head=NULL,因此第一次分配内存的时候整个内存都是空的(NULL),所以使用if(head==NULL){} 实现建立一个链表的头节点,并且返回头节点的地址,成功分配内存则赋值给head。
- 若第二次调用mallo函数,而此时head不是NULL,则从头遍历整个链表,若发现有一段内存未用并且大于需要分配的内存大小(p1->data>size&&p1->t==false),则用两个结构体指针,一个指向此时的位置,另一个新开辟一个节点,表示完成这次分配内存后该区域剩余的内存,而当前分配的空间则缩小到指定大小,然后将新节点插入到链表这个位置中这样就模拟出了内存分配。
- 假如遍历的时候刚好碰见和指定大小一样的一段空内存,这样的话就把该段内存标记为已占用的就可以了,p1->t=true;要是遍历到最后一个区域,也就是前面内存空缺的位置还是不满足指定的要求,需要在最后面分配,这是先检测最后面的区域大小是否符合,若不符合,返回NULL,代表未成功分配内存,若符合,便和上面的情况一样了,新建一个节点来储存剩余内存的信息,而此时的节点就将大小缩小到指定大小,节点内标记为已占用。
- 代码中的k便是检测前面是否已经分配,若分配k==false,若没有成功分配k==true;这样便是内存最后面的区域了!成功分配返回head,未成功分配返回NULL,其他操作就在主函数里面了。
int di=1,mall;
ab* mallo(struct ab *head,int size)
{
struct ab *p1=head,*p2=head;
if(head==NULL)
{
if(size>mall)return NULL;
p1=(struct ab*)malloc(len);
p1->data=size;
p1->id=di++;
p1->t=true;
p1->next=NULL;
return p1;
}
else
{
bool k=false;
int s=0;
while(p1!=NULL)
{
p2=p1;
s+=p1->data;
if(p1->data>size&&p1->t==false)
{
p2=(struct ab*)malloc(len);
p2->data=p1->data-size;
p2->t=false;
p2->id=0;
p2->next=p1->next;
p1->data=size;
p1->t=true;
p1->id=di++;
p1->next=p2;
k=true;
break;
}
else if(p1->data==size&&p1->t==false)
{
p1->id=di++;
p1->t=true;
k=true;
break;
}
else p1=p1->next;
}
if(k==false)
{
if(mall-s>=size)
{
p1=(struct ab*)malloc(len);
p1->next=NULL;
p2->next=p1;
p1->data=size;
p1->t=true;
p1->id=di++;
}
else return NULL;
}
}
return head;
}
- 最重要的一个已经说完了,search这个功能实现很简单,假如释放一个指定ID的内存,把该内存标记为未被占用(false)就行,假如ID未找到,返回 0,找到并成功释放,返回1,判断的条件当然在主函数啦!
int search(struct ab *p,int id)
{
bool k=false;
while(p!=NULL)
{
if(p->id==id)
{
p->t=false;
k=true;
break;
}
p=p->next;
}
if(k==false)return 0;
return 1;
}
- 嗯,这个功能是实现内存整理的,本来可以将标记为(false)的内存块大小变为0,就能实现,不过既然是模拟内存分配,就要把未被分配的内存节点从链表中摘下来,好像有delete这个函数可以把摘下来的内存在计算机内存(此内存非彼内存)中释放!但终究没有加入,下面的代码,第四行,是除去整个内存开始的空区域,将头节点重新选择至链表中第一个出现的已占用的区域,然后在循环里面用p2遍历下面连续的空区域,重新连接整个链表,最后便把链表中标记(false)的区域都摘除了下来!返回新链表的头节点head;
ab* bing(struct ab* head)
{
struct ab *p1=head,*p2=head;
while(p1!=NULL&&p1->t==0)p1=p1->next;
head=p1;
while(p1!=NULL)
{
if(p1->next==NULL)return head;
else p2=p1->next;
while(p2!=NULL&&p2->t==0)p2=p2->next;
p1->next=p2;
p1=p2;
}
return head;
}
- 最后一个功能,输出整个链表,这样大家便可以查看到此时的内存分配状况了!
void print(struct ab *p1)
{
cout<<"\nSize\tID\tT/F"<<endl;
while(p1!=NULL)
{
cout<<p1->data<<"\t"<<p1->id<<"\t";
if(p1->t==true)cout<<"true"<<endl;
else cout<<"false"<<endl;
p1=p1->next;
}
cout<<endl;
}
- 好了,用链表模拟内存的分配就是这样。
下面附上完整源代码:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string>
using namespace std;
#define len sizeof(struct ab)
struct ab
{
int data;
int id;
bool t;
struct ab* next;
};
int di=1,mall;
ab* mallo(struct ab *head,int size)
{
struct ab *p1=head,*p2=head;
if(head==NULL)
{
if(size>mall)return NULL;
p1=(struct ab*)malloc(len);
p1->data=size;
p1->id=di++;
p1->t=true;
p1->next=NULL;
return p1;
}
else
{
bool k=false;
int s=0;
while(p1!=NULL)
{
p2=p1;
s+=p1->data;
if(p1->data>size&&p1->t==false)
{
p2=(struct ab*)malloc(len);
p2->data=p1->data-size;
p2->t=false;
p2->id=0;
p2->next=p1->next;
p1->data=size;
p1->t=true;
p1->id=di++;
p1->next=p2;
k=true;
break;
}
else if(p1->data==size&&p1->t==false)
{
p1->id=di++;
p1->t=true;
k=true;
break;
}
else p1=p1->next;
}
if(k==false)
{
if(mall-s>=size)
{
p1=(struct ab*)malloc(len);
p1->next=NULL;
p2->next=p1;
p1->data=size;
p1->t=true;
p1->id=di++;
}
else return NULL;
}
}
return head;
}
int search(struct ab *p,int id)
{
bool k=false;
while(p!=NULL)
{
if(p->id==id)
{
p->t=false;
k=true;
break;
}
p=p->next;
}
if(k==false)return 0;
return 1;
}
void print(struct ab *p1)
{
cout<<"\nSize\tID\tT/F"<<endl;
while(p1!=NULL)
{
cout<<p1->data<<"\t"<<p1->id<<"\t";
if(p1->t==true)cout<<"true"<<endl;
else cout<<"false"<<endl;
p1=p1->next;
}
cout<<endl;
}
ab* bing(struct ab* head)
{
struct ab *p1=head,*p2=head;
while(p1!=NULL&&p1->t==0)p1=p1->next;
head=p1;
while(p1!=NULL)
{
if(p1->next==NULL)return head;
else p2=p1->next;
while(p2!=NULL&&p2->t==0)p2=p2->next;
p1->next=p2;
p1=p2;
}
return head;
}
int main()
{
int n;
cout<<"Please enter the number of operations and total memory size"<<endl;
cin>>n>>mall;
struct ab *head=NULL;
while(n--)
{
string a;
int size,id;
struct ab *aa=head;
cout<<"Please enter the operation to be performed: ";
cin>>a;
if(a=="alloc")
{
cout<<"Please enter the size you want to allocate memory: ";
cin>>size;
aa=mallo(head,size);
if(aa==NULL)cout<<"\n\nNULL\tCould not find the assigned area.\n"<<endl;
else head=aa;
}
else if(a=="erase")
{
cout<<"Please enter a ID that needs to be freed: ";
cin>>id;
if(search(head,id)==0)cout<<"\nThe ID does not exist.\n"<<endl;
}
else if(a=="defragment")
head=bing(head);
if(aa!=NULL)print(head);
}
return 0;
}
程序截图:
执行的操作:
1.alloc n – 分配n字节的连续内存,并输出被分配的内存块的id;
2.erase x – 释放id为x的内存块;
3.defragment – 对内存进行碎片整理。
- 6 10
- alloc 5
- alloc 3
- erase 1
- alloc 6
- defragment
- alloc 6