设计RandomPool结构
【题目】 设计一种结构,在该结构中有如下三个功能:
- insert(key):将某个key加入到该结构,做到不重复加入。
- delete(key):将原本在结构中的某个key移除。
- getRandom():等概率随机返回结构中的任何一个key。
【要求】 Insert、delete和getRandom方法的时间复杂度都是O(1)。
//设计RandomPool结构
#include<iostream>
#include<map>
#include<time.h>
#include<stdlib.h>
#include<string>
using namespace std;
template<class T>
class RandomPool
{
public:
RandomPool() //初始化index
{
this->index = 0;
}
void insert(T key) //插入key
{
if (p2.find(key) != p2.end() && index != 0) //判断插入的值是否存在
{
cout << "此值已存在,无法插入" << endl;
return;
}
else
{
cout << "插入成功" << endl;
index++;
p1.insert(make_pair(index, key));
p2.insert(make_pair(key, index));
}
}
void Delete(T key) //删除key值
{
if (p2.find(key) == p2.end())
{
cout << "此键值不存在" << endl;
return;
}
map<T, int>::iterator it1 = p2.find(key);
map<int, T>::iterator it2 = p1.find(index);
if (key != ((*it2).second))
{
int c = (*it1).second;
p1.erase((*it1).second);
p1.insert(make_pair((*it1).second, (*it2).second));
p2.erase(key);
p2.insert(make_pair((*it2).second, c));
map<int, T>::iterator it3 = p1.find(index);
p2.erase((*it3).second);
p1.erase(index);
index--;
return;
}
p1.erase((*it1).second);
p2.erase(key);
index--;
}
int getindex() //获取现在RandomPool结构中的index
{
return index;
}
int getsize() //获取RandomPool结构的长度
{
return p1.size();
}
void getRandom() //随机获取key值
{
map<int, T>::iterator it = p1.find((rand() % p1.size() + 1));
cout << (*it).second << endl;
}
void get() //打印目前RandomPool中的key值
{
for (map<int,string>::iterator it = p1.begin(); it != p1.end(); ++it)
{
cout << (*it).second << endl;
}
}
private:
map<int, T>p1;
map<T, int>p2;
int index;
};
int main()
{
srand((unsigned int)time(NULL));
RandomPool<string>v;
v.insert("你好");
v.insert("你好");
v.Delete("你好");
v.Delete("我好");
v.insert("你好");
v.insert("我好");
v.insert("大家好");
v.Delete("我好");
v.get();
v.getRandom();
return 0;
}
原理图如图所示:
上面把功能和要求都实现了我还是要说的还就是在删除那一步,不光是简单删除操作,因为因为题目有三点要求,我用的是map容器来实现的,原理如图所示,大概意思就是,一个结构,内部建立两个map容器,其中一个用来正向记录保存的数据,一个用来反向记录,这里的正向和反向指的是,在第一个map容器中(1,“小狗”),(2.“小猫”),这样记录但是在第二个map容器中记录的方法是(“小狗”,1),(“小猫”,2),这样的目的是,因为每次只输入了一个key值,然后要求的是每次的时间复杂度是0(1),也就是说你无法每次寻找的时候遍历整个map容器,所以就要借助map容器自带的find函数来查找,然而find只能根据索引查找,无法根据key查找,就有了第二个表,第二个表用来根据传入的key的值来find该结构是否已经存在该key。
我想要说的是在删除这一操作的时候,不单单是简单的删除,因为第三个要求是,要求你随即返回一个该结构中的数据,要是该结构一直只是插入,没有删除还好说,要是删除的话,位置就会空出来,这样的话要是随及返回的话,可能会返回已经空了的位置,就会引起错误,那么我们删除的步骤是,将要删除的位置删除掉,然后将最后一个位置的数据填入到删除的地方,再将index–,这样以来的话就算随即返回也不会存在内存访问越界的问题。然后就是我在操作上遇到的问题就是两个map容器是相辅相成,如果将其中一个删除的话另一个将无法删除,所以要先将其中的一个保存后再删除,看代码就知道了。还有就是,我刚开始我想的是拿最后一个值,直接将要删除的位置的值覆盖但是根本不行,也就是说在map中必须要删除,不能说是已经在某个位置插入了元素,再对该位置重新赋值,必须删除后重新插入。