和左神一起练算法:设计RandomPool结构

设计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中必须要删除,不能说是已经在某个位置插入了元素,再对该位置重新赋值,必须删除后重新插入。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值