我正在用C++编写一个算法,为此我需要一个数据结构来存储一系列n
数据点。也就是说,我想要存储元素v[0],v[1],...,v[n-1]
。我确实关心订单。
我想快速的操作是:
- 顺序访问(即访问
v[0]
,然后访问v[1]
,依此类推,具有编辑值的能力( -
点重定位,即
{v[0],v[1],...,v[i],v[i+1],...,v[j-1],v[j],v[j+1],...,v[n-1]}
->{v[0],v[1],...,v[i],v[j],v[i+1],...,v[j-1],v[j+1],...,v[n-1]}
; -
部分逆转,即
{v[0],...,v[i],v[i+1],...,v[j-1],v[j],v[j+1],...,v[n-1]}
->{v[0],...,v[i],v[j],v[j-1],...,v[i+1],v[j+1],...,v[n-1]}
。
看起来,我可以使用XOR链表来实现我的算法,它将给出最小的复杂度(上面的操作将是O(1)
,给我的算法O(n^2)
(。但我知道,XOR链表被认为是"一个丑陋的数据结构"([1],[2](。
什么是比这更好的数据结构?更确切地说,有没有其他常用的数据结构,在O(1)
时间内实现这些操作?
这取决于许多您没有提到的因素。
首先,它取决于元素的大小及其复制代码。如果你有小元素(大约64字节或更少(,并且它们的复制(或移动(很便宜(甚至微不足道(在POD类型的意义上((,那么使用std::vector
可能是一个非常好的选择,即使时间复杂性"更差"(顺便说一句,作为未来的提示,不要太执着于追求最小的时间复杂性,这只是整个故事的一部分(。
如果元素是平凡的,这一点尤其正确,因为向量中的旋转操作将非常快(尽管仍然是O(n((,而其他操作在时间复杂性方面与链表相同。
其次,这取决于您执行所提到的不同操作的频率。通过链表进行顺序访问确实效率很低,如果经常进行遍历,通常不建议使用这种方法。
如果你的元素太小,以至于你考虑使用XOR链表(为每个元素留出一个指针(,那么你很可能根本不应该使用链表。老实说,我不确定XOR链表是否真的值得(但我不想谈这个(。
总的来说,我不得不说,您应该测试这三个选项:链表(std::forward_list
或std::list
(、std::vector
或指针向量(例如std::vector< std::unique_ptr<T> >
(。另一个选择可能是一个展开的链表,但这只有在我提到的特定因素范围内才是好的。
我重申,我说过测试它们,因为这确实是你知道什么是最好的唯一方法。根据我最喜欢的一句话:,"分析"只是经验法则,不再是了
就数学定律所指的现实而言,它们是不确定的;就他们所确信的而言,他们并没有提及现实。(爱因斯坦(
我只会使用std::vector<T>
,然后只在您发现操作在实践中过于昂贵的情况下寻找可能更高效的数据结构。
std::vector<T>
的顺序访问是非常有效的std::rotate
算法将适用于操作2std::reverse
算法将适用于操作3
上述算法在<algorithm>
报头中。