【发布时间】:2011-10-10 14:48:48
【问题描述】:
在阅读 C++11 的 FCD 中的 forward_list 和 N2543 时,我偶然发现了 splice_after 的一个特定重载(稍微简化,让 cit 成为 const_iterator):
void splice_after(cit pos, forward_list<T>& x, cit first, cit last);
行为是在pos 之后(first,last) 之间的所有内容都移动到this。因此:
this: 1 2 3 4 5 6 x: 11 12 13 14 15 16
^pos ^first ^last
will become:
this: 1 2 13 14 3 4 5 6 x: 11 12 15 16
^pos ^first ^last
描述包括复杂性:
复杂度:O(距离(first, last))
我可以看到这是因为需要调整 PREDECESSOR(last).next = pos.next,而 forward_list 不允许这种情况在 O(1) 中发生。
好的,但是在 O(1) 中加入两个 单链表 不是这种简单数据结构的优势之一吗?因此我想知道 -- forward_list 上是否没有任何操作可以拼接/合并/加入 O(1) 中的任意数量的元素?
当然,算法非常简单。只需要一个操作名称(伪代码):(更新通过集成 Kerreks 答案)
temp_this = pos.next;
temp_that = last.next;
pos.next = first.next;
last.next = temp_this;
first.next = temp_that;
结果有点不同,因为移动的不是(first,last),而是(first,last]。
this: 1 2 3 4 5 6 7 x: 11 12 13 14 15 16 17
^pos ^first ^last
will become:
this: 1 2 13 14 15 16 3 4 5 6 7 x: 11 12 17
^pos ^last ^first
我认为这是一个与前一个一样合理的操作,人们可能愿意这样做——尤其是如果它具有 O(1) 的好处。
- 我是否忽略了对许多元素的 O(1) 运算?
- 或者我的假设是错误的,即
(first,last]可能对移动范围有用? - 还是O(1)算法有错误?
【问题讨论】:
-
您的解决方案的细节有点偏离,但问题很好。 +1
-
因为不是 (first,last) 被移动,而是 (first,last])。 这正是关键所在,所有标准算法都使用该假设,但有一个例外会迷惑人的。
-
@PlasmaHH
splice_after不是已经违反了标准假设,因为所有其他算法都适用于 [first,last)? -
如果有
before_end迭代器,那么确实可以做到。 -
@ChristianRau:确实。看看这有多混乱?还有另一个有偏差的版本会多么令人困惑。创建标准容器是为了易于使用,而不是为了最终性能。
标签: c++ complexity-theory c++11