一种有效的数据结构,用于按 ID 访问和查找加权随机项
An efficient data structure for access by ID and finding the weighted random item
您能否帮助我处理允许对以下内容进行O(logN)
(或至少O(sqrtN)
(操作的数据结构:
- 插入具有
ID
(int64_t
(和health
(double
(的项目 - 按
ID
删除项目 - 查找按
health
随机加权的项目
首选语言是 C++ 或 C。加权随机是指以下内容:
考虑totalHealth=Sum(health[0], health[1], ..., health[N-1])
.我需要一个快速(如上所述(操作,相当于:
- 计算
const double atHealth = rand_uint64_t()*totalHealth/numeric_limits<uint64_t>::max();
- 遍历
i=0 to N-1
以找到第一个i
,以便Sum(health[0], health[1], ..., health[i]) >= atHealth
约束:health[i] > 0
,rand_uint64_t()
返回一个在0
和numeric_limits<uint64_t>::max()
之间均匀分布的整数值。
到目前为止,我尝试的是一种C++unordered_map
,它允许通过ID
快速(Θ(1)
(插入和通过ID
删除,但是操作#3在N
中仍然是线性的,如我上面的伪代码中所述。
非常感谢您的帮助!
我想不出使用现有 STL 容器的方法,但如果您愿意编写自己的二叉树,我可以想到一种方法。诀窍是每个节点都保持其左侧所有节点的总运行状况(它不需要担心其右侧的节点,如下所示(。然后,如果您按 ID 顺序遍历树,您还可以按 ID 顺序计算log(n)
时间内的"累积运行状况"。因此,树按 ID 和累积运行状况排序,您可以按 ID 或"累积运行状况"log(n)
时间进行查找。例如,考虑一个非常简单的树,如下所示:
ID: 8
h: 10
chl: 15
+-------|--------+
| |
ID: 4 ID: 10
h: 15 h: 7
chl: 0 chl: 0
在上面的h
中是节点的运行状况,chl
是其左侧所有节点的累积运行状况。因此,上述所有节点的总运行状况为 15 + 10 + 7 = 32(我假设您单独维护该计数,尽管您也可以正确跟踪节点的累积运行状况,并且您不需要(。让我们看3个案例:
- 您计算
atHealth < 15
.然后在第一个节点,您可以看到您的值小于chl
因此您知道需要向左走,最终到达正确的叶子。 - 你计算一个
atHealth >= 15 < 25
所以你知道它是> 15,所以你不会在根部左走,你所在的节点的运行状况为 10 和 10 + 15 意味着该节点的累积运行状况在 15 到 25 之间,所以你很好。 - 您计算
atHealth >= 25
。每次访问节点并向右移动时,您都必须添加您所在节点的chl
和h
,以便在您走树时继续计算累积运行状况,这样您就知道您从10 + 25 = 25
开始,当您向右走时,您会将其添加到之后遇到的任何节点的h
或chl
中。因此,您可以快速发现右侧的节点是正确的。
插入新节点时,在遍历树时,每个父节点的总运行状况递增;删除节点时,从树上走回总运行状况。因此,插入和删除仍然是O(log(n))
,按 ID 查找也是按 ID 或按atHealth
log(n)
的。
如果你想保持一个平衡的树,事情显然会变得更加复杂,但它仍然是可行的。
- 通过方法访问结构
- 使用不带参数的函数访问结构元素
- 如果我只是不访问queue_front节点的子节点,而是将它们推到队列中呢?还是BFS吗
- 用于访问容器<T>数据成员的正确 API
- 访问者访问变体并返回不同类型时出错
- 尝试通过多个向量访问变量时,向量下标超出范围
- 无法访问嵌套类.类的使用无效
- 写入位置0x0000000C时发生访问冲突
- 我们可以访问一个不存在的联盟的成员吗
- C++从另一个类访问公共静态向量的正确方法是什么
- 我的简单if-else语句是如何无法访问的代码
- 一种有效的数据结构,用于按 ID 访问和查找加权随机项
- 通过 id 访问 QML 插槽中的嵌套对象(从 c++ 调用)
- OpenMP:当我按线程 ID 访问共享变量时,我是否需要一个关键部分
- 使用宏访问指向数据成员的指针会导致"error: expected unqualified-id before ‘*’ token"
- QML元素ID访问从C 访问
- 具有可移动节点、可访问属性和可靠ID的C++图
- 通过指针访问类的成员时"unqualified-id"编译器错误
- Qt:如何访问在主窗口上按id拖动的元素
- 仅使用一个用户id和密码访问数据库