仅仅是一个最简单的内存模拟……
规 则:
我们拥有长度为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<<" NULL Could not find the assigned area. "<<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<<" The ID does not exist. "<<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<<" Size ID T/F"<<endl; while(p1!=NULL) { cout<<p1->data<<" "<<p1->id<<" "; 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<<" Size ID T/F"<<endl; while(p1!=NULL) { cout<<p1->data<<" "<<p1->id<<" "; 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<<" NULL Could not find the assigned area. "<<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<<" The ID does not exist. "<<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