【问题标题】:Python data structure for efficient add, remove, and random.choice用于高效添加、删除和随机选择的 Python 数据结构
【发布时间】:2013-04-06 06:49:48
【问题描述】:

我正在寻找一个内置的 Python 数据结构,它可以add 一个新元素,remove 一个现有元素,并选择一个随机元素,所有这些都比 O(n) 时间好。

我希望 set 可以做到这一点,但据我所知,从 Python 集中选择随机元素的唯一方法是 random.choice(list(my_set)),这需要 O(n) 时间。

我更喜欢 Python 内置的解决方案,因为我需要高效且易于部署。不幸的是,Python 似乎没有内置的树数据类型。

【问题讨论】:

  • 这可能是界面设计的问题。在tree/hashmap中随机选择并不难,但即使是C++ STL的map/unordered_map也不支持随机选择。

标签: python data-structures


【解决方案1】:

Python 没有内置 数据结构来满足您的所有 3 个要求。

也就是说,自己实现一棵树相当简单。


另一种选择是将字典与列表相结合,以创建有效的集合,同时维护其项目列表:

import random

class ListDict(object):
    def __init__(self):
        self.item_to_position = {}
        self.items = []

    def add_item(self, item):
        if item in self.item_to_position:
            return
        self.items.append(item)
        self.item_to_position[item] = len(self.items)-1

    def remove_item(self, item):
        position = self.item_to_position.pop(item)
        last_item = self.items.pop()
        if position != len(self.items):
            self.items[position] = last_item
            self.item_to_position[last_item] = position

    def choose_random_item(self):
        return random.choice(self.items)

由于列表中完成的唯一操作是 .pop().append() 以及索引检索和分配,因此它们所花费的时间不应超过恒定时间(至少在大多数 Python 实现中是这样)。

您可以使用额外的方法扩展上述定义以支持其他有用的操作,例如lenin 和迭代:

class ListDict(object):
    ... # methods from above

    def __contains__(self, item):
        return item in self.item_to_position

    def __iter__(self):
        return iter(self.items)

    def __len__(self):
        return len(self.items)

【讨论】:

  • 实现高效的自平衡树并非易事。
  • @tba shrug 我会说这是主观的。无论如何,您甚至不需要一棵树 - 请参阅编辑后的答案。
  • 小贴士:不妨用dict.pop代替remove_item的前四行。
  • 是否也可以获得 O(1) 集包含操作?除了在所有项目上保持一个平行集之外。
  • 哦,当然。你可以做item in self.item_to_position。容易。
猜你喜欢
  • 1970-01-01
  • 2014-03-04
  • 2013-02-22
  • 2010-10-27
  • 2012-11-05
  • 2012-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多