内存管理(链表,指针操作,繁琐)

来源:互联网 发布:淘宝网分析 编辑:程序博客网 时间:2024/05/22 11:45
内存管理
Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u
Submit Status Practice FZU 1893

Description

在为进程动态分配内存时,操作系统必须对其进行管理。一种管理内存的方式是,维护一张记录内存使用情况的表来模拟内存的存储情况,其任一表项可能是以下两种情况之一:一个已分配给进程的内存区或者一个空闲的内存区。表中每一个表项含有以下内容:空闲区或已使用内存区的指示标志、内存大小、指向下一表项的指针。
一个表项一般有一个前驱表项和一个后继表项(除非这个表项是内存的最底端或最顶端),已使用区表项的前驱表项和后继表项可能是已使用区表项也可能是空闲区表项,而空闲区表项的前驱表项和后继表项只可能是已使用区表项,因为如果两个空闲区表项如果互为相邻的表项,我们就可以将它们合并为一个空闲区表项,内存大小为两个空闲区表项之和。
当系统创建一个新的进程时,有很多种方法可以用来为新创建的进程分配内存,在这里我们假设已知新进程要占用的内存大小,并只可能给进程分配连续的内存空间。在本题中,我们采用最佳适配算法来分配内存。最佳适配算法搜索整个表,找出够用的最小的空闲区(如有多个,取表中最前的),并将新进程分配在空闲区的顶部,如有剩余内存仍作为空闲区表项,并且为新已使用区表项的下一表项。
当系统结束一个进程时,在整个表中找到相应的已使用区表项并将其变为空闲区表项。
你的任务是编写一个程序,来实现这样一个内存管理的过程。在本题中,初始时内存表只有一个内存空闲区表项,且内存大小为100个单位大小。

Input

输入数据第一行为一整数T,表示有T组输入数据。
每组数据每行是一个系统命令,包括“Create”,“Delete”,“Print”,“End”,每条命令后面的参数如下:
Create:两个整数i和size,i表示新进程的进程号,i>0,size表示新进程需占用的内存大小,size>0,输入保证新进程的进程号与已存在的进程号不同。
Delete:一个整数i,i>0,表示要结束的进程号。
Print:无参数。
End:无参数,不做任何处理,表示系统终止命令。
注意:输入保证出现的表项个数不超过100个。

Output

对于Create命令,如果成功创建新进程,输出一行“Create process i of size s successfully!”,其中i为新进程的进程号,s为新进程占用的内存大小;如果无足够大小的内存空闲区,输出一行“No enough memory!”。
对于Delete命令,如果成功结束进程,输出一行“Delete process i of size s successfully!”,其中i为结束进程的进程号,s为该进程占用的内存大小;如果内存中无该进程,输出一行“No such process!”。
对于Print命令,将内存表从表头开始按顺序输出,每行输出一个表项,进程表项格式为“P 进程号 内存大小”,空闲区表项格式为“H 内存大小”。
对于End命令,不做任何处理,终止程序。

Sample Input

2Create 1 30Create 2 20Create 3 30PrintCreate 4 100Delete 4Delete 2PrintDelete 3PrintEndCreate 1 100PrintEnd

Sample Output

Create process 1 of size 30 successfully!Create process 2 of size 20 successfully!Create process 3 of size 30 successfully!P 1 30P 2 20P 3 30H 20No enough memory!No such process!Delete process 2 of size 20 successfully!P 1 30H 20P 3 30H 20Delete process 3 of size 30 successfully!P 1 30H 70Create process 1 of size 100 successfully!P 1 100

这题本来以为不容易,觉得很容易会TLE,可后来发觉其实复杂度也不高,因为表项不超过100,所以可以放心地疯狂地遍历。。。

debug了很久,一堆小错误。。。

AC CODE(编得不好)

//Memory: 240 KBTime: 0 MS//Language: GNU C++Result: Accepted#include <iostream>#include <cstdio>#include <memory.h>using namespace std;struct Node{    int size;  //记录这块内存空间的大小    bool used;  //标记这块内存是否被占用    int idx;  //这块内存的编号    int id;  //占用这块内存区域的是编号为idx的进程    Node *next;    Node *pre;}dum, m[300];char str[7];int i, s, T, k;int p[1001]; //两个功能:1.储存进程所在表项编号,2.q[i]为-1时表明进程不存在void Init(){    dum.pre = NULL;    dum.size = 0;    for(int j = 0; j  < 300; j++)    {        m[j].pre = m[j].next = NULL;        m[j].used = false;        m[j].size = 0;        m[j].idx = j;    }    m[0].size = 100;    dum.next = &m[0];    m[0].pre = &dum;    memset(p, -1, sizeof(p));    k = 1;}int main(){    Init();    scanf("%d",&T);    while(1)    {        scanf("%s", str);        //CREAT        if(str[0] == 'C')        {            scanf("%d%d", &i, &s);            int minsize = 101;  //用大小为minsize的内存区域储存新进程            int minidx;  //内存的编号            for(struct Node *h = dum.next; h != NULL; h = h ->next)            {                if(!h ->used && h ->size >= s && h ->size < minsize)                {                    minsize = h ->size;                    minidx = h ->idx;                }            }            if(minsize == 101)            {                puts("No enough memory!");                continue;            }            printf("Create process %d of size %d successfully!\n", i, s);            m[minidx].used = true;            m[minidx].id = i;            if(minsize != s)  //有多余空间时才创建空表项            {                m[k].size = minsize - s;                m[k].pre = &m[minidx];                m[k].next = m[minidx].next;                m[minidx].next = &m[k];                k++;            }            m[minidx].size = s;            p[i] = minidx;  //记录编号为i的进程储存在哪一个内存区域        }        //DELETE        else if(str[0] == 'D')        {            scanf("%d", &i);            if(p[i] < 0)            {                puts("No such process!");                continue;            }            int t = p[i];  //获取要删除的进程所在的内存编号            printf("Delete process %d of size %d successfully!\n", i, m[t].size);            p[i] = -1;  //重设为-1,表明这个进程已经被删除            m[t].used = false;  //重新标记为未使用            if(!(m[t].pre ->used) && m[t].pre != &dum)  //上一表项空闲,则合并            {                m[t].size += m[t].pre ->size;                m[t].pre ->size = 0;                m[t].pre ->pre ->next = &m[t];                m[t].pre = m[t].pre ->pre;            }            if(m[t].next != NULL && !(m[t].next ->used))  //下一表项空闲,则合并            {                m[t].size += m[t].next ->size;                m[t].next ->size = 0;                if(m[t].next ->next != NULL)                    m[t].next ->next ->pre = &m[t];                m[t].next = m[t].next ->next;            }        }        else if(str[0] == 'P')        {            for(struct Node *h = dum.next; h != NULL; h = h ->next)            {                if(h ->used)                    printf("P %d %d\n", h ->id, h ->size);                else                    printf("H %d\n", h ->size);            }        }        else        {            T--;            if(!T) break;            Init();        }    }    return 0;}