7-6 对象池(object_pool)分数 10 PTA C++入门题答案

7-6 对象池(object_pool)

分数 10

全屏浏览题目

切换布局

作者 王政单位 山东大学

Java有废料回收(GC)的功能,可以回收无法再使用的内存、对象等资源。但C++就要自己负责释放动态分配的资源。身为一名软件开发者,我感到肩上的担子更重了。那么资源管理是怎样实现的呢?我查到一种用空闲链表(free list) 技术实现 对象池(object pool) 的入门级方案。

比方说有容量为C对象池Object pool[C + 1](0号是哑元不用),用空闲链表把它管起来。C++的链表听说要用深受爱戴和尊敬的指针,但指针才刚讲,来不及了,我先用数组索引模拟指针。

  • 建立空闲链表的头索引、后继数组:int head = 1, next[C + 1];

  • head为0表示没有空闲单元了,否则表示下个空闲单元的索引

  • 初始化:next[1] = 2; next[2] = 3; ... next[C] = 0;

模拟使用:

扫描二维码关注公众号,回复: 14893082 查看本文章
  • 分配对象:new

  • 如果head == 0,没有可用单元,返回0即可。

  • 如果head != 0,那么用p保存head现值,将head改为next[head],返回p表示可以使用pool[p]对象。

  • 引用对象:ref p

  • 如果p有效(在[1, C]的范围内,并且已经分配)输出ok

  • 否则error

  • 释放对象:delete p

  • 如果p == 0,输出head即可。C/C++都是这样规定,允许free(NULL)或delete nullptr)。

  • 如果p != 0,即请求归还pool[p]单元:

  • 如果p有效(在[1, C]的范围内,并且已经分配),把它放到空闲链表的头部:next[p] = head; head = p;。

  • 无效则输出error

目的:练习数组、循环、事件模拟、空闲链表技术;辅助理解指针。

输入规格

  • 首行设定对象池容量capacity C,C是正整数,小于65536。

  • 后续有若干行的分配、释放请求,处理到EOF为止。请求数量小于65536。

  • new分配操作

  • ref x引用x号单元

  • delete x释放x号单元

输出规格

  • 首行输出:capacity <C> # head=1

  • 之后逐条处理操作:

  • 原样输出操作和参数、空格、#、空格、操作结果

  • 操作结果有以下几种:

  • 分配:new # return <p>, head=<h>输出分配的单元索引p,分配之后的空闲头索引h。

  • 如果没有空闲单元,返回0。

  • 引用:ref <p> # ok或ref <p> # error

  • 释放:

  • delete <p> # head=<h>,其中p是释放的单元索引,h是调整后的空闲头索引。

  • 如p无效则输出error

样例输入

capacity 2
new   
ref 1
new   
new   
delete 2 
ref 2
delete 2 
delete 9 
delete 0 
new   
delete 1 
new   
delete 1 
delete 2 

样例输出

capacity 2 # head=1
new # return 1, head=2
ref 1 # ok
new # return 2, head=0
new # return 0, head=0
delete 2 # head=2
ref 2 # error
delete 2 # error
delete 9 # error
delete 0 # head=2
new # return 2, head=0
delete 1 # head=1
new # return 1, head=0
delete 1 # head=1
delete 2 # head=2

代码长度限制16 KB

时间限制400 ms

内存限制64 MB

答案

#include<iostream>
#include<vector>
#include <bitset> 
using namespace std;
template<typename T>
class ObjectPool
{
private:
    vector<T*> pool;
    bitset<65537> is_vaid;
    int head = 1,C;
    vector<int> next;
public:
    ObjectPool(int c)
    {
        C = c;
        for (int i = 0; i < c; ++i)
        {
            next.push_back(i+1);
            pool.push_back(new T());
            is_vaid[i] = 0;
        }
        pool.push_back(new T());
        next.push_back(0);
    }
    int createNew()
    {
        if (head == 0)return 0;
        else if (head != 0)
        {
            int p;
            p = head;
            head = next[head];
            is_vaid[p] = 1;
            //printf("\n2\n");
            return p;
        }
        return 0;
    }
    T* ref(int p)
    {
        //cout << endl << "h" << endl;
        if (p<1 || p>C)return nullptr;
        //cout << endl << "h" << endl;
        if (is_vaid[p]==1)
        {
            //cout << endl << pool[p] << endl;
            return pool[p];
        }
        return nullptr;
    }
    int deleteObject(int p)
    {
        if (p == 0)return head;
        else
        {
            if (p >= 1 && p <= C && is_vaid[p]==1)
            {
                next[p] = head;
                head = p;
                return head;
            }
        }
        return 0;
    }
    int getHead()
    {
        //printf("\n1\n");
        return head;
    }
};

int main()
{
    int C,i;
    scanf("capacity %d", &C);
    
    ObjectPool<int>* object_pool = new ObjectPool<int>(C);
    int* int_ptr=nullptr;
    char c;
    c = getchar();
    while (c != EOF)
    {
        c = getchar();
        switch (c)
        {
        case 'n':
            scanf("ew");
            i = object_pool->createNew();
            printf("new # return %d, head=%d\n", i, object_pool->getHead());
            break;
        case 'r':
            scanf("ef %d", &i);
            int_ptr =object_pool->ref(i);

            if (int_ptr == nullptr)
            {
                printf("ref %d # error\n", i);
            }
            else
            {
                printf("ref %d # ok\n", i);
            }
            break;
        case 'd':
            scanf("elete %d", &i);
            if (object_pool->deleteObject(i) !=0)
            {
                printf("delete %d # head=%d\n", i, object_pool->getHead());
            }
            else
            {
                printf("delete %d # error\n", i);
            }
            break;
        case EOF:
            return 0;
        }
    }
}

猜你喜欢

转载自blog.csdn.net/lifesize/article/details/128944964