我为“C 中的滚动中位数”问题给出了这个答案
我找不到具有 order-statistic 的 c++ 数据结构的现代实现,因此最终在 top coders 链接中实现了这两个想法(匹配编辑:向下滚动到 FloatingMedian)。
两个多组
第一个想法将数据划分为两个数据结构(堆、多集等),每个插入/删除 O(ln N) 不允许在没有大成本的情况下动态更改分位数。即我们可以有一个滚动的中位数,或者一个滚动的 75%,但不能同时有两者。
段树
第二个想法使用 O(ln N) 的段树进行插入/删除/查询,但更灵活。最好的“N”是数据范围的大小。因此,如果您的滚动中位数具有一百万个项目的窗口,但您的数据与 1..65536 不同,那么每次移动 100 万个滚动窗口只需要 16 次操作!(而且您只需要 65536 * sizeof(counting_type) 个字节,例如 65536*4)。
GNU 顺序统计树
就在放弃之前,我发现stdlibc++中包含顺序统计树!!!
它们有两个关键操作:
iter = tree.find_by_order(value)
order = tree.order_of_key(value)
请参阅libstdc++ 手册 policy_based_data_structures_test(搜索“拆分和连接”)。
我已经包装了树,以便在支持 c++0x/c++11 样式的部分类型定义的编译器的便利标头中使用:
#if !defined(GNU_ORDER_STATISTIC_SET_H)
#define GNU_ORDER_STATISTIC_SET_H
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
// A red-black tree table storing ints and their order
// statistics. Note that since the tree uses
// tree_order_statistics_node_update as its update policy, then it
// includes its methods by_order and order_of_key.
template <typename T>
using t_order_statistic_set = __gnu_pbds::tree<
T,
__gnu_pbds::null_type,
std::less<T>,
__gnu_pbds::rb_tree_tag,
// This policy updates nodes' metadata for order statistics.
__gnu_pbds::tree_order_statistics_node_update>;
#endif //GNU_ORDER_STATISTIC_SET_H