唯一格式算法和列表容器的唯一性之间有什么区别?

时间:2016-03-20 14:43:48

标签: c++ list unique std

我可以在列表中执行唯一算法吗?如果是这样,列表容器的唯一功能的区别在哪里?

以下代码是否等效?

std::list<int> l;
//add some values to list
l.unique();

std::list<int> l;
//add some value to list
std::unique(l.begin(), l.end());

3 个答案:

答案 0 :(得分:2)

  

以下代码是否等效?

不,不是。 std::list::unique将删除所有连续重复项,但std::unique无法对所有容器执行此操作。该算法将重新排列容器,使得未删除的容器位于开头,并返回一个您应该删除的迭代器。

这两个是等价的(至少就结果列表的外观而言,虽然不是为了达到目标所采取的步骤,对类型的要求或对迭代器验证的影响):

l.unique();
l.erase(
    std::unique(l.begin(), l.end()), 
    l.end());

后者也被称为Erase-Remove习惯用法(虽然在这种情况下我们使用的是唯一而不是删除)

答案 1 :(得分:1)

They're not the same

std::list::unique从容器中删除所有连续的重复元素 这是你可能想要的。

std::unique ......好吧......

  

通过移动范围中的元素来完成移除,使得要擦除的元素被覆盖。保留的元素的相对顺序被保留,容器的物理大小不变。指向新逻辑端和范围的物理端之间的元素的迭代器仍然是可解除引用的,但元素本身具有未指定的值。对unique的调用之后通常会调用容器的擦除方法,该方法会擦除未指定的值并减小容器的物理大小以匹配其新的逻辑大小。

答案 2 :(得分:0)

默认情况下,3000中的算法是适用于迭代器的通用算法。总之,这些算法无法从容器的构建方式中获益。

然而,STL还将成员函数添加到其容器中,这些函数不太通用,但可以利用容器结构。

示例:<algorithm>将遍历所有元素以查找给定元素,而std::find(map.cbegin(), map.cend(), element)可以使用树结构。这会将map.find(element)算法缩减为linear

同样的策略被添加到log(n),因为'移动'元素是std :: list只不过是更改列表中的链接,这比移动/复制更高效。元素的内容。

因此,对于std::list,我不希望有太多不同,但如果您在列表中存储昂贵的类,您会注意到差异。

PS:std :: unique不会删除元素,它会将它移到后面并返回一个新的'end',使用std :: remove(或std :: list :: remove)来删除元素