unordered map is an associative container that contains key-value pairs with unique keys. Search, insertion, and removal of elements have average constant-time complexity. Internally, the elements are not sorted in any particular order,but organized into buckets. Which bucket an element is placed into depends entirely on the hash of its key. This allows fast access to individual elements, since once the hash is computed, it refers to the exact bucket the element is placed into.

unordered_map containers are faster than map containers to access individual elements by their key, although they are generally less efficient for range iteration through a subset of their elements.

unordered_map's generally use more memory. A map just has a few house-keeping pointers then memory for each object. Contrarily, unordered_map's have a big array (these can get quite big in some implementations) and then additional memory for each object. If you need to be memory-aware, a map should prove better, because it lacks the large array.

unordered_map is an associated container that stores elements formed by combination of key value and a mapped value. The key value is used to uniquely identify the element and mapped value is the content associated with the key. Both key and value can be of any type predefined or user-defined. Internally unordered_map is implemented using Hash Table,the key provided to map are hashed into indices of hash table that is why performance of data structure depends on hash function a lot but on an average the cost of look-up from hash table is O(1). In worst case unordered_map may require O(n) time but practically it is much faster and outperforms tree based maps.

std::map对应的数据结构是红黑树。红黑树是一种近似于平衡的二叉查找树,里面的数据是有序的。在红黑树上做查找、插入、删除操作的时间复杂度为O(logN)。而std::unordered_map对应哈希表,哈希表的特点就是查找效率高,时间复杂度为常数级别O(1), 而额外空间复杂度则要高出许多。所以对于需要高效率查询的情况,使用std::unordered_map容器,但是std::unordered_map对于迭代器遍历效率并不高。而如果对内存大小比较敏感或者数据存储要求有序的话,则可以用std::map容器。

下面是从其他文章中copy的测试代码,详细内容介绍可以参考对应的reference:

#include "unordered_map.hpp"
#include <iostream>
#include <string>
#include <unordered_map>

//////////////////////////////////////////////////
// reference: http://en.cppreference.com/w/cpp/container/unordered_map
int test_unordered_map1()
{
	// Create an unordered_map of three strings (that map to strings)
	std::unordered_map<std::string, std::string> u = {
			{ "RED", "#FF0000" },
			{ "GREEN", "#00FF00" },
			{ "BLUE", "#0000FF" }
	};

	// Iterate and print keys and values of unordered_map
	for (const auto& n : u) {
		std::cout << "Key:[" << n.first << "] Value:[" << n.second << "]\n";
	}

	// Add two new entries to the unordered_map
	u["BLACK"] = "#000000";
	u["WHITE"] = "#FFFFFF";

	// Output values by key
	std::cout << "The HEX of color RED is:[" << u["RED"] << "]\n";
	std::cout << "The HEX of color BLACK is:[" << u["BLACK"] << "]\n";

	std::cout << "The u's size: " << u.size() << std::endl;

	return 0;
}

/////////////////////////////////////////////////////
// reference: http://www.cplusplus.com/reference/unordered_map/unordered_map/at/
typedef std::unordered_map<std::string, std::string> stringmap;

stringmap merge(stringmap a, stringmap b) {
	stringmap temp(a); temp.insert(b.begin(), b.end()); return temp;
}

int test_unordered_map2()
{
	////////// at/size
	std::unordered_map<std::string, int> mymap = { { "Mars", 3000 }, { "Saturn", 60000 }, { "Jupiter", 70000 } };

	mymap.at("Mars") = 3396;
	mymap.at("Saturn") += 272;
	mymap.at("Jupiter") = mymap.at("Saturn") + 9638;

	for (auto& x : mymap) {
		std::cout << x.first << ": " << x.second << std::endl;
	}

	std::cout << "mymap.size() is " << mymap.size() << std::endl;

	/////////// begin
	std::unordered_map<std::string, std::string> mymap2 = { { "Australia", "Canberra" }, { "U.S.", "Washington" }, { "France", "Paris" } };

	std::cout << "mymap2 contains:";
	for (auto it = mymap2.begin(); it != mymap2.end(); ++it)
		std::cout << " " << it->first << ":" << it->second;
	std::cout << std::endl;

	std::cout << "mymap2's buckets contain:\n";
	for (unsigned i = 0; i < mymap2.bucket_count(); ++i) {
		std::cout << "bucket #" << i << " contains:";
		for (auto local_it = mymap2.begin(i); local_it != mymap2.end(i); ++local_it)
			std::cout << " " << local_it->first << ":" << local_it->second;
		std::cout << std::endl;
	}

	////////////// bucket
	std::unordered_map<std::string, std::string> mymap3 = {
			{ "us", "United States" },
			{ "uk", "United Kingdom" },
			{ "fr", "France" },
			{ "de", "Germany" }
	};

	for (auto& x : mymap3) {
		std::cout << "Element [" << x.first << ":" << x.second << "]";
		std::cout << " is in bucket #" << mymap3.bucket(x.first) << std::endl;
	}

	/////////////// count
	std::unordered_map<std::string, double> mymap4 = {
			{ "Burger", 2.99 },
			{ "Fries", 1.99 },
			{ "Soda", 1.50 } };

	for (auto& x : { "Burger", "Pizza", "Salad", "Soda" }) {
		if (mymap4.count(x)>0)
			std::cout << "mymap4 has " << x << std::endl;
		else
			std::cout << "mymap4 has no " << x << std::endl;
	}

	///////////////// erase
	std::unordered_map<std::string, std::string> mymap5;

	// populating container:
	mymap5["U.S."] = "Washington";
	mymap5["U.K."] = "London";
	mymap5["France"] = "Paris";
	mymap5["Russia"] = "Moscow";
	mymap5["China"] = "Beijing";
	mymap5["Germany"] = "Berlin";
	mymap5["Japan"] = "Tokyo";

	// erase examples:
	mymap5.erase(mymap5.begin());      // erasing by iterator
	mymap5.erase("France");             // erasing by key
	mymap5.erase(mymap5.find("China"), mymap5.end()); // erasing by range

	// show content:
	for (auto& x : mymap5)
		std::cout << x.first << ": " << x.second << std::endl;

	////////////////////// find
	std::unordered_map<std::string, double> mymap6 = {
			{ "mom", 5.4 },
			{ "dad", 6.1 },
			{ "bro", 5.9 } };

	std::string input;
	std::cout << "who? ";
	getline(std::cin, input);

	std::unordered_map<std::string, double>::const_iterator got = mymap6.find(input);

	if (got == mymap6.end())
		std::cout << "not found";
	else
		std::cout << got->first << " is " << got->second;

	std::cout << std::endl;

	//////////////////// insert
	std::unordered_map<std::string, double>
		myrecipe,
		mypantry = { { "milk", 2.0 }, { "flour", 1.5 } };

	std::pair<std::string, double> myshopping("baking powder", 0.3);

	myrecipe.insert(myshopping);                        // copy insertion
	myrecipe.insert(std::make_pair<std::string, double>("eggs", 6.0)); // move insertion
	myrecipe.insert(mypantry.begin(), mypantry.end());  // range insertion
	myrecipe.insert({ { "sugar", 0.8 }, { "salt", 0.1 } });    // initializer list insertion

	std::cout << "myrecipe contains:" << std::endl;
	for (auto& x : myrecipe)
		std::cout << x.first << ": " << x.second << std::endl;

	std::cout << std::endl;

	//////////////////// =
	stringmap first = { { "AAPL", "Apple" }, { "MSFT", "Microsoft" } };  // init list
	stringmap second = { { "GOOG", "Google" }, { "ORCL", "Oracle" } };   // init list
	stringmap third = merge(first, second);                      // move
	first = third;                                    // copy

	std::cout << "first contains:";
	for (auto& elem : first) std::cout << " " << elem.first << ":" << elem.second;
	std::cout << std::endl;

	return 0;
}

//////////////////////////////////////////////////////
// reference: http://www.geeksforgeeks.org/unordered_map-in-stl-and-its-applications/
int test_unordered_map3()
{
	// key will be of string type and mapped value will be of double type
	std::unordered_map<std::string, double> umap;

	// inserting values by using [] operator
	umap["PI"] = 3.14;
	umap["root2"] = 1.414;
	umap["root3"] = 1.732;
	umap["log10"] = 2.302;
	umap["loge"] = 1.0;

	// inserting value by insert function
	umap.insert(std::make_pair("e", 2.718));

	std::string key = "PI";

	// If key not found in map iterator to end is returned
	if (umap.find(key) == umap.end()) {
		std::cout << key << " not found\n\n";
	} else {// If key found then iterator to that key is returned
		std::cout << "Found " << key << "\n\n";
	}

	key = "lambda";
	if (umap.find(key) == umap.end())
		std::cout << key << " not found\n";
	else
		std::cout << "Found " << key << std::endl;

	//  iterating over all value of umap
	std::unordered_map<std::string, double>::iterator itr;
	std::cout << "\nAll Elements : \n";
	for (itr = umap.begin(); itr != umap.end(); itr++) {
		// itr works as a pointer to pair<string, double> type itr->first stores the key part
		// and itr->second stroes the value part
		std::cout << itr->first << "  " << itr->second << std::endl;
	}

	return 0;
}

GitHubhttps://github.com/fengbingchun/Messy_Test

C++11中std::unordered_map的使用的更多相关文章

  1. C++11中std::function的使用

    class template std::function is a general-purpose polymorphic function wrapper. Instances of std::fu ...

  2. C++11中std::move的使用

    std::move is used to indicate that an object t may be "moved from", i.e. allowing the effi ...

  3. C++11中std::bind的使用

    std::bind: Each argument may either be bound to a value or be a placeholder: (1).If bound to a value ...

  4. C++11中std::forward的使用 (转)

    std::forward argument: Returns an rvalue reference to arg if arg is not an lvalue reference; If arg ...

  5. C++11中std::forward的使用

    std::forward argument: Returns an rvalue reference to arg if arg is not an lvalue reference; If arg ...

  6. C++11中std::move、std::forward、左右值引用、移动构造函数的测试

    关于C++11新特性之std::move.std::forward.左右值引用网上资料已经很多了,我主要针对测试性能做一个测试,梳理一下这些逻辑,首先,左值比较熟悉,右值就是临时变量,意味着使用一次就 ...

  7. 用C++11的std::async代替线程的创建

    c++11中增加了线程,使得我们可以非常方便的创建线程,它的基本用法是这样的: void f(int n); std::thread t(f, n + 1); t.join(); 但是线程毕竟是属于比 ...

  8. C++11 使用 std::async创建异步程序

    c++11中增加了线程,使得我们可以非常方便的创建线程,它的基本用法是这样的: void f(int n); std::thread t(f, n + 1); t.join(); 但是线程毕竟是属于比 ...

  9. (原创)用C++11的std::async代替线程的创建

    c++11中增加了线程,使得我们可以非常方便的创建线程,它的基本用法是这样的: void f(int n); std::thread t(f, n + ); t.join(); 但是线程毕竟是属于比较 ...

随机推荐

  1. python中的运算符优先级(其它语言也试用)

  2. linux vi常用操作

    1.基本操作 进入vi vi 或者 vim 进入一个文件或者新建一个文件 例如:vim 11.txt vi有3种模式 一般模式:刚进入时.按esc时. 编辑模式:按下字母[i, I, o, O, a, ...

  3. ringojs java jar 集成使用

    ringojs 可以方便进行java 代码的集成,我们可以把下载的jar包放到classpath,后者ringojs 的lib 目录 也可以进行代码编写 测试代码 集成了java 的一个hashid ...

  4. pfsense openvpn上网终于通了

    先看配置,等会在说过程中遇到的问题: 1.openvpn配置: /var/etc/openvpn/server2.conf下: port 1195 proto tcp dev tap writepid ...

  5. 数据抽取 CDC

    什么是数据抽取 数据抽取是指从源数据源系统抽取目的数据源系统需要的数据.实际应用中,数据源较多采用的是关系数据库. [编辑] 数据抽取的方式 (一) 全量抽取 全量抽取类似于数据迁移或数据复制,它将数 ...

  6. opencv中读取显示图像

    opencv是个开源的图像处理的库,小到基本的图像处理函数,如图像移动放大缩小,大到人脸识别,部分机器学习的知识,所以是个学习的不错的库.之前有图像处理的知识,这次再学习下这个开源库. 先上基础的图像 ...

  7. 【linux】U盘安装启动出现press the enter key to begin the installation process 就不动弹了

    今天在物理机上安装centOS6.5  64bit 系统的时候,出现了U盘安装启动出现press the enter key to begin the installation process 就不动 ...

  8. NLTK在自然语言处理

    nltk-data.zip 本文主要是总结最近学习的论文.书籍相关知识,主要是Natural Language Pracessing(自然语言处理,简称NLP)和Python挖掘维基百科Infobox ...

  9. Django Admin定制

    Django内置的Admin是对于model中对应的数据表进行增删改查提供的组件,使用方式有: 依赖APP: django.contrib.auth django.contrib.contenttyp ...

  10. vim自定义配置之自动括号

    BundlenInstall安装auto-pairs vimConfig/plugin/auto-pairs-setting.vim let g:autopairsflymode=