如何检查两个std :: vector是否只包含相同的元素?

时间:2012-05-08 21:13:22

标签: c++ algorithm stl vector comparison

我需要一个算法或标准库函数来比较两个向量元素,如下所示:

class Utility
{
    template <class T>
    static bool CheckIfVectorsEquivalent(   const std::vector<T> & Vec1,
                                            const std::vector<T> & Vec2)
    {
        // ???
    }
};

按照以下规范工作:

std::vector<int> v1, v2, v3, v4, v5, v6, v7, v8;

// Returns false when not all the elements are matching between vectors
v1.push_back(1);
v1.push_back(3);
v1.push_back(5);
v2.push_back(2);
v2.push_back(3);
v2.push_back(8);
Utility::CheckIfVectorsEquivalent(v1, v2);  // Must return false

// Returns true when all the elements match, even if the are not in the same order
v3.push_back(3);
v3.push_back(1);
v3.push_back(7);
v4.push_back(7);
v4.push_back(3);
v4.push_back(1);
Utility::CheckIfVectorsEquivalent(v3, v4);  // Must return true

// Returns false when one of the vectors is subset of the other one
v5.push_back(3);
v5.push_back(1);
v5.push_back(7);
v6.push_back(7);
v6.push_back(3);
v6.push_back(1);
v6.push_back(18);
v6.push_back(51);
Utility::CheckIfVectorsEquivalent(v5, v6);  // Must return false

// Returns true when the both vectors are empty
Utility::CheckIfVectorsEquivalent(v7, v8);  // Must return true

是否有任何标准(使用STL)方式?如果没有,我该怎么写这个算法?这让我很困惑。

7 个答案:

答案 0 :(得分:18)

标准方法是对这两个向量进行排序并使用运算符== ,它会比较相应的值。

实现此算法的示例解决方案是:

#include <vector>
#include <algorithm>

template<typename T>
bool compare(std::vector<T>& v1, std::vector<T>& v2)
{
    std::sort(v1.begin(), v1.end());
    std::sort(v2.begin(), v2.end());
    return v1 == v2;
}

由于排序,它的复杂性为O(n * log(n))。

答案 1 :(得分:11)

如果您只使用c ++ 11解决方案,那么std::is_permutation正是您想要的

template <class FI1, class FI2>
bool is_permutation ( FI1 first, FI1 last, FI2 d_first );

如果你不能那样做,那么在即将推出的1.50版本中,将会有

boost::algorithm::is_permutation

具有相同的界面。

答案 2 :(得分:3)

从每个向量创建一个multiset,然后只是比较它们是否相等。

答案 3 :(得分:0)

对于未排序的输入,这个问题有一个O(n)解决方案:

#include <vector>
#include <algorithm>
#include <iostream>
#include <boost/function_output_iterator.hpp>

template <typename T>
T xorfunc(const T& a, const T& b) {
  return a^b;
}

template <typename T>
bool compare(const std::vector<T>& v1, const std::vector<T>& v2) {
  if (v1.size() != v2.size())
    return false;

  T result = 0;
  std::transform(v1.begin(), v1.end(), v2.begin(), boost::make_function_output_iterator([&result](const T& r) { result ^= r; }), std::ptr_fun(&xorfunc<T>));
  return !result;
}

适用于整数输入,并利用a ^ b ^ c ^ d == 0对任何配对值组合的事实。它永远不会给出假阴性,它可能潜在地给出误报,但你可以在O(n)空间/时间中进一步减少这些误报。如果你大多数都是负片,那么这可能是一个有用的预先排序+比较步骤来快速排除它们。它适用于您展示的所有测试用例:

int main() {
    std::vector<int> v1, v2, v3, v4, v5, v6, v7, v8;

    // Returns false when not all the elements are matching between vectors
    v1.push_back(1);
    v1.push_back(3);
    v1.push_back(5);
    v2.push_back(2);
    v2.push_back(3);
    v2.push_back(8);
    std::cout << compare(v1, v2) << " (false)" << std::endl;  // Must return false

    // Returns true when all the elements match, even if the are not in the same order
    v3.push_back(3);
    v3.push_back(1);
    v3.push_back(7);
    v4.push_back(7);
    v4.push_back(3);
    v4.push_back(1);
    std::cout << compare(v3, v4) << " (true)" << std::endl;  // Must return true

    // Returns false when one of the vectors is subset of the other one
    v5.push_back(3);
    v5.push_back(1);
    v5.push_back(7);
    v6.push_back(7);
    v6.push_back(3);
    v6.push_back(1);
    v6.push_back(18);
    v6.push_back(51);
    std::cout << compare(v5, v6) << " false" << std::endl;  // Must return false

    // Returns true when the both vectors are empty
    std::cout << compare(v7, v8) << " true" << std::endl;  // Must return true

}

给出:

0 (false)
1 (true)
0 false
1 true

答案 4 :(得分:0)

最简单的方法是创建Vec1和Vec2的副本,对它们进行排序并使用==进行比较。

另一种方法是从Vec1和Vec2构建两个多重集,并使用==进行比较。

另一种方法是使用map(std :: map或unordered_map)来存储计数器 - 即为Vec1的每个元素增加存储值并为Vec2的每个存储元素递减,然后检查map是否包含非零元素。如果地图中存储了非零元素,则向量不相等。

凌乱的伪代码示例:

std::vector<Value> vec1, vec2;
//initialize vec1 and vec2, fill with data
typedef int Counter;
typedef unordered_map<Value, Counter> CounterMap;

CounterMap counters;
for (size_t i = 0; i < vec1.size(); i++)
    counters[vec1[i]]++;
for (size_t i = 0; i < vec2.size(); i++)
    counters[vec2[i]]--;

bool equal = true;
for (CounterMap::const_iterator i = coutners.begin(); equal && (i != counters.end()); i++)
    if (i->second != 0)
        equal = false;

取决于你的STL(或boost)实现,数据类型和向量中存储数据的顺序)其中一种方法会更快,但很难说出哪一种。

答案 5 :(得分:0)

如果我们认为int足够大以用于在以下算法中完成的计算,则存在简单的O(N)算法。

0:初始化:有大小为max(v1,v2),product1 = 1,product2 = 1

1:如果v1的大小!= v2的大小

,则返回false

2:

foreach (  i in v1 ) {
   product1 *= primes[v1[i]]
   product2 *= primes[v2[i]]
}

3

result product1 == product2;

答案 6 :(得分:-1)

  v7.push_back(3);
  v7.push_back(1);
  v7.push_back(7);

  v8.push_back(7);
  v8.push_back(3);
  v8.push_back(1);
  v8.push_back(1);
  v8.push_back(7);

  std::cout << compare(v7, v8) << " true or false" << std::endl;  

上述条件,函数比较将返回true或false。我丢失了计数。 如果返回true。 我们不能用这种方式: 标准方法是对这两个向量进行排序,并使用operator ==,比较相应的值。