【问题标题】:Trying to improve algorithm to be more generic试图改进算法以使其更通用
【发布时间】:2017-09-12 17:20:06
【问题描述】:

我想出了以下算法来删除向量中的连续重复项,但我正在寻找一种方法来改进它并能够将它与其他顺序容器一起使用。

我已经四处寻找一个常见的父容器类型,但到目前为止我什么都想不出来。

有什么想法吗?

谢谢!

template <class T>
void erase_adjacent_duplicate (std::vector<T>& v)
{
    std::vector<T>::iterator it = v.begin();

    while (it != v.end()) 
    {
        if(std::adjacent_find(it, v.end()) == v.end())
        {
            it = v.end();
        }
        else
        {
            it = std::adjacent_find(it, v.end()) - 1;
            v.erase(it + 1);
        }
    }
}

【问题讨论】:

  • 您的代码目前面临的问题究竟是什么?
  • 嗯,通常你会通过传递两个迭代器来做到这一点。另外,您是否假设容器已经排序?
  • @user0042 我正在尝试找到一种方法来编辑它,以便我可以传递一个列表或一个向量或一个 forward_list ......等等......
  • @NirFriedman 它已经排序了
  • 可以是v.erase(std::unique(v.begin(), v.end()), v.end());

标签: c++ algorithm templates containers sequential


【解决方案1】:

使用迭代器作为输入,而不是寻找一个共同的父容器。然后你可以编写你的算法,使其对所有 InputIterators 都有效。见http://en.cppreference.com/w/cpp/iterator

【讨论】:

  • 但是如何从容器中删除元素呢?
  • 由你决定。 std::remove() 在不知道容器类型的情况下工作。 en.cppreference.com/w/cpp/algorithm/remove
  • 之后您必须致电container.erase。迭代器很有用,但大多数时候工作范围是完整的容器,因此拥有允许容器作为参数的接口是有意义的。
【解决方案2】:

C++ 标准库中已经有通用算法std::unique(C++ 标准)

从每个连续的组中删除除第一个元素之外的所有元素 迭代器 i 在范围 [first + 1,last) 满足以下条件:*(i - 1) == i 或 pred((i - 1), *i) != false。

这是一个演示程序

#include <iostream>
#include <vector>
#include <algorithm>

int main() 
{
    std::vector<int> v = { 1, 1, 3, 3, 3, 2, 2 };

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

    for (int x : v) std::cout << x << ' ';
    std::cout << std::endl;

    return 0;
}

它的输出是

1 3 2

考虑到数组没有像erase 这样的成员函数。因此,您不能为每个包含erase 调用的顺序容器编写通用函数。

【讨论】:

  • 但是使用 std::unique 我不能保存像 {1,2,3,2,3,1,2} 这样的列表,对吗?它不会返回类似 {1,2,3} 的东西吗?我的目标实际上只是删除连续的元素,而不是让它们只出现一次。
  • @VincentDM:查看文档。 std::unique 只“删除”相邻的相等元素。
  • @VincentDM 该算法处理连续的等效元素组。请参阅我帖子中的演示程序。
【解决方案3】:

您可以为容器类型创建模板,例如:

template <class Cont>
void erase_adjacent_duplicate(Cont& cont)
{
     cont.erase(std::unique(std::begin(cont), std::end(cont)), std::end(cont));
}

【讨论】:

  • 为什么不把两个迭代器传给函数呢?然后你可以将它与 C 数组一起使用。这是惯用的方式。
  • @NirFriedman:您不能从 c 数组中擦除元素。 (大小是固定的)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-14
  • 1970-01-01
相关资源
最近更新 更多