data-structures - 用于快速索引查找的列表数据结构
问题描述
我需要将大量元素存储在类似列表的数据结构中。额外的要求是在任何时候都应该快速确定每个元素的索引。元素未排序,无法排序。
如果使用简单数组,则每次查询元素的索引时都必须使用线性搜索。这可行,但它是一个非常低效的解决方案。这是伪代码中的数据结构:
class IndexList1 {
Array elements
getIndex(e) {
for (i = 0; i < elements.length; i++) {
if (elements[i] == e) {
return i
}
}
return -1;
}
insertAt(e, i) {
elements.insertAt(e, i)
}
removeFrom(i) {
elements.removeFrom(i)
}
}
更好的方法是将元素映射到内部映射中的索引或作为元素中的字段。这种方式不需要搜索来确定元素的索引。这里的问题是,在列表中间插入或删除元素后,插入点之后的所有索引都必须更新。对于频繁的插入和删除以及大量元素,这不是很有效。
在伪代码中,改进后的数据结构如下所示:
class IndexList2 {
Array elements
Map elementIndexMap
getIndex(e) {
return elementIndexMap.get(e)
}
insertAt(e, i) {
elements.insertAt(e, i)
updateIndicesFrom(i)
}
removeFrom(i) {
elementsIndexMap.delete(elements[i])
elements.removeFrom(i)
updateIndicesFrom(i)
}
updateIndicesFrom(i) {
for (; i < elements.length; i++) {
elementsIndexMap[elements[i]] = i
}
}
}
是否有用于大量元素的巧妙的类似列表的数据结构,以有效的方式跟踪每个元素的索引,即使有很多插入和删除?高效我的意思是 O(1) for getIndex()
and 比 O(n) for insert()
and更好remove()
。
解决方案
解决这个问题的通常方法是把项目放在某种平衡树(红黑树、B+树、skip-list等)中,并带有父指针,并用大小标记树中的每个节点的子树。
然后,您可以通过走到根节点并将其左侧的任何子树的大小相加来找到任何项目的索引。
它就像一个订单统计树(https://en.wikipedia.org/wiki/Order_statistic_tree),没有对键进行排序。
推荐阅读
- flatpickr - 如何更改 flatpickr 默认时区
- java - 从字符串的开头删除所有或某些特殊字符
- swift - 从 Xcode 调用 C 库函数
- sails.js - 通过模型设置创建唯一的多键索引
- javascript - 如何在 testcafe 中调用外部异步等待函数
- javascript - url-createobjecturl-no-longer-accepts-mediastream - 在 2018 年 12 月 14 日 Chrome 更新之后
- c - struct 中的枚举 - C 中的枚举范围
- python - ValueError:无法获取具有未知等级的形状的长度
- mysql - 为什么 <> 'null' 在 MySQL 中有效?
- python - Python-正确添加分数