unordered_map in C++ STL

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.  unorder map是关联性容器,保存了key和对应的value。
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 search, insert and delete from hash table is O(1).  unordered_map 使用hash table是实现,依赖于哈希函数,search,insert和delete的复杂度是(1)。

// C++ program to demonstrate functionality of unordered_map 
#include <iostream> 
#include <unordered_map> 
using namespace std; 

int main() 
{ 
	// Declaring umap to be of <string, int> type 
	// key will be of string type and mapped value will 
	// be of double type 
	unordered_map<string, int> umap; 

	// inserting values by using [] operator 
	umap["GeeksforGeeks"] = 10; 
	umap["Practice"] = 20; 
	umap["Contribute"] = 30; 

	// Traversing an unordered map 
	for (auto x : umap) 
	cout << x.first << " " << x.second << endl; 

} 

Output:

Contribute 30
GeeksforGeeks 10
Practice 20

unordered_map vs unordered_set : 
In unordered_set, we have only key, no value, these are mainly used to see presence/absence in a set. For example, consider the problem of counting frequencies of individual words. We can’t use unordered_set (or set) as we can’t store counts.  unordered_set存储key,用来表示是否存在一个set中,例如,计算每个词的频率,不能用unordered_set,因为无法计数。

unordered_map vs map : 
map (like set) is an ordered sequence of unique keys whereas in unordered_map key can be stored in any order, so unordered.
Map is implemented as balanced tree structure that is why it is possible to maintain an order between the elements (by specific tree traversal). Time complexity of map operations is O(Log n) while for unordered_set, it is O(1) on average. map和set一样,是有序的,unordered_map是无序的,map的操作复杂度是 O(Log n),而unordered_set是 O(1)。

Methods on unordered_map
A lot of function are available which work on unordered_map. most useful of them are – operator =, operator [], empty and size for capacity, begin and end for iterator, find and count for lookup, insert and erase for modification.
The C++11 library also provides function to see internally used bucket count, bucket size and also used hash function and various hash policies but they are less useful in real application.
We can iterate over all elements of unordered_map using Iterator. Initialization, indexing and iteration is shown in below sample code :

// C++ program to demonstrate functionality of unordered_map 
#include <iostream> 
#include <unordered_map> 
using namespace std; 

int main() 
{ 
	// Declaring umap to be of <string, double> type 
	// key will be of string type and mapped value will 
	// be of double type 
	unordered_map<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(make_pair("e", 2.718)); 

	string key = "PI"; 

	// If key not found in map iterator to end is returned 
	if (umap.find(key) == umap.end()) 
		cout << key << " not found\n\n"; 

	// If key found then iterator to that key is returned 
	else
		cout << "Found " << key << "\n\n"; 

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

	// iterating over all value of umap 
	unordered_map<string, double>:: iterator itr; 
	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 
		cout << itr->first << " " << itr->second << endl; 
	} 
} 

Output:

Found PI

lambda not found

All Elements : 
loge  1
e  2.718
log10  2.302
root3  1.732
PI  3.14
root2  1.414

A practical problem based on unordered_map – given a string of words, find frequencies of individual words.

Input :  str = "geeks for geeks geeks quiz practice qa for";
Output : Frequencies of individual words are
   (practice, 1)
   (for, 2)
   (qa, 1)
   (quiz, 1)
   (geeks, 3)

Below is a C++ solution using unordered_map.

// C++ program to find freq of every word using 
// unordered_map 
#include <bits/stdc++.h> 
using namespace std; 

// Prints frequencies of individual words in str 
void printFrequencies(const string &str) 
{ 
	// declaring map of <string, int> type, each word 
	// is mapped to its frequency 
	unordered_map<string, int> wordFreq; 

	// breaking input into word using string stream 
	stringstream ss(str); // Used for breaking words 
	string word; // To store individual words 
	while (ss >> word) 
		wordFreq[word]++; 

	// now iterating over word, freq pair and printing 
	// them in <, > format 
	unordered_map<string, int>:: iterator p; 
	for (p = wordFreq.begin(); p != wordFreq.end(); p++) 
		cout << "(" << p->first << ", " << p->second << ")\n"; 
} 

// Driver code 
int main() 
{ 
	string str = "geeks for geeks geeks quiz "
				"practice qa for"; 
	printFrequencies(str); 
	return 0; 
} 

Output:

(qa, 1)
(quiz, 1)
(practice, 1)
(geeks, 3)
(for, 2)

Methods of unordered_map :

  • at(): This function in C++ unordered_map returns the reference to the value with the element as key k.
  • begin(): Returns an iterator pointing to the first element in the container in the unordered_map container
  • end(): Returns an iterator pointing to the position past the last element in the container in the unordered_map container
  • bucket(): Returns the bucket number where the element with the key k is located in the map.
  • bucket_count: bucket_count is used to count the total no. of buckets in the unordered_map. No parameter is required to pass into this function.
  • bucket_size: Returns number of elements in each bucket of the unordered_map.
  • count(): Count the number of elements present in an unordered_map with a given key.
  • equal_range: Return the bounds of a range that includes all the elements in the container with a key that compares equal to k.

unordered_map at() in C++

Prerequisite : Unordered maps in STL

Unordered_map : unordered_map is an associated container that stores elements formed by the 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.

unordered_map :: at(): This function in C++ unordered_map returns the reference to the value with the element as key k.
Syntax:

unordered_map.at(k);
Parameter:
It is the key value of the element whose mapped value we want to access.
Return type :
A reference to the mapped value of the element with a key value equivalent

Note : The method gives run-time error if key is not present.

// C++ program to illustrate 
// std :: unordered_map :: at() 
#include<iostream> 
#include<string> 
#include<unordered_map> 

using namespace std; 

int main() 
{ 
	unordered_map<string,int> mp = { 
							{"first",1}, 
							{"second",2}, 
							{"third",3}, 
							{"fourth",4} 
	}; 
									
	// returns the reference i.e. the mapped 
	// value with the key 'second' 
	cout<<"Value of key mp['second'] = "
		<<mp.at("second")<<endl; 
	
	try
	{ 
		mp.at(); 
	} 

	catch(const out_of_range &e) 
	{ 
		cerr << "Exception at " << e.what() << endl; 
	} 
	
	
	return 0; 
} 

Output:

Value of key mp['second'] = 2
Exception at _Map_base::at

Practical Application : std :: unordered_map :: at() function can be used to access the mapped value and thus can edit, update etc.

// CPP program to illistrate 
// application of this function 
// Program to correct the marks 
// given in different subjects 
#include<iostream> 
#include<string> 
#include<unordered_map> 

using namespace std; 

// driver code 
int main() 
{ 
	// marks in different subjects 
	unordered_map<string,int> my_marks = { 
					{"Maths", 90}, 
					{"Physics", 87}, 
					{"Chemistry", 98}, 
					{"Computer Application", 94} 
					}; 
		
									
		my_marks.at("Physics") = 97; 
		my_marks.at("Maths") += 10; 
		my_marks.at("Computer Application") += 6; 
		
		for (auto& i: my_marks) 
		{ 
			cout<<i.first<<": "<<i.second<<endl; 
		} 
	
	
	
	return 0; 
} 

Output:

Computer Application: 100
Chemistry: 98
Physics: 97
Maths: 100

How unordered_map at() is different from unordered_map operator()

  • Both at() and operator[] is used to refer the element present at the given position, the only difference is, at() throws out-of-range exception whereas operator[] shows undefined behavior.

unordered_map begin() in C++

The unordered_map::begin() is a built-in function in C++ STL which returns an iterator pointing to the first element in the unordered_map container or in any of its bucket.

  1. Syntax for first element in unordered_map container:
    unordered_map.begin()
    

    Parameters: This function does not accepts any parameters.

    Return Value: The function returns an iterator pointing to the first element in the unordered_map container.

    Note: In an unordered map, there is no specific element which is considered as the first element.

    Below program illustrate the above function.

// CPP program to demonstrate the 
// unordered_map::begin() function 
// when first element of the container 
// is to be returned as iterator 
#include <bits/stdc++.h> 
using namespace std; 

int main() 
{ 

	// Declaration 
	unordered_map<std::string, std::string> mymap; 

	// Initilisation 
	mymap = { { "Australia", "Canberra" }, 
			{ "U.S.", "Washington" }, 
			{ "France", "Paris" } }; 

	// Iterator pointing to the first element 
	// in the unordered map 
	auto it = mymap.begin(); 

	// Prints the elements of the first element in map 
	cout << it->first << " " << it->second; 

	return 0; 
} 

Output:

France Paris
  1. Syntax for first element in unordered_map bucket:
    unordered_map.begin( n )
    

    Parameters: The function accepts one mandatory parameter n which specifies the bucket number whose first element’s iterator is to be returned.

    Return Value: The function returns an iterator pointing to the first element in the n-th bucket.

    Below program illustrate the above function.

// CPP program to demonstrate the 
// unordered_map::begin() function 
// when first element of n-th container 
// is to be returned as iterator 
#include <bits/stdc++.h> 
using namespace std; 

int main() 
{ 

	// Declaration 
	unordered_map<std::string, std::string> mymap; 

	// Initilisation 
	mymap = { { "Australia", "Canberra" }, 
			{ "U.S.", "Washington" }, { "France", "Paris" } }; 

	// Iterator pointing to the first element 
	// in the n-th bucket 
	auto it = mymap.begin(0); 

	// Prints the elements of the n-th bucket 
	cout << it->first << " " << it->second; 

	return 0; 
} 

Output:

U.S. Washington

unordered_map end( ) function in C++ STL

The unordered_map::end() is a built-in function in C++ STL which returns an iterator pointing to the position past the last element in the container in the unordered_map container. In an unordered_map object, there is no guarantee that which specific element is considered its first element. But all the elements in the container are covered since the range goes from its begin to its end until invalidated.

Syntax:

iterator unordered_map_name.end(n)

Parameters : This function accepts one parameter n which is an optional parameter that specifies the bucket number. If it is set, the iterator retrieves points to the past-the-end element of a bucket, otherwise, it points to the past-the-end element of the container.

Return value: The function returns an iterator to the element past the end of the container.

Below programs illustrates the above-mentioned function:

Program 1:

// CPP program to demonstrate the 
// unordered_map::end() function 
// returning all the elements of the multimap 
#include <iostream> 
#include <string> 
#include <unordered_map> 
using namespace std; 

int main() 
{ 
	unordered_map<string, int> marks; 

	// Declaring the elements of the multimap 
	marks = { { "Rohit", 64 }, { "Aman", 37 }, { "Ayush", 96 } }; 

	// Printing all the elements of the multimap 
	cout << "marks bucket contains : " << endl; 
	for (int i = 0; i < marks.bucket_count(); ++i) { 

		cout << "bucket #" << i << " contains:"; 

		for (auto iter = marks.begin(i); iter != marks.end(i); ++iter) { 
			cout << "(" << iter->first << ", " << iter->second << "), "; 
		} 

		cout << endl; 
	} 
	return 0; 
} 

Output:

marks bucket contains : 
bucket #0 contains:
bucket #1 contains:
bucket #2 contains:
bucket #3 contains:(Aman, 37), (Rohit, 64), 
bucket #4 contains:(Ayush, 96),

Program 2:

// CPP program to demonstrate the 
// unordered_map::end() function 
// returning the elements along 
// with their bucket number 
#include <iostream> 
#include <string> 
#include <unordered_map> 

using namespace std; 

int main() 
{ 
	unordered_map<string, int> marks; 

	// Declaring the elements of the multimap 
	marks = { { "Rohit", 64 }, { "Aman", 37 }, { "Ayush", 96 } }; 

	// Printing all the elements of the multimap 
	for (auto iter = marks.begin(); iter != marks.end(); ++iter) { 

		cout << "Marks of " << iter->first << " is "
			<< iter->second << " and his bucket number is "
			<< marks.bucket(iter->first) << endl; 
	} 

	return 0; 
} 

Output:

Marks of Ayush is 96 and his bucket number is 4
Marks of Aman is 37 and his bucket number is 3
Marks of Rohit is 64 and his bucket number is 3

map vs unordered_map in C++

Pre-requisite : std::mapstd::unordered_map

When it comes to efficiency, there is a huge difference between maps and unordered maps.
We must know the internal working of both to decide which one is to be used.

Difference :

                  | map             | unordered_map
---------------------------------------------------------
Ordering        | increasing  order   | no ordering
                | (by default)        |

Implementation  | Self balancing BST  | Hash Table
                | like Red-Black Tree |  

search time     | log(n)              | O(1) -> Average 
                |                     | O(n) -> Worst Case

Insertion time  | log(n) + Rebalance  | Same as search
                      
Deletion time   | log(n) + Rebalance  | Same as search

Use std::map when  使用map时的条件

  • You need ordered data.   需要有序的数据
  • You would have to print/access the data (in sorted order).  处理有序的数据
  • You need predecessor/successor of elements.  需要元素的前驱后继
  • See advantages of BST over Hash Table for more cases.
// CPP program to demonstrate use of std::map 
#include <bits/stdc++.h> 

int main() 
{ 
	// Ordered map 
	std::map<int, int> order; 

	// Mapping values to keys 
	order[5] = 10; 
	order[3] = 5; 
	order[20] = 100; 
	order[1] = 1; 

	// Iterating the map and printing ordered values 
	for (auto i = order.begin(); i != order.end(); i++) { 
		std::cout << i->first << " : " << i->second << '\n'; 
	} 
} 

Output :

1 : 1
3 : 5
5 : 10
20 : 100

Use std::unordered_map when 使用unordered_map

  • You need to keep count of some data (Example – strings) and no ordering is required. 需要对数据进行计数,不需要顺序
  • You need single element access i.e. no traversal.  需要访问一个元素,而不是遍历
// CPP program to demonstrate use of 
// std::unordered_map 
#include <bits/stdc++.h> 

int main() 
{ 
	// Unordered map 
	std::unordered_map<int, int> order; 

	// Mapping values to keys 
	order[5] = 10; 
	order[3] = 5; 
	order[20] = 100; 
	order[1] = 1; 

	// Iterating the map and printing unordered values 
	for (auto i = order.begin(); i != order.end(); i++) { 
		std::cout << i->first << " : " << i->second << '\n'; 
	} 
} 

Output :

1 : 1
3 : 5
20 : 100
5 : 10

猜你喜欢

转载自blog.csdn.net/qq_27009517/article/details/86622704