我正在用Python编写一个网络应用程序,它接收来自服务器的编号消息。消息的序列号在1..N
范围内,可能会出现故障。我想跟踪收到的最新消息,条件是到目前为止消息中没有间隙。
例如,
1,3,2
,我会将3
标记为收到的最新未删除邮件。 1,2,5,4
,我会将2
标记为自我尚未收到3
以来收到的最新未删除邮件。 3
进入后,我会将5
标记为收到的最新消息。最有效的方法是什么?是否有一些数据结构或编程习惯用法来实现解决这个问题的算法?
答案 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()