题目解析:
1.哪些内存被占用了?
2.怎么按照要求释放内存?
要想知道那些内存被占用了,我们可以使用一个数组来模拟内存池,初始化大小为100,其中的状态分为已占用或者空缺,用true和false表示状态。
true:内存被占用
false:内存未被占用
故初始化一个数组,数组中存放位置是否被占用,即vector<bool> status=vector<bool>(100, false)
现在已经解决了第一个问题,接下来是第二个问题,如何删除指定空间大小的内存?
延续上面的思路,若释放内存则直接将状态改为false即可,那怎么知道从哪个位置开始,到哪个位置结束,将指定位置的值更改呢?我们可以使用map来解决这个问题,map<key,value>中key可以用来记录起始位置,value表示其后有多少空间,在删除时,只需要先访问指定位置上的元素是否被使用,未被使用返回error,已被使用,则将status中的位置改为true,这样就完成了释放资源的操作。
上述的问题都解决完之后,此时考虑我们如何分配内存,遵循题目中连续的原则,则存在的问题即是若前面已经被释放但是不满足要求,该如何跳过该段内存,继续向后寻找。将此问题抽象为寻找从某一位置开始中间连续size大小的内存。
具体实现代码如下
#include<iostream>
#include<vector>
#include<sstream>
#include<map>
using namespace std;
class MemPool {
public:
//构造函数
MemPool() {
//初始化内存
status = vector<bool>(100, false);
}
int Request(int size) { // 要求分配多少字符
int res = -1;
if (size <= 0) {
return res;
}
//寻找位置插入
for (int i = 0; i < total - size; i++) {
int j = 0;
while (j < size) {
if (status[i+j]) {
break;
}
j++;
}
if (j == size) {
res = i;
break;
}
}
//判断res的值
if (res == -1) {
return res;
}
for (int i = 0; i < size; i++) {
status[i+res] = true;
}
storage[res] = size;
return res;
}
bool Release(int startAddr) {
//判断内存是否被使用
if (status.count(startAddr)) {
return false;
}
for (int i = startAddr; i < storage[startAddr]; i++) {
status[i] = false;
}
return true;
}
private:
vector<bool> status;
map<int, int> storage;
static constexpr int total = 100;
};
int main() {
int N;
cin >> N;
MemPool pool;
for (int i = 0; i < N; ++i) {
string str;
cin >> str;
string cmd = str.substr(0, str.find_first_of('='));
int num = stoi(str.substr(str.find_first_of('=') + 1));
if (cmd == "REQUEST") {
int size = num;
int result = pool.Request(size);
if (result != -1) {
cout << result << endl;
}
else {
cout << "error" << endl;
}
}
else {
int addr = num;
if (!pool.Release(addr)) {
cout << "error" << endl;
}
}
}
return 0;
}
综上所述,应该掌握两个点,一个是合理使用各种结构,一开始只想着用数组完成,并没有考虑到map,所以浪费了大量时间在寻找插入位置上,另外一个就是学习如何查找i之后大小为size的空间。
仅用作学习用途,便于复习。