IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++漫游记 (2):比较两个map容器是否相同 -> 正文阅读

[C++知识库]C++漫游记 (2):比较两个map容器是否相同

需求:
比较两个同类型的std::map<key, value>变量是否相同。

实现:
对比流程:
1.size不同,则map不相同。
2.size相同,遍历map1,查找map2中是否存在相同key,不存在则map不相同。
3.存在相同key,比较value是否相同,不同则map不相同。

这里采用模板函数,以支持value的不同类型。如果value是单一类型,可以直接将模板函数具体化。
代码如下:

template<typename K, typename V>
bool CompareMap(const std::map<K, V>& map1, const std::map<K, V>& map2)
{
    if (map1.size() != map2.size())
    {
        return false;
    }

    for (auto iter1 : map1)
    {
        auto iter2 = map2.find(iter1.first);
        if (iter2 == map2.end())
        {
            return false;
        }
        else
        {
            if (iter1.second != iter2->second)
            {
                return false;
            }
        }
    }

    return true;
}

OK,比较两个map容器是否相同的函数已完成,好像也没啥毛病。再次回顾流程时,忽然发现有个地方被忽略:经过第1步判断后,两个map的size是相同的,因此我们可以直接使用迭代器同时遍历两个map,并比较这两个迭代器所指向的key和value是否相同。为什么可以这样?因为map容器是有序的,按key值从小到大排列

调整对比流程:
1.size不同,则map不相同。
2.size相同,同时遍历map1、map2,比较迭代器指向元素的key和value是否相同,只要有一个不同,则map不相同。

代码如下:

template<typename K, typename V>
bool CompareMap(const std::map<K, V>& map1, const std::map<K, V>& map2)
{
    if (map1.size() != map2.size())
    {
        return false;
    }

    auto iter1 = map1.begin();
    auto iter2 = map2.begin();
    for (; iter1 != map1.end(); ++iter1, ++iter2)
    {
        if (iter1->first != iter2->first || iter1->second != iter2->second)
        {
            return false;
        }
    }

    return true;
}

这样就可以了。从代码结构看,第二种效率是优于第一种的(最后的完整代码包含时间测试)。

上面完成了map的比较函数,还剩下value的比较,即上面代码中的iter1.second != iter2->seconditer1->second != iter2->second。如果value的类型是int、std::string、结构体、类等,只要支持 != 运算(另外还有 == 运算,一般同时实现,不过上面没用到),就可以直接使用。如果不支持,则需要重载 != 运算。

下面以结构体为例(类也是一样)。

struct MapValue
{
    int n;
    std::string s;

    bool operator==(const MapValue& _Value) const
    {
        return n == _Value.n && s == _Value.s;
    }

    bool operator!=(const MapValue& _Value) const
    {
        return n != _Value.n || s != _Value.s;
    }
};

上面定义了结构体MapValue,同时重载了实现了 == 和 != 运算。如果重载运算符放在结构体外,则为:

struct MapValue
{
    int n;
    std::string s;
};

bool operator==(const MapValue& _Value1, const MapValue& _Value2)
{
    return _Value1.n == _Value2.n && _Value1.s == _Value2.s;
}

bool operator!=(const MapValue& _Value1, const MapValue& _Value2)
{
    return _Value1.n != _Value2.n || _Value1.s != _Value2.s;
}

关于结构体,还有一种比较方式,就是使用memcmp(不推荐,仅作了解)。这时比较value就可以写为:if (0 != memcmp(&it1.second, &it2->second, sizeof(V)))。使用memcmp有些限制:数据成员是基本类型或简单复合类型(char[n]),并且结构体要1字节对齐。如果不是1字节对齐,结构体中被填充的字节部分可能是随机或无效的内容。另外数据成员也不能是自带内存管理类型(如std::string)。以上情况使用memcmp会得到意外的结果。

下面给出完整代码(带时间测试):

// CompareMap.cpp
//

#include <iostream>
#include <map>
#include <Windows.h>

struct MapValue
{
    int n;
    std::string s;

    MapValue(int _n = 0, std::string _s = "")
    {
        n = _n;
        s = _s;
    }

    bool operator==(const MapValue& _Value) const
    {
        return n == _Value.n && s == _Value.s;
    }
    bool operator!=(const MapValue& _Value) const
    {
        return n != _Value.n || s != _Value.s;
    }
};

template<typename K, typename V>
bool CompareMap1(const std::map<K, V>& map1, const std::map<K, V>& map2)
{
    if (map1.size() != map2.size())
    {
        return false;
    }

    for (auto iter1 : map1)
    {
        auto iter2 = map2.find(iter1.first);
        if (iter2 == map2.end())
        {
            return false;
        }
        else
        {
            if (iter1.second != iter2->second)
            {
                return false;
            }
        }
    }

    return true;
}

template<typename K, typename V>
bool CompareMap2(const std::map<K, V>& map1, const std::map<K, V>& map2)
{
    if (map1.size() != map2.size())
    {
        return false;
    }

    auto iter1 = map1.begin();
    auto iter2 = map2.begin();
    for (; iter1 != map1.end(); ++iter1, ++iter2)
    {
        if (iter1->first != iter2->first || iter1->second != iter2->second)
        {
            return false;
        }
    }

    return true;
}

int main()
{
    std::map<int, MapValue> map1;
    std::map<int, MapValue> map2;
    for (int i = 0; i < 1000000; ++i)
    {
        map1[i] = MapValue(1, "123");
        map2[i] = MapValue(1, "123");
    }
    map1[1000000] = MapValue(1, "123");
    map2[1000000] = MapValue(1, "1234");

    ULONGLONG iTime = 0;
    iTime = GetTickCount64();
    std::cout << (CompareMap1(map1, map2) ? "map1 == map2" : "map1 != map2") << std::endl;
    //std::cout << (CompareMap2(map1, map2) ? "map1 == map2" : "map1 != map2") << std::endl;
    std::cout << "Time: " << GetTickCount64() - iTime << "ms" << std::endl;
    
    return 0;
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-07-14 22:56:44  更:2021-07-14 22:56:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/4 3:58:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码