我试图以STL方式实现具有以下功能的算法:
给定范围[first,last)
,邻域范围nSpan
和(二进制)谓词Pred
,它会删除该范围内的元素,因此Pred
是对于最多彼此远离的任何剩余元素{1}}
示例:
nSpan
= 1且nSpan
= Equality =>衰减到Pred
算法 std::unique
= 2且nSpan
= PointEquality =>消毒折线
Pred
+ P2
|
v
^
P0 | P4 P0 P1 P4
+---->-------+---->------+ becomes +---->-------+---->------+
P1 P3
= 2和nSpan
=平等:['a','b','a','d','e','d','f'] - &gt ; ['a','d','f'] 在最后一个例子中,显而易见的是(为了防止算法变得模棱两可),我们从第一个迭代器扫描并打开,同时检查nSpan距离以删除元素(否则会有多种方法来删除元素)。
到目前为止我的尝试(下面的代码清单)有以下缺点:
Pred
函数实现,而是作为remove
函数实现(我需要删除一个,而且看起来要困难得多)并强制提供整体容器作为参数而不是范围(理想情况下算法应该是容器不可知的)我正在列出first attempt
erase
理想签名
template<typename Cont, typename It, class Pr>
void erase_neighbors(Cont &cont, It first, It last, int nSpan, Pr Pred)
{
if (0 < nSpan && nSpan < std::distance(first, last)) for (It it2; (it2 = first), first != last; )
{
if (nSpan < std::distance(it2, last))
{
std::advance(it2, nSpan);
if (Pred(*first, *it2))
{
first = cont.erase(first, it2);
last = cont.end();
continue;
}
}
++first;
}
}
理想的实现:非c ++ 11且没有提升(即使有相关的提升算法我会很高兴知道它)
答案 0 :(得分:2)
在某种程度上我理解问题陈述,这似乎做你想要的。见in action:
template<typename It, class Pr>
It remove_neighbors(It first, It last, int nSpan, Pr Pred) {
if (first == last || nSpan <= 0) return last;
It lastGood = first;
It cur = first;
++cur;
for (; cur != last; ++cur) {
bool found = false;
It back = lastGood;
for (int i = nSpan; i > 0; --i, --back) {
if (Pred(*back, *cur)) {
found = true;
lastGood = back;
break;
}
if (back == first) break;
}
if (!found) {
++lastGood;
*lastGood = std::move(*cur);
}
}
++lastGood;
return lastGood;
}
这不会超过N
移动/副本,也不会超过N * nSpan
Pred
次调用。
答案 1 :(得分:1)
通过维护下一个元素的表,可以避免列出的问题。因此,每个位置都会指向符合good
邻居的下一个有效位置,而不会违反谓词,如下所示:
map<unsigned, unsigned> neigh_table;
while(it != end){
neigh = startneigh = it + 1;
do{
if(pred(it, neigh)) //if predicate fails, restart with a new neighbour
neigh = startneigh = neigh + 1;
else
++neigh;
}while(neigh - startneigh < range && neigh != end);
neigh_table[it-start] = startneigh - start;
it = neigh;
}
在操作结束时,您可以:
在任何一种情况下,如果不将实际容器传递给函数,您将无法修改容器。这就是stl::remove
等函数不会修改容器长度的原因。有关如何使用stl :: remove实际修改容器的示例,请参阅remove-erase idiom。