有一个简单而高效的方法:
如果你只需要在最终填充了学生结构体之后搜索百分位数,那么可以使用ArrayList来动态构建,当你不知道元素数量时。如果你知道它们,那么直接从数组开始,否则从动态数组创建数组。(例如Java中的ArrayList)。
插入:不必要,在末尾添加后排序即可。
删除:如果可以接受的话,也不必要。
告诉百分位数:更简单的是:与element[length * percentile]非常接近:O(1)
实际上,在Java中,数组方法比平衡树方法快得多,至少在应用程序可以一次性构建数组的情况下(例如每天对学生进行评估,每天都构建它)。
我已经使用自己编写的ArrayListInt实现了上述算法,它与ArrayList相同,但使用基本类型(double、int)而不是对象类型。当所有数据都被读取时,我会进行一次排序。
此外,你想要键值:
我会添加一个TreeMap(平衡树)。现在这有点值得怀疑,因为TreeMap和额外的百分位数数组是否有意义取决于你需要搜索的频率、内存使用与搜索时间之间的关系。
更新:
结果:treeset与排序数组(动态构建数组,然后最终排序):
num elements: 1000 treeSet: 4.55989 array=0.564159
num elements: 10000 treeSet: 2.662496 array=1.157591
num elements: 100000 treeSet: 31.642027 array=12.224639
num elements: 1000000 treeSet: 1319.283703 array=140.293312
num elements: 10000000 treeSet: 21212.307545 array=3222.844045
现在的元素数量已经接近限制值(1GB堆空间),在下一步内存将会不足(虽然在清理完TreeSet的内存后,1e7的测试案例也可以正常运行)。
尚缺的是搜索时间,但使用二分查找的排序数组只能被哈希表超越。
最后: 如果您能够构建学生集合,例如每天构建一次,则使用数组方法可以更轻松地进行百分位数搜索。