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

来源:互联网 发布:linux gtk编程 编辑:程序博客网 时间:2024/06/16 12:35

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


题意:如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;}



原创粉丝点击