Python:无间隙地跟踪最新的消息序列ID

时间:2013-11-27 03:13:06

标签: python algorithm networking

我正在用Python编写一个网络应用程序,它接收来自服务器的编号消息。消息的序列号在1..N范围内,可能会出现故障。我想跟踪收到的最新消息,条件是到目前为止消息中没有间隙。

例如,

  • 如果邮件为1,3,2,我会将3标记为收到的最新未删除邮件。
  • 如果邮件为1,2,5,4,我会将2标记为自我尚未收到3以来收到的最新未删除邮件。
  • 3进入后,我会将5标记为收到的最新消息。

最有效的方法是什么?是否有一些数据结构或编程习惯用法来实现解决这个问题的算法?

1 个答案:

答案 0 :(得分:0)

我环顾四周,并没有立即找到一个好的答案。

这是我通过一个小型阻止课程来做这件事。对于单个handle_new_index来说,这在技术上可能是O(N),但仍应保证handle_new_index操作的平均时间保持不变。

我不认为时间复杂性会好得多,因为无论你做什么,都必须对某种数据结构进行插入。

随着数十亿的请求和非常广泛的传播,非连续集可以具有适度的内存占用。

import random

class gapHandler:
    def __init__(self):
        self.greatest = 0
        self.non_contiguous = set()

    def handle_new_index(self, message_index):
        """
        Called when a new numbered request is sent. Updates the current
        index representing the greatest contiguous request.

        """
        self.non_contiguous.add(message_index)
        if message_index == self.greatest + 1:
            self._update_greatest()

    def _update_greatest(self):
        done_updating = False
        while done_updating is False:
            next_index = self.greatest + 1
            if next_index in self.non_contiguous:
                self.greatest = next_index
                self.non_contiguous.remove(next_index)
            else:
                done_updating = True


def demo_gap_handler():
    """ Runs the gapHandler class through a mock trial. """
    gh = gapHandler()

    for block_id in range(20000):
        start = block_id*500 + 1
        end = (block_id + 1)*500 + 1

        indices = [x for x in range(start, end)]
        random.shuffle(indices)
        while indices:
            new_index = indices.pop()
            gh.handle_new_index(new_index)
            if new_index % 50 == 0:
                print(gh.greatest)


if __name__ == "__main__":
    demo_gap_handler()

以下是一些基本测试:

import unittest
import gaps


class testGaps(unittest.TestCase):

    def test_update_greatest(self):
        gh = gaps.gapHandler()
        gh.non_contiguous = set((2, 3, 4, 6))

        gh._update_greatest()
        self.assertEqual(gh.greatest, 0)

        gh.greatest = 1
        gh._update_greatest()
        self.assertEqual(gh.greatest, 4)

    def test_handle_new_index(self):
        gh = gaps.gapHandler()
        gh.non_contiguous = set((2, 3, 4, 6, 2000))

        gh.handle_new_index(7)
        self.assertEqual(gh.greatest, 0)

        gh.handle_new_index(1)
        self.assertEqual(gh.greatest, 4)

        gh.handle_new_index(5)
        self.assertEqual(gh.greatest, 7)

if __name__ == "__main__":
    unittest.main()