C++常用的无序关联容器unordered_map
是C++11正式加入的对hash_map的官方实现(之前标准C++没有hash_map的官方实现,也就是说我们使用的STL的hash_map并不是官方的)。从名字可以看出这个结构是无序的,底层设计思想和STL的hash_map一样。元素在内部不以任何特定顺序排序,而是放进桶中。元素放进哪个桶完全依赖于其键的哈希。这允许对单独元素的快速访问,因为一旦计算哈希,则它准确指代元素所放进的桶。unordered_map搜索、插入和元素移除拥有平均常数时间复杂度。
所在头文件为
,类模板为:
template < class Key, // unordered_map::key_type
class T, // unordered_map::mapped_type
class Hash = hash<Key>, // unordered_map::hasher
class Pred = equal_to<Key>, // unordered_map::key_equal
class Alloc = allocator< pair<const Key,T> > //unordered_map::allocator_type
> class unordered_map;
key_type
:第一个模板参数(Key)mapped_type
:第二个模板参数(T)value_type
:pairhasher
:第三个模板参数(Hash)key_equal
:第四个模板参数(Pred)特性:
示例:
// constructing unordered_maps
#include
#include
#include
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 main()
{
stringmap first; // empty
// 一个元素为:{key, value}
stringmap second({ {"apple","red"}, {"lemon","yellow"} }); // init list
stringmap third({ {"orange","orange"}, {"strawberry","red"} }); // init list
stringmap fourth(second); // copy
stringmap fifth(merge(third, fourth)); // move
stringmap sixth(fifth.begin(), fifth.end()); // range
std::cout << "sixth contains:" << std::endl;
for (auto& x : sixth)
{
std::cout << x.first << ":" << x.second << std::endl;
}
std::cout << std::endl;
return 0;
}
输出结果:
sixth contains:
orange:orange
strawberry:red
apple:red
lemon:yellow
复制: unordered_map& operator= ( const unordered_map& ump );
移动: unordered_map& operator= ( unordered_map&& ump );
初始化列表: unordered_map& operator= ( intitializer_list<value_type> il );
示例:
// assignment operator with unordered_map
#include
#include
#include
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 main()
{
//stringmap first, second, third;//此处连续定义三个会报错。
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:" << std::endl;
for (auto& elem : first)
{
std::cout << elem.first << ":" << elem.second << std::endl;
}
std::cout << std::endl;
return 0;
}
输出结果:
first contains:
AAPL:Apple
MSFT:Microsoft
ORCL:Oracle
GOOG:Google
即,“第一个”指整个容器中的第一个,“尾后”指整个容器中的尾后。
iterator begin() noexcept; //返回一个迭代器,指向第一个元素
const_iterator begin() const noexcept; //返回一个迭代器,指向第一个元素
iterator end() noexcept; //返回一个迭代器,指向尾后元素
const_iterator end() const noexcept; //返回一个迭代器,指向尾后元素
const_iterator cbegin() const noexcept; //返回一个常量迭代器,指向第一个元素
const_iterator cend() const noexcept; //返回一个常量迭代器,指向尾后元素
即,“第一个”指某个桶中的第一个,“尾后”指某个桶中的尾后。
local_iterator begin( size_type n ); //返回一个迭代器,指向第n个桶内的第一个元素
const_local_iterator begin ( size_type n ) const;//返回一个迭代器,指向第n个桶内的第一个元素
local_iterator end(size_type n); //返回一个迭代器,指向第n个桶内的尾后元素
const_local_iterator end (size_type n) const; //返回一个迭代器,指向第n个桶内的尾后元素
const_local_iterator cbegin( size_type n ) const;//返回一个常量迭代器,指向第n个桶内的第一个元素
const_local_iterator cend( size_type n ) const; //返回一个常量迭代器,指向第n个桶内的尾后元素
示例:
// unordered_map::cbegin/cend example
#include
#include
#include
int main()
{
std::unordered_map<std::string, std::string> mymap = { { "Australia", "Canberra" }, { "U.S.", "Washington" }, { "France", "Paris" } };
std::cout << "mymap contains:" << std::endl;
for (auto it = mymap.cbegin(); it != mymap.cend(); ++it)
std::cout << it->first << ":" << it->second << std::endl; // cannot modify *it
std::cout << std::endl;
std::cout << "mymap's buckets contain:\n";
for (unsigned i = 0; i < mymap.bucket_count(); ++i)
{
std::cout << "bucket #" << i << " contains:";
for (auto local_it = mymap.cbegin(i); local_it != mymap.cend(i); ++local_it)
std::cout << local_it->first << ":" << local_it->second;
std::cout << std::endl;
}
return 0;
}
输出结果:
mymap contains:
Australia:Canberra
U.S.:Washington
France:Paris
mymap's buckets contain:
bucket #0 contains:
bucket #1 contains:Australia:Canberra
bucket #2 contains:France:Paris
bucket #3 contains:
bucket #4 contains:
bucket #5 contains:
bucket #6 contains:
bucket #7 contains:U.S.:Washington
bool empty() const noexcept; //unordered_map 是否为空
size_type size() const noexcept; //获取unordered_map 中元素的数量
mapped_type& operator[] (const key_type& k); //如果 k 匹配容器中某个元素的键,则该函数返回该映射值的引用。
mapped_type& operator[] (key_type&& k); //如果 k 与容器中任何元素的键都不匹配,则该函数将使用该键 插入 一个新元素,并返回该映射值的引用。
mapped_type& at (const key_type& k); //如果 k 匹配容器中某个元素的键,则该函数返回该映射值的引用。
const mapped_type& at (const key_type& k) const; //如果 k 与容器中任何元素的键都不匹配,则该函数将抛出 out_of_range 异常。
注意:const std::unordered_map 不能使用 operator[]
操作!!
示例:
// unordered_map::at
#include
#include
#include
int main()
{
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;
}
return 0;
}
输出结果:
Mars: 3396
Jupiter: 69910
Saturn: 60272
// unordered_map::insert
#include
#include
#include
int main()
{
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;
return 0;
}
输出结果:
myrecipe contains:
baking powder: 0.3
flour: 1.5
eggs: 6
milk: 2
sugar: 0.8
salt: 0.1
iterator erase (const_iterator position); //返回一个迭代器,指向被删除元素的后一个元素
size_type erase (const key_type& k); //返回被删除元素的数目,此处为1
iterator erase (const_iterator first, const_iterator last); //返回一个迭代器,指向最后一个被删除元素的后一个元素
void clear() noexcept;
示例:
// unordered_map::erase
#include
#include
#include
int main() {
std::unordered_map<std::string, std::string> mymap;
// populating container:
mymap["U.S."] = "Washington";
mymap["U.K."] = "London";
mymap["France"] = "Paris";
mymap["Russia"] = "Moscow";
mymap["China"] = "Beijing";
mymap["Germany"] = "Berlin";
mymap["Japan"] = "Tokyo";
// erase examples:
mymap.erase(mymap.begin()); // erasing by iterator
mymap.erase("France"); // erasing by key
mymap.erase(mymap.find("China"), mymap.end()); // erasing by range
// show content:
for (auto& x : mymap)
{
std::cout << x.first << ": " << x.second << std::endl;
}
return 0;
}
输出结果:
U.S.: Washington
Russia: Moscow
iterator find (const key_type& k);
const_iterator find (const key_type& k) const;
//说明:在容器中搜索键值等于 k 的元素,如果找到,则返回一个指向该元素的迭代器,否则返回一个指向unordered_map :: end的迭代器。
示例:
// unordered_map::find
#include
#include
#include
int main() {
std::unordered_map<std::string, double> mymap = {
{"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 = mymap.find(input);
if (got == mymap.end())
std::cout << "not found";
else
std::cout << got->first << " is " << got->second;
std::cout << std::endl;
return 0;
}
输出结果:
who? mom
mom is 5.4
size_type bucket_count() const noexcept; //获取容器中桶的数目
size_type bucket_size ( size_type n ) const; //获取第 n 个桶中元素的数量
size_type bucket ( const key_type& k ) const; //获取键为 k 的元素所在桶的序号