hash/unordered_map

1.hash
functional 头文件中定义了 hash 模板,可以从 K 类型的对象生成哈希值的函数对象的类型。接受 K 类型的单个参数,然后返回 size_t 类型的哈希值,对于相等的键必须产生相等的哈希值,对于不相等的键产生碰撞的可能性必须最小接近 size_t 最大值的倒数

std::hash<int> hash_int;// Function object to hash int
std::vector<int> {-5, -2, 2, 5, 10};
std::transform(std::begin(n), std::end(n),std::ostream_iterator<size_t> (std:: cout," "),hash_int);
std::hash<Box*> hash_box; // Box class as in Chapter 2
auto upbox = std::make_unique<Box>(1A 2, 3);
hash_box(upbox.get()) // Hash value = 1143026886

2.unordered_map
unordered_map元素的位置由键的哈希值确定。
在这里插入图片描述
unordered_map 必须能够比较元素是否相等。容器默认会使用定义在 fimctional 头文件中的equal_to 模板。它会用 == 运算符来比较元素,这一点和 map 容器不同,map 容器使用的是等价。如果使用的键是没有实现 operator==() 的类类型,那就必须提供一个函数对象来比较键。

(1)初始化
需要支持用 hash 的实例哈希 k 类型的键,而且必须能够用 == 运算符来比较键
<1> 初始化列表

std::unordered_map<std::string, size_t> people {{"Jan",44}, {"Jim", 33}, {"Joe", 99}}; // Name,age

格子的个数是默认的,它使用 equal_to() 对象来判断键是否相等。它会用定义在 string 头文件中的 hash 来对 string 进行哈希

<2>指定格子数

std::unordered_map<std::string,size_t> people {{ { "Jan", 44}, {"Jim", 33}, {"Joe", 99}}, 10};

<3> 用迭代器定义的一段 pair 对象来生成容器

std::vector<std::pair<string, size_t>>folks {{ "Jan",44}, {"Jim", 33}, {"Joe", 99},{"Dan", 22},{"Ann", 55}, {"Don", 77}};
std::unordered_map<string, size_t> neighbors {std::begin(folks), std::end(folks) , 500};

<4> 自定义类型作为键值
必须为这个类定义一个哈希函数和一个恒等运算符

//定义键类型
class Name
{
public:
    size_t hash() const { return std::hash<std::string>()(first+second); }//用函数对象 hash<string>() 来哈希 Name 对象的成员 first 和 second 所拼接的字符串
    bool operator==(const Name& name) const { return first == name.first && second== name.second; }
};
定义hash函数对象
class Hash_Name {
public:
    size_t operator()(const Name& name) const { return name.hash(); }
};
Hash_Name作为模板参数,且Hash_Name()作为构造函数参数
std::unordered_map<Name, size_t, Hash_Name> people
{{{{"Ann", "Ounce"}, 25}, {{"Bill", "Bao"}, 46}, {{"Jack", "Sprat"}, 77}},500,Hash_Name()}

更加详细的:
https://blog.csdn.net/y109y/article/details/82669620
1.函数作为参数模板,构造函数加上函数参数
2.重载operate()定义函数对象,作为模板参数,构造函数不加函数参数

如果忽略了 Name 类的成员函数 operator==(),可以定义一个函数对象的类类型 Name_Equal,在构造函数中指定它:

std::unordered_map<Name, size_t, Hash_Name, Name_Equal〉 people
{ { { {"Ann", "Ounce"}, 25}, {{"Bill”, "Bao"}, 46},{{"Jack","Sprat"}, 77}},500,Hash_Name(), Name_Equal()};

<5> unordered_map 也有移动和拷贝构造函数。可以用它们生成容器的副本,副本容器的格子个数、哈希函数都和参数容器相同。

(2)插入元素 insert/emplace
<1> 插入一个元素

auto pr = people.insert (std::pair<string, size_t> {"Jan", 44});// Move insert

first 是一个迭代器,它指向插入的新元素;如果元素没有被插入,它指向的是阻止插入的元素。Pair 的成员变量 second 是一个布尔值,如果对象插入成功,它的值为 true。

<2> 指定位置插入

auto iter = people.insert(pr.first,person);

返回一个指向插入元素或阻止插入操作的元素的迭代器。使用容器的成员函数 size() 返回的元素个数来判断元素是否插入成功。

<3> 插入初始化列表中的内容,无返回值

people.insert({{"Bill", 21}, {"Ben", 22}});

<4> 插入迭代器范围值

folks.insert(std::begin(people), std::end(people));// Insert copies of'all people elements

<5> emplace()
emplace_hint() 在容器的适当位置生成元素
<6> unordered_map 容器实现了赋值运算符

folks = people //folks和people分别是两个unordered_map

(3)调整格子数
将元素重新分配到新的格子中,元素会被再次哈希。容器当前存在的任何迭代器都会失效
rehash() ——改变格子的个数

people.rehash(15); // Make bucket count 15

容器中的所有元素都会被重新哈希分配到新的格子中,而且当前所有的迭代器都会失效

bucket_count()——返回容器当前格子数
max_load_factor——最大装载因子

people.max_load_factor(1.2*people.max_load_factor()); // 工ncrease max load factor by 20%,无参数地调用这个函数,它会返回当前的最大载入因子

load_factor() ——返回当前载入因子

reserve——设置容纳元素个数

(4)获取元素
与map类似,有[]和at()
访问格子

auto iter = people.begin(1); // Returns an iterator for the 2nd bucket
for(auto iter = people.begin(index); iter != people.end(index); ++iter) //访问索引为Index格子的所有元素

bucket_count() ——返回的格子个数
bucket_size() ——返回参数指定的格子中的元素个数,参数为索引值
bucket() ——返回的是格子的索引值,参数为键

people.bucket_size(people.bucket(key))

(5)删除元素
erase(),与map类似,可以移除指定键的,也可以移除一个迭代器范围的
clear(),移除所有元素

3.unordered_multimap
find() ——返回它所找到的第一个元素的迭代器,如果找不到这个键,会返回一个结束迭代器
count()——键为参数,发现容器中给定键的元素个数
equal_range() ——参数为键,与map类似
当容器中只有一个 key 时,可以用 find() 来访问这个元素。如果超过一个,可以用 equal_range() 来访问这段元素

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值