.net 通过键和索引进行高效操作和检索的数据结构

.net 通过键和索引进行高效操作和检索的数据结构,.net,data-structures,dictionary,lookup-tables,.net,Data Structures,Dictionary,Lookup Tables,我正在寻找一种具有功能的数据结构,例如.NET中的OrderedDictionary,也就是说,一个关联集合(即一个将键与值关联的集合)可以维持元素顺序(就像普通的列表一样) 它必须通过索引和键进行快速查找。它还应该有一个快速的“附加”操作(在末尾插入一个新项),以及快速删除具有任何索引的项(基于索引或键) 如果我没有弄错的话,.NET中的OrderedDictionary同时使用哈希表和数组来存储其项。因此,基于键检索索引(反之亦然)是O(n),当然,从数组中间删除项首先是O(n),如果按键删

我正在寻找一种具有功能的数据结构,例如.NET中的
OrderedDictionary
,也就是说,一个关联集合(即一个将键与值关联的集合)可以维持元素顺序(就像普通的
列表一样)

它必须通过索引和键进行快速查找。它还应该有一个快速的“附加”操作(在末尾插入一个新项),以及快速删除具有任何索引的项(基于索引或键)

如果我没有弄错的话,.NET中的
OrderedDictionary
同时使用哈希表和数组来存储其项。因此,基于键检索索引(反之亦然)是O(n),当然,从数组中间删除项首先是O(n),如果按键删除,则从键添加索引查找


我的问题是,是否存在满足我的条件的更高效的数据结构,或者这确实是我在这里的最佳选择?

您可以像链接一样使用,只是因为在TreeNode的定义中,您应该添加键,但问题是查找元素不是O(1),它是O(log(n))的键和索引(事实上,索引不是TreeNode的一部分,可以找到),但所有操作都是O(log(n))这是基于比较方法的已知最快的方法。

我认为您可以使用两个红黑树来实现这一点:一个用于存储由比较函数排序的键的键查找树,以及一个索引查找树,其中键按任意顺序排列,如在列表中。每个索引查找节点必须有一个“大小”字段-如果需要,红黑树可以按索引进行查找每个节点中都包含一个“大小”字段。例如,请参阅中的RedBlackTreeSet实现

键查找树中的每个项都需要一个指向索引查找树中相应项的指针。除了左右节点指针外,索引查找树还需要一个父指针字段,以允许从下到上以及从上到下的导航

每个键总共需要六个指针:两个节点中通常的左指针和右指针,加上从键查找节点到索引查找节点的指针,再加上每个索引查找节点中的父指针。每个节点中还需要一个指针来指向存储值

操作:

追加-追加操作会将键插入两个树中-一次插入键查找树中由比较函数确定的位置,另一次插入索引查找树的最右位置。插入红黑树是一个对数时间操作

按键查找-这在键查找树上完成,使用比较函数查找正确的位置-O(log(n))

按索引查找-这可以在索引查找字段上完成,如上所述-O(log(n))

从键获取索引-首先在键查找树中查找键O(log(n))。跟随指针到索引查找树。跟随父指针到根节点(O(log(n)),对于平衡树)。使用向上的“大小”字段确定键的索引。-O(log(n))

按索引删除-在索引查找树中查找项。从索引查找树中删除。在键查找树中查找定位的键。从键查找树中删除。所有操作都是O(log(n)),因此总体删除为O(log(n))

按键删除-使用“从键获取索引”获取键的索引。从索引查找树中按索引删除。从键查找树中按键删除。总体上为O(log(n))

该结构还支持在任意位置插入O(log(n)),而不仅仅是在末尾

存储开销显然相当大,但仍然是O(n)。时间复杂度满足所有要求

不幸的是,我不知道这个结构的任何实现


更新:我突然想到你可以把一棵树和一个哈希表结合起来得到O(1)按键查找。与我上面建议的两棵树不同,按键查找使用哈希表,按位置查找使用平衡顺序统计树,如上所述,但哈希表的插槽包含指向平衡树节点的指针,用于按键查找获取列表位置。按键查找现在是O(1)当然,你现在偶尔会得到O(n)re散列惩罚,就像任何散列表一样。

也许你会在(第233页)中发现一些有趣的东西。

实际上,OrderedDictionary Meat是你的需求

您对OrderedDictionary的分析不正确。它实际上是O(1)表示基于键的查找,O(1)表示基于键的索引

即使是简单的分析也可以通过键或索引进行O(1)查找。数组提供O(1)访问,哈希表提供有效的O(1)访问

插入/删除稍微复杂一些,但给定的摊销分析仍然是O(1)


文章声称插入和删除是O(n)。这至少不适用于插入,因为摊销分析允许你简单地增加“成本”将给定元素从1插入到2。插入需要调整数组大小的元素时,成本的后半部分用于支付复制成本。最终插入将花费更长的时间,但仍然是O(1)摊销后,差异仅在您导致数组大小调整时显示,这是不可能的。

如何在BST中按索引获取项目?此外,BST不是按键排序的,这意味着它不保留项目索引吗?@DeCaf,您可以在一个BST中按键而不是值排序,然后在另一个BST中按值排序,因此在按键调用时,您将发现i在O(log(n))中,当你想通过索引(值基)来查找它时,你可以在O(log(n))中进行,删除这两个元素也需要相同的时间。对于索引,当你说I'th元素时,意味着I'th元素可以在bst中的O(log(n))中完成。也许我在f中有点模糊