模拟内存分配(链表实现)

仅仅是一个最简单的内存模拟……


规 则: 


我们拥有长度为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

迷失在幽谷中的鸟儿,独自飞翔在这偌大的天地间,却不知自己该飞往何方……


原文地址:https://www.cnblogs.com/im0qianqian/p/5989554.html