std::vector 比较两个vector是否相等

std::vector 比较两个vector是否相等

1. 利用std::vector的operator==函数

1.1 示例代码

#include <vector>
#include <iostream>

int main()
{
    std::vector<int> vector1, vector2;
    for (int i = 1; i < 10; ++i)
    {
        vector1.push_back(i);
        vector2.push_back(i);
    }
    // 直接比较
    if (vector1 == vector2)
    {
        std::cout << "vector1 == vector2" << std::endl;
    }
    else
    {
        std::cout << "vector1 != vector2" << std::endl;
    }

    return 0;
}
/* run output:
vector1 == vector2
*/ 

1.2 解析源码

1.2.1 源码

// std::vector类的operator==重载函数
template <class _Ty, class _Alloc>
_NODISCARD bool operator==(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) {
    return _Left.size() == _Right.size()
           && _STD equal(_Left._Unchecked_begin(), _Left._Unchecked_end(), _Right._Unchecked_begin());
}

// std::equal
template <class _InIt1, class _InIt2, class _Pr>
_NODISCARD _CONSTEXPR20 bool equal(const _InIt1 _First1, const _InIt1 _Last1, const _InIt2 _First2, _Pr _Pred) {
    // compare [_First1, _Last1) to [_First2, ...) using _Pred
    _Adl_verify_range(_First1, _Last1);
    auto _UFirst1      = _Get_unwrapped(_First1);
    const auto _ULast1 = _Get_unwrapped(_Last1);
    auto _UFirst2      = _Get_unwrapped_n(_First2, _Idl_distance<_InIt1>(_UFirst1, _ULast1));
    if constexpr (decltype(_Equal_memcmp_is_safe(_UFirst1, _UFirst2, _Pred))::value) {
#ifdef __cpp_lib_is_constant_evaluated
        if (!_STD is_constant_evaluated())
#endif // __cpp_lib_is_constant_evaluated
        {
            const auto _First1_ch = reinterpret_cast<const char*>(_UFirst1);
            const auto _First2_ch = reinterpret_cast<const char*>(_UFirst2);
            const auto _Count     = static_cast<size_t>(reinterpret_cast<const char*>(_ULast1) - _First1_ch);
            return _CSTD memcmp(_First1_ch, _First2_ch, _Count) == 0;
        }
    }

    for (; _UFirst1 != _ULast1; ++_UFirst1, (void) ++_UFirst2) {
        if (!_Pred(*_UFirst1, *_UFirst2)) {
            return false;
        }
    }

    return true;
}

1.2.2 解析

可以看到,首先判断两个vector的大小是否相等,如果大小不等,则视为不相同;

如果大小相等,再调用std::equal函数来进行判断。

而equal函数,实现核心:

for (; _UFirst1 != _ULast1; ++_UFirst1, (void) ++_UFirst2) {
    if (!_Pred(*_UFirst1, *_UFirst2)) {
        return false;
    }
}

上面的UFirst1以及ULast1都是第一个vector的起始和终止迭代器;

UFirst2是第二个vector的起始迭代器,代码主要比较两个vector相同位置上的值相同即可。

1.3 应用注意事项(存在问题)

1.3.1 示例代码

#include <vector>
#include <iostream>

int main()
{
    int a = 100;
    int b = 200;

    std::vector<int*> vector1;
    vector1.push_back(&a);
    vector1.push_back(&b);

    std::vector<int*> vector2;
    vector2.push_back(&b);
    vector2.push_back(&a);

    if (vector1 == vector2)
    {
        std::cout << "vector1 == vector2" << std::endl;
    }
    else
    {
        std::cout << "vector1 != vector2" << std::endl;
    }

    return 0;
}

/* run output:
vector1 != vector2
*/

1.3.2 存在问题

如上示例,很明显,本期望是两个vector相同,但是经过比较后,却判定为不相同。事与愿违。

问题根因:没有对容器vector的元素排序,std::equal函数只是对比两个容器对称索引处两个数据值是否相同。

应用注意事项:如果应用时,两个容器的元素可能顺序不相同,建议优先对容器元素进行排序。

优化后,示例代码:

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

int main()
{
    int a = 100;
    int b = 200;

    std::vector<int*> vector1;
    vector1.push_back(&a);
    vector1.push_back(&b);

    std::vector<int*> vector2;
    vector2.push_back(&b);
    vector2.push_back(&a);

    // 利用算法先排序
    std::sort(vector1.begin(), vector1.end());
    std::sort(vector2.begin(), vector2.end());

    if (vector1 == vector2)
    {
        std::cout << "vector1 == vector2" << std::endl;
    }
    else
    {
        std::cout << "vector1 != vector2" << std::endl;
    }

    return 0;
}

/* run output:
vector1 == vector2
*/

2. 自定义方法

2.1 仿标准库写法

2.1.1 示例代码

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

bool compareVector(std::vector<int*> vector1, std::vector<int*> vector2)
{
    if (vector1.size() != vector2.size())
    {
        return false;
    }

    std::sort(vector1.begin(), vector1.end());
    std::sort(vector2.begin(), vector2.end());
    auto iter1 = vector1.begin();
    auto iter2 = vector2.begin();
    while (iter1 != vector1.end() && iter2 != vector2.end() && (*iter1) == (*iter2))
    {
        ++iter1;
        ++iter2;
    }
    if (iter1 == vector1.end())
    {
        return true;
    }

    return false;
}

int main()
{
    int a = 100, b = 200, c = 300;

    std::vector<int*> vector1;
    vector1.push_back(&a);
    vector1.push_back(&b);
    vector1.push_back(&c);

    std::vector<int*> vector2;
    vector2.push_back(&b);
    vector2.push_back(&c);
    vector2.push_back(&a);

    if (compareVector(vector1, vector2))
    {
        std::cout << "vector1 == vector2" << std::endl;
    }
    else
    {
        std::cout << "vector1 != vector2" << std::endl;
    }

    return 0;
}

/* run output:
vector1 == vector2
*/

2.1.2 解析

仿标准库的思路,只是自定义多增加了排序的步骤。

2.2 利用std::set容器元素的唯一性

2.2.1 示例代码

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

bool compareVector(std::vector<int*> vector1, std::vector<int*> vector2)
{
    if (vector1.size() != vector2.size())
    {
        return false;
    }
    // 利用std::set元素唯一性特征
    std::set<int*> tempSet(vector1.begin(), vector1.end());
    for (const auto& item2 : vector2)
    {
        if (tempSet.insert(item2).second)
        {
            return false; // 但凡有一个数据插入成功,则视为不相同
        }
    }

    return true;
}

int main()
{
    int a = 100, b = 200, c = 300;

    std::vector<int*> vector1;
    vector1.push_back(&a);
    vector1.push_back(&b);
    vector1.push_back(&c);

    std::vector<int*> vector2;
    vector2.push_back(&b);
    vector2.push_back(&c);
    vector2.push_back(&a);

    if (compareVector(vector1, vector2))
    {
        std::cout << "vector1 == vector2" << std::endl;
    }
    else
    {
        std::cout << "vector1 != vector2" << std::endl;
    }

    return 0;
}

/* run output:
vector1 == vector2
*/

2.2.2 解析

主要思路:利用std::set容器的唯一性特性。

实现方法:利用一个临时std::set,构造时将vector1所有元素填充进去。

如果vector2容器但凡有一个元素插入成功,说明vector2容器中发现有元素与vector1不同,则可判定两个容器不相同。

posted @ 2022-11-14 17:00  kaizenly  阅读(7020)  评论(0编辑  收藏  举报
打赏