代码之家  ›  专栏  ›  技术社区  ›  Mark Tyler

具有O(1)随机移除和添加的数据结构,用于洗牌生成器顺序

  •  0
  • Mark Tyler  · 技术社区  · 6 年前

    我需要一个数据结构,允许您在 O(1) 时间

    原因是我需要从生成器中洗牌数据,但由于大小原因,我无法同时将所有数据加载到内存中。

    这是一个用法示例,它自动洗牌生成器表达式生成的结果的顺序,而无需将所有内容加载到内存中:

    def generator_shuffler(generator)
        a = magical_data_structure_described_above
        for i in generator:
            a.add(i)
            if len(a) > 10: yield a.poprandom()
    

    起初我试着用python set() 然而,从这里开始: Set.pop() isn't random? ,似乎 集合() 不会按任意顺序删除项目。如何使用上述用法实现数据结构?

    2 回复  |  直到 6 年前
        1
  •  5
  •   rici    6 年前

    如果要随机弹出,为什么不使用一个列表并通过将最后一个元素与随机选择的元素交换,然后删除新的最后一个元素来实现弹出?这不会保留数据结构中其余元素的顺序,但“随机弹出”和“随机移动”表明您并不在乎。

        2
  •  1
  •   Ajax1234    6 年前

    在集合中查找和删除随机元素通常是 O(k) 使用时 pop 但是,您可以修改该操作,以便在检查长度时对列表进行无序排列,这样一来 add 流行音乐 操作仍然存在 O(1) :

    import random
    
    class RandomStack:
       def __init__(self, _d = None):
          self.stack = _d if _d else []
       def __len__(self):
          random.shuffle(self.stack)
          return len(self.stack)
       def add(self, _val):
          self.stack.append(_val)
       def poprandom(self):
          return self.stack.pop()
    
    
    a = RandomStack()
    for i in range(16):
      a.add(i)
      if len(a) > 10:
         val = a.poprandom()
         print(val)
    

    输出:

    2
    4
    9
    0
    6
    12