在上一篇文章中我们讨论了unordered_set的问题,unordered_set的问题在于,不可能在该数据结构中存储重复的条目。例如,如果我们在unordered_set中已经有一些值v,那么再次插入v将无效。
要处理此重复,应使用unordered_mulitset,它也可以存储重复的元素。在内部,当插入现有值时,数据结构将增加其计数,该计数与每个值相关。由于每个值的计数都存储在unordered_multiset中,因此比unordered_set占用更多的空间(如果所有值都是不同的)。
unordered_multiset的内部实现与unordered_set的内部实现相同,并且还使用哈希表进行搜索,只是计数值与前一个值相关联。由于元素的散列,它没有存储元素的特定顺序,因此所有元素可以任何顺序出现,但重复元素在一起。 unordered_multiset上的所有操作平均需要花费固定时间,但在最坏的情况下可以线性化。
Unordered_multiset支持许多功能,这些函数在下面的代码中演示:
// C++ program to demonstrate various function
// of unordered_multiset
#include
using namespace std;
// making typedef for short declaration
typedef unordered_multiset::iterator umit;
// Utility function to print unordered_multiset
void printUset(unordered_multiset ums)
{
// begin() returns iterator to first element of set
umit it = ums.begin();
for (; it != ums.end(); it++)
cout << *it << " ";
cout << endl;
}
// Driver program to check all function
int main()
{
// empty initialization
unordered_multiset ums1;
// Initialization by intializer list
unordered_multiset ums2 ({1, 3, 1, 7, 2, 3,
4, 1, 6});
// Initialization by assignment
ums1 = {2, 7, 2, 5, 0, 3, 7, 5};
// empty() function return true if set is empty
// otherwise false
if (ums1.empty())
cout << "unordered multiset 1 is empty\n";
else
cout << "unordered multiset 1 is not empty\n";
// size() function returns total number of elements
// in data structure
cout << "The size of unordered multiset 2 is : "
<< ums2.size() << endl;
printUset(ums1);
ums1.insert(7);
printUset(ums1);
int val = 3;
// find function returns iterator to first position
// of val, if exist otherwise it returns iterator
// to end
if (ums1.find(val) != ums1.end())
cout << "unordered multiset 1 contains "
<< val << endl;
else
cout << "unordered multiset 1 does not contains "
<< val << endl;
// count function returns total number of occurrence in set
val = 5;
int cnt = ums1.count(val);
cout << val << " appears " << cnt
<< " times in unordered multiset 1 \n";
val = 9;
// if count return >0 value then element exist otherwise not
if (ums1.count(val))
cout << "unordered multiset 1 contains "
<< val << endl;
else
cout << "unordered multiset 1 does not contains "
<< val << endl;
val = 1;
// equal_range returns a pair, where first is iterator
// to first position of val and second it iterator to
// last position to val
pair erange_it = ums2.equal_range(val);
if (erange_it.first != erange_it.second)
cout << val << " appeared atleast once in "
"unoredered_multiset \n";
printUset(ums2);
// erase function deletes all instances of val
ums2.erase(val);
printUset(ums2);
// clear function deletes all entries from set
ums1.clear();
ums2.clear();
if (ums1.empty())
cout << "unordered multiset 1 is empty\n";
else
cout << "unordered multiset 1 is not empty\n";
}
输出 :
unordered multiset 1 is not empty
The size of unordered multiset 2 is : 9
3 0 5 5 7 7 2 2
3 0 5 5 7 7 7 2 2
unordered multiset 1 contains 3
5 appears 2 times in unordered multiset 1
unordered multiset 1 does not contains 9
1 appeared atleast once in unoredered_multiset
6 4 2 7 3 3 1 1 1
6 4 2 7 3 3
unordered multiset 1 is empty
如我们所见,大多数操作工作都类似于unordered_set,但需要注意的一些事情是:
equal_range(val)函数返回一对数据类型,其中第一个迭代器指向val的第一个位置,第二个迭代器指向val的最后一个位置。
例如,如果某个值v已在unordered_multiset中出现t次,并且调用了擦除操作,则v将被完全删除,这通常不是预期的行为,因此delete(val)函数将从数据结构中删除其所有实例。
通过使用find函数和擦除的迭代器版本,我们只能删除某个值的一个副本,因为find函数将迭代器返回到找到值的第一个位置,我们可以传递此迭代器来擦除而不是实际值,从而仅删除一个副本,如下所示:
// C++ program to delete one copy from unordered set
#include
using namespace std;
// making typedef for short declaration
typedef unordered_multiset::iterator umit;
// Utility function to print unordered_multiset
void printUset(unordered_multiset ums)
{
// begin() returns iterator to first element of
// set
umit it = ums.begin();
for (; it != ums.end(); it++)
cout << *it << " ";
cout << endl;
}
// function to delete one copy of val from set
void erase_one_entry(unordered_multiset& ums,
int val)
{
// find returns iterator to first position
umit it = ums.find(val);
// if element is there then erasing that
if (it != ums.end())
ums.erase(it);
}
// Driver program to check above function
int main()
{
// initializing multiset by initializer list
unordered_multiset ums ({1, 3, 1, 7, 2, 3,
4, 1, 6});
int val = 1;
printUset(ums);
erase_one_entry(ums, val);
printUset(ums);
}
输出 :
6 4 2 7 3 3 1 1 1
6 4 2 7 3 3 1 1
unordered_multiset的方法:
- insert()–在unordered_multiset中插入新元素。因此增加了容器的尺寸。
- begin()–返回一个迭代器,该迭代器指向容器中的第一个元素或其存储桶中的第一个元素。
- end()–返回一个迭代器,该迭代器指向容器中最后一个元素之后的位置,或者指向其存储桶中最后一个元素之后的位置。
- empty()–如果unordered_multiset容器为空,则返回true。否则,它返回false。
- find()–返回一个迭代器,该迭代器指向具有元素val的位置。
- cbegin()–返回一个常量迭代器,该迭代器指向容器中的第一个元素或其存储桶中的第一个元素。
- cend()–返回一个常量迭代器,该常量迭代器指向容器中最后一个元素之后的位置,或者指向其存储桶中最后一个元素之后的位置。
- equal_range()–返回所有元素均等于给定值的范围。
- emplace()–在unordered_multiset容器中插入一个新元素。
- clear()–清除unordered_multiset容器的内容。
- count()–返回unordered_multiset容器中等于给定值的元素计数。
- size()– unordered_multiset的size()方法用于计算调用它的unordered_set的元素数。
- max_size – unordered_multiset的max_size()获取unordered_multiset容器能够容纳的最大元素数。
- swap()–交换两个unordered_multiset容器的内容。
- 擦除()–用于删除单个元素或具有确定值的所有元素,或从开始(包括)到结束(不包括)的一系列元素。
- bucket()–返回给定元素所在的存储桶编号。值区大小从0到bucket_count-1不等。
- bucket_size()–返回存储桶中具有元素val的元素数。
- reserve()– unordered_multiset的reverse()函数将容器中的存储桶数(bucket_count)设置为最适合包含至少n个元素的存储桶。
- max_bucket_count()–返回无序多集容器可以具有的最大存储桶数。
- load_factor()–返回unordered_multiset容器中的当前负载系数。
- max_load_factor()–返回unordered_multiset容器的最大加载因子。
- bucket_count()–返回unordered_multiset容器中的存储桶总数。
- hash_function()–此哈希函数是一元函数,仅接受单个参数,并基于该参数返回一个唯一的大小为size_t的值。
- rehash()–将容器中的存储桶数设置为N或更多。
- key_eq()–根据比较结果返回布尔值。
- emplace_hint()–在unordered_multiset容器中插入一个新元素。
- get_allocator –此函数获取存储的分配器对象并返回用于构造容器的分配器对象。
- 运算符= –’=’是C++ STL中的运算符,它将unordered_multiset复制(或移动)到另一个unordered_multiset和unordered_multiset :: 运算符=是相应的运算符函数。