消息id乱序接收但顺序发送问题

点:将问题抽象,对应到能完成功能的数据结构算法


题意:如rpc server,rpcid是从1-N的正整数不重复,先后接收到rpcid为3、1、5、2、4、8、6、7的消息,即乱序接收,但它必须做到按顺序返回相应部分的返回,

比如对于3、1、5、2、4、8、6、7的接收顺序,rpc server的返回顺序应该是1、2、3(接收到2时)和4、5(接收到4时)和6、7、8(接收到7时)

来自程序员代码面试指南


思路:即接收到哪个id时,要判断它之前的部分是否已经接收过,如果接收过就全部打印,否则要等”连成片“后,比如初始接收到了3不能返回,因为1、2都没出现过呢,再出现了1也不能返回,因为2还没出现,当出现2时,判断1、2、3已经是从1开始的连续区间,此时可以返回1、2、3,后面最小输出起点是4,而出现5时不能返回,因为4还未出现,当出现4,则4、5可返回

基于这个情况,可见rpc server需要能够先暂存不能输出的,并且接收到新的时候要判断是否符合返回条件,以及暂存的数据是否形成连续空间需要连续输出,直到出现断点为止

一个很简单的办法就是,stl的set,set基于二叉排序树(红黑树),将需要暂存不能返回的rpcid保存在这里,并初始化时记录一个当前返回起点标志,每次接收到数据时:

1、塞入set

2、判断set的最小元素,是否比当前返回起点标志大1

如果不符合:结束

如果已符合:将set内的rpcid挨个返回,同时每返回一个rpcid时(返回后要在set中删除掉这个元素),更新当前返回起点标志,下次遍历set时要判断是否符合比当前返回起点标志大1


代码:

#include <iostream>
#include <set>


class MessageProcesser {
    int lastprint;
    std::set<int> rangemap;

public:
    MessageProcesser():lastprint(0) {}
    ~MessageProcesser () {
        rangemap.clear();
    }

    void recv (int rpcid) {
        if (rpcid < 1) {
            return;
        }

        rangemap.insert(rpcid);

        std::set<int>::iterator it = rangemap.begin();
        if (*it - lastprint == 1) {
            send();
        }
    }

    void send () {
        std::set<int>::iterator it = rangemap.begin();
        for (; it != rangemap.end();) {
            if (*it - lastprint == 1) {
                std::cout << *it << "\t";
                ++lastprint;
                it = rangemap.erase(it);
            } else {
                it++;
            }
        }
        std::cout << std::endl;
    }
};

int main () {
    MessageProcesser mp;
    mp.recv(5);
    mp.recv(2);
    mp.recv(3);
    mp.recv(1);
    mp.recv(7);
    mp.recv(4);
    mp.recv(6);
    return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值