手机qq的位置服务器,腾讯面试题:腾讯服务器每秒有2w个QQ号同时上线,找出5min内重新登入的qq号并打印出来。...

---------------------------------------------------分割线-----------------------------------------

首先把网上的答案贴出来,就是看这个答案了:

用 6,000,000 个桶。

qq的节点结构和上面大家讨论的基本一样,增加一个指针指向输出列表,后面说。 struct QQstruct { num_type  qqnum; timestamp  last_logon_time; QQstruct  *pre; QQstruct  *next; OutPutList *out;

// 用于 free

节点的时候,顺便更新一下输出列表。 } 增加两个指针列表。 第一个大小 300 的循环链表,自带一个指向 QQStruct 的域,循环存 300

秒内的qq指针。时间一过 就 free 掉, 所以保证所有桶占用的空间在 2w X 300 以内。 第二个是 输出列表, 就是存放题目需要输出的节点。 如果登陆的用户,5分钟内完全没有重复的话,每秒 free 掉 2w 个节点。 不过在 free

的时候,要判断一下时间是不是真的超时,因为把节点入桶的时候,遇到重复的,会更 新一下最后登陆的时间。当然啦,这个时候,要把这个 qq 号码放到需要输出的列表里面。

---------------------------------------------------分割线-----------------------------------------

首先,我们考虑,如果是给定600w个QQ号,是静态的,那麽使用位图应该是最好的方法了。由于QQ号码最多有10^10个≈10G,那麽每个QQ号用2bit存放,也就是需要2.5GB的内存空间,可以找到。

其次,考虑还是动态的,如果记录每个QQ号码的时间戳,在添加时进行对比,如果存放时间戳的数据结构为4字节,那麽需要的空间为40GB,过大。

-----------------------------------------------------分割线---------------------------------------

在回过头来之前的解法,QQstruct结构的大小为20B,600W个这个结构的大小为120MB,相对于40GB,降低了很多。

首先,插入的规则。将每秒中的2w个QQ,构造成QQstruct结构,hash之后存放在桶中,同一桶中的QQstruct按照qqnum大小进行排序。同时声明一个指针,将这2w个QQ链接起来。如果在插入时,发现相同的QQ号之前已经登录过了,那麽不再生成新的QQstruct结构,而只是更新last_logon_time字段。

比如说head_t1指向在在t1登录的所有QQ号,head_t2类似,如果qqnum1在t1和t2(t1

<

t2)都登入过,那麽head_t1和head_t2会有同样一个结构,结构中,qqnum=qqnum1,last_logon_time=t2。

其次,删除的规则。由于始终存放600w个条目,超时之后,就应该将之前的条目删除。比如在第t1+300秒,就应该将head_t1指向的QQstrcut结构删除。删除之前,需要做一个判断,即last_logon_time是否等于t1,即这个QQ号码在之后的时间是否登入过。当删除qqnum1时,发现last_logon_time不等于t1,证明这个QQ号码在5min钟内重复登入了,将它打印出来,但是不删除。如果发现last_logon_time是等于t1的,就将对应的QQstruct结构释放掉。

整个算法就是这个样子了,而我对于这个QQstruct结构还是有些疑问的,对于OutPutList

*out这个成员很陌生,而且对于任意一个QQ号,既会存在于某个桶的链中,也存在于某个时间点的链中,所以需要进行修改:

struct QQstruct { num_type qqnum; timestamp last_logon_time; QQstruct *pre_barret; QQstruct *next_barret; QQstruct *pre_time; QQstruct *next_time; }

重新计算下需要的空间,桶结点本身可能需要占用空间,假设每个桶结点是8B,那麽桶结点需要8B * 600w ≈

48MB;剩下的就是QQstruct结构的大小了,最多为24B * 600w ≈

144MB,所有的空间加起来也就200MB了。

当然插入删除时,相较于时间戳策略要耗时,也属于用时间换空间的想法吧,呵呵~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值