C++11 新用法
基于哈希的 map 和 set
简述
基于哈希的 map 和 set ,它们分别叫做 unordered_map, unordered_set 。数据分布越平均,性能相较 map 和 set 来说提升就更大。但由于它们基于哈希,所以并不像 map 和 set 一样能自动排序;它们都是无序的。
我做了一个测试:随机生成 \(10^7\) 个 int 范围内的整数(平均分布),然后将其分别插入 map 和 unordered_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\n", 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\n", 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\n", 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 << '\n';
与其相关的是一个新的关键字 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 << '\n';
// C++11 之后
for (auto val : mp)
cout << val.first << ' ' << val.second << '\n';
模板嵌套时一个小改善
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 << '\n';
}
sort(v.begin(), v.end(), [](const pair<int, int> &a, const pair<int, int> &b) {
return a.first > b.first;
});
cout << "After sort:\n";
for (auto& val : v) {
cout << val.first << ' ' << val.second << '\n';
}
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);
// ...
}
C++11 新用法的更多相关文章
- C++11之for循环的新用法《转》
相关资料:https://legacy.gitbook.com/book/changkun/cpp1x-tutorial/details C++11之for循环的新用法 C++使用如下方法遍历一个容器 ...
- C++11常用特性介绍——for循环新用法
一.for循环新用法——基于范围的for循环 for(元素类型 元素对象 : 容器对象) { //遍历 } 1)遍历字符串 std::string str = "hello world&qu ...
- C++ 11学习和掌握 ——《深入理解C++ 11:C++11新特性解析和应用》读书笔记(一)
因为偶然的机会,在图书馆看到<深入理解C++ 11:C++11新特性解析和应用>这本书,大致扫下,受益匪浅,就果断借出来,对于其中的部分内容进行详读并亲自编程测试相关代码,也就有了整理写出 ...
- [转载] C++11新特性
C++11标准发布已有一段时间了, 维基百科上有对C++11新标准的变化和C++11新特性介绍的文章. 我是一名C++程序员,非常想了解一下C++11. 英文版的维基百科看起来非常费劲,而中文版维基百 ...
- c++11新标准for循环和lambda表达式
:first-child { margin-top: 0px; } .markdown-preview:not([data-use-github-style]) h1, .markdown-previ ...
- C++11新特性之一——Lambda表达式
C++11新特性总结可以参考:http://www.cnblogs.com/pzhfei/archive/2013/03/02/CPP_new_feature.html#section_6.8 C++ ...
- C++11新标准:nullptr关键字
一.nullptr的意义 1.NULL在C中的定义 #define NULL (void*)0 2.NULL在C++中的定义 #ifndef NULL #ifdef __cplusplus #defi ...
- C++11新标准:decltype关键字
一.decltype意义 有时我们希望从表达式的类型推断出要定义的变量类型,但是不想用该表达式的值初始化变量(如果要初始化就用auto了).为了满足这一需求,C++11新标准引入了decltype类型 ...
- C++11新标准:auto关键字
一.auto意义 编程时常常需要把表达式的值赋给变量,这就要求在声明变量的时候清楚地知道表达式的类型,然后要做到这一点并非那么容易.为了解决这个问题,C++11新标准引入了auto类型说明符,用它就能 ...
随机推荐
- 查找第K大的值
这种题一般是给定N个数,然后N个数之间通过某种计算得到了新的数列,求这新的数列的第K大的值 POJ3579 题意: 用$N$个数的序列$x[i]$,生成一个新序列$b$. 新的序列定义为:对于任意的$ ...
- python爬虫步骤 (新手备学 )爬虫编程。
Python爬虫是用Python编程语言实现的网络爬虫,主要用于网络数据的抓取和处理,相比于其他语言,Python是一门非常适合开发网络爬虫的编程语言,大量内置包,可以C Python爬虫可以做的事情 ...
- 15.python文件(file)方法详解
文件的基本操作 文件读写: 文件的读写满足以下3个步骤: 1).打开文件 2).操作数据(读.写) 3).关闭文件 --> 不要忘记 1).打开文件: python的open() 方法用于打开一 ...
- JS DOM中getElement系列和querySelector系列获取节点
节点查找方法 document.getElementById() 前面必须是document document.getElementsByName() 前面必须是document ele.getEl ...
- VS GIT 使用入门---我只是搬运工
网上资料推荐 GitHub 新手详细教程 - Hanani_Jia的博客 - CSDN博客 https://blog.csdn.net/Hanani_Jia/article/details/77950 ...
- 浅谈python的第三方库——numpy(二)
前一期博文中,初步探索了numpy中矩阵的几种运算操作,本文将展示numpy矩阵的元素抽取与合并操作. 1 元素抽取 在我们使用矩阵的时候,有时需要提取出矩阵的某些位置上的元素单独研究,这时就需要熟悉 ...
- Codeforces Round #599 (Div. 2) D. 0-1 MST(bfs+set)
Codeforces Round #599 (Div. 2) D. 0-1 MST Description Ujan has a lot of useless stuff in his drawers ...
- (转)jvm具体gc算法介绍标记整理--标记清除算法
转自:https://www.cnblogs.com/ityouknow/p/5614961.html GC算法 垃圾收集器 概述 垃圾收集 Garbage Collection 通常被称为“GC”, ...
- The Way to Home CodeForces - 910A
4个月前做的一道题,当时不知道为什么,写了一个bfs,直接就超时了. 现在再看这个题目,发现就是一个简单的贪心,每次走最远即可. #include <bits/stdc++.h> usin ...
- BZOJ 3280: 小R的烦恼
Description 小R最近遇上了大麻烦,他的程序设计挂科了.于是他只好找程设老师求情.善良的程设老师答应不挂他,但是要 求小R帮助他一起解决一个难题.问题是这样的,程设老师最近要进行一项邪恶的实 ...