我正在寻找一个具有高效插入,删除和查找的数据结构,二进制树通常符合这些数据结构,但是我的项目不是根据它们的值进行排序 - 而是我需要根据它们的实际情况对它们进行排序插入位置(即像数组一样)。所有操作都将根据此位置访问,插入或删除项目,就像使用数组一样。
所以基本上问题是插入/删除项会导致其后面的所有项目的索引都移动了1.显然存储索引永远不会比O(n)更好,所以基本的二进制树/哈希表都没有了
是否有能够在线性时间内实现所有这些操作的结构?我一直认为二进制树可以以某种方式进行调整,并且我支持通过索引查找,让每个节点存储其左侧分支中的节点数。
答案 0 :(得分:0)
用指数注释的2-3个手指树应该能够做到这一点。它们是持久的(在函数编程意义上),可能是好的也可能是坏的。如果你想要一个可变的变体,它至少是一个想法的来源。 2-3手指树支持
因此要在任意位置插入,可以在该位置拆分,添加到其中一个零件的末尾,然后连接。 同样,要删除项目,您可以拆分该索引,删除该项目,然后再次连接。两者都花费少于O(log n)时间,这是一个过度近似。
现有的实现(特殊的索引注释,并针对性能进行了调整)是Haskell中的Data.Sequence
模块。引入它们的paper比它需要的更难阅读。有一个article更清楚地解释了一般的想法,但省略了许多细节,因此实施它们是不够的。
答案 1 :(得分:-1)
List支持这些功能,如果容量>则为O(1)添加。数
其他一切都是O(N),但在实践中更好 如果你在0位置插入那么它是O(N)但如果你在倒数第二个位置插入,你会发现它比O(N)更好。
List<simple> ls = new List<simple>();
simple ss = new simple(0);
ls.Add(ss);
ls.Add(new simple(2));
ls.Insert(0, new simple(1));
ls.Add(new simple(3));
ls.Add(new simple(4));
ls.RemoveAt(2);
foreach(simple s in ls)
{
System.Diagnostics.Debug.WriteLine(s.ID);
}
System.Diagnostics.Debug.WriteLine(ls[1].ID.ToString());
System.Diagnostics.Debug.WriteLine(ls.IndexOf(ss).ToString());
}
public class simple
{
public Int32 ID { get; private set; }
public simple(Int32 id) { ID = id; }
}