我正在用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-linked list来实现我的算法,它会给出最小的复杂度(上面的操作将为O(1)
,为我的算法提供O(n^2)
。但我知道,XOR链表被认为是一个丑陋的数据结构" ([1],[2])。
这对于什么是好的数据结构呢?更确切地说,还有其他常用的数据结构,在O(1)
时间内实现这些操作吗?
答案 0 :(得分:1)
这取决于你没有提到的更多因素。
首先,它取决于元素的大小及其复制代码。如果你有小元素(大约64字节或更少)并且他们的复制(或移动)是便宜的(甚至是微不足道的(在POD类型意义上)),那么使用std::vector
可能是一个非常很好的选择,即使是“更糟糕”的时间复杂性(顺便说一句,作为未来的小窍门,不要过于追求最小的时间复杂性,它只是整个故事的一部分)。
如果您的元素琐事,尤其如此,因为向量中的旋转操作将非常快(尽管仍为O(n)),而其他操作在与链表相比的时间复杂度。
其次,这取决于您执行上述不同操作的频率。通过链表进行顺序访问实际上效率很低,如果经常进行遍历,通常不建议使用它们。
如果您的元素太小而您考虑使用XOR链接列表(为每个元素节省一个指针),那么您可能根本不应该使用链接列表。说实话,我不确定XOR链接列表是否真的值得(但我不想进入)。
总的来说,我不得不说你应该测试这三个选项:linked-list(std::forward_list
或std::list
),std::vector
或者指针向量(例如std::vector< std::unique_ptr<T> >
)。另一个选择可能是unrolled linked-list,但这只会在我提到的因素的特定制度中有用。
我重申,我说测试他们,因为这是你知道什么是最好的唯一方法。 “分析”仅用于经验法则,不再是我最喜欢的引用之一:
就数学定律而言,它们指的是现实,它们并不确定;只要他们确定,他们就不会提到现实。 (阿尔伯特爱因斯坦)
答案 1 :(得分:0)
我只会使用std::vector<T>
,如果您发现在实践中操作过于昂贵,那么只会寻找可能更有效的数据结构。
std::vector<T>
的顺序访问非常有效。std::rotate
algorithm适用于操作2. std::reverse
algorithm适用于操作3。上述算法位于<algorithm>
header。