• C++11 新用法


    基于哈希的 map 和 set

    简述

    基于哈希的 mapset ,它们分别叫做 unordered_map, unordered_set 。数据分布越平均,性能相较 mapset 来说提升就更大。但由于它们基于哈希,所以并不像 mapset 一样能自动排序;它们都是无序的。

    我做了一个测试:随机生成 (10^7)int 范围内的整数(平均分布),然后将其分别插入 mapunordered_map,再完整的做一次查询,查看时间和内存上的消耗。

    测试代码

    #include <cstdio>
    #include <cstdlib>
    #include <ctime>
    #include <map>
    #include <vector>
    #include <unordered_map>
    
    using namespace std;
    
    vector<pair<int, int>> data;
    
    int main() {
        freopen("map.txt", "r", stdin);
        data.resize(5000000);
        map<int, int> mp;
        double st, ed;
        st = clock();
        for (int i = 0; i < 5000000; ++i) scanf("%d%d", &data[i].first, &data[i].second);
        ed = clock();
        printf("Read: %dms
    ", int(1000.0 * (ed - st) / CLOCKS_PER_SEC));
        st = clock();
        for (int i = 0; i < 5000000; ++i) mp[data[i].first] = data[i].second;
        ed = clock();
        printf("Insert: %dms
    ", int(1000.0 * (ed - st) / CLOCKS_PER_SEC));
        st = clock();
        for (int i = 0; i < 5000000; ++i) data[i].second = mp[data[i].first];
        ed = clock();
        printf("Query: %dms
    ", int(1000.0 * (ed - st) / CLOCKS_PER_SEC));
        data = vector<pair<int, int>>();
    }
    

    测试结果

    结构 总耗时 插入耗时 查询耗时 内存
    map 18,041 MS 10,299 MS 7,742 MS 230.7 MB
    unordered_map 7,138 MS 5,426 MS 1,712 MS 212.0 MB

    当数据分布平均时,从时间上看,两者的性能差距约为 (7138 / 18041 approx 40\%)

    提示

    即使在平均意义下 unordered_map 有着比 map 更高的效率,但是由于两者的实现(前者哈希,后者平衡树), unordered_map 单次插入的最差复杂度是 (O(N))map 单次插入的最差复杂度是 (O(log N)) 。所以在出题人故意造数据卡 unordered_map 使其内部哈希表发生严重冲突时,unordered_map 就会变得很慢。

    语法上的变化

    auto 关键字的新含义

    在 C++11 中,auto 关键字被赋予了新的含义。其功能是自动类型推导。

    auto x = 3; // y的类型自动推导为 int
    auto y = make_pair(1, 2); // y的类型自动推导为 pair<int, int>
    auto z; // 编译错误, z的类型需要一个初始值才能推导
    
    map<int, int> mp;
    // iter的类型推导为map<int, int>::iterator
    for (auto iter = mp.begin(); iter != mp.end(); ++iter)
        cout << iter->first << ' ' << iter->second << '
    ';
    

    与其相关的是一个新的关键字 decltype,取得某一个值的类型。

    int a = 1, b = 2;
    decltype(a + b) c; // c为int
    

    增强的 for(基于范围的for循环)

    map<int, int> mp;
    
    // C++11 之前遍历
    for (map<int, int>::iterator it = mp,begin(); it != mp,end(); ++it)
    	cout << it->first << ' ' << it->second << '
    ';
    
    // C++11 之后
    for (auto val : mp)
    	cout << val.first << ' ' << val.second << '
    ';
    

    模板嵌套时一个小改善

    priority_queue<pair<int, int> > heap; // C++11之前需加一个空格避免歧义
    priority_queue<pair<int, int>> heap; // C++11之后不用
    

    初始化列表

    更简单的初始化方式。

    vector<pair<int, int>> v{ {1, 2}, {2, 3}, {3, 4} };
    
    // 等价于下面代码
    vector<pair<int, int> > v;
    v.push_back(make_pair(1, 2));
    v.push_back(make_pair(2, 3));
    v.push_back(make_pair(3, 4));
    

    lambda 表达式

    下面用一个例子讲述一下lambda表达式的大致用法。

    #include <iostream>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    
    int main() {
        vector<pair<int, int>> v{ {1, 2}, {2, 3}, {3, 4} };
        for (auto& val : v) {
            cout << val.first << ' ' << val.second << '
    ';
        }
        sort(v.begin(), v.end(), [](const pair<int, int> &a, const pair<int, int> &b) {
            return a.first > b.first;
        });
        cout << "After sort:
    ";
        for (auto& val : v) {
            cout << val.first << ' ' << val.second << '
    ';
        }
        return 0;
    }
    

    代码里的 sort,在C++11之前比较常见的等价写法是:

    bool cmp(const pair<int, int> &a, const pair<int, int> &b) {
        return a.first > b.first;
    }
    
    int main() {
        // ...
        sort(v.begin(), v.end(), cmp);
        // ...
    }
    
  • 相关阅读:
    BZOJ2456: mode 众数卡空间
    BZOJ4128: Matrix 矩阵BSGS
    [SDOI2011]计算器 BSGS
    前台中文搜索到后台乱码
    批量删除实现js+springmvc
    基于Jquery+Ajax+Json实现分页显示
    分页条的制作
    input text中不能显示空格后的内容
    mysql存入中文乱码问题
    WEBROOT根目录 <%=request.getContextPath()%>
  • 原文地址:https://www.cnblogs.com/sandychn/p/11346363.html
Copyright © 2020-2023  润新知