📜  unordered_multimap及其应用

📅  最后修改于: 2021-05-25 18:26:54             🧑  作者: Mango

允许重复:
我们在上一篇文章中讨论过unordered_map,但是有一个限制,我们不能在unordered_map中存储重复项,也就是说,如果我们在unordered_multimap中已经有一个键值对,并且已经插入了另一个键值对,那么两者都将存在,而在在unordered_map的情况下,对应于该键的先前值由仅会存在的新值更新。甚至可以在unordered_multimap中存在两次。

内部代表:
unordered_multimap的内部实现与unordered_map的内部实现相同,但是对于重复键,每个键值对都维护另一个计数值。由于对存储在哈希表中,因此它们之间没有特定的顺序,但是具有相同键的对在数据结构中会聚在一起,而具有相同值的对不能保证会聚在一起。

时间复杂度:
unordered_multimap上的所有操作平均需要花费恒定的时间,但在最坏的情况下,时间可能变为线性,具体取决于内部使用的哈希函数,但从长远来看,unordered_multimap的性能要优于multimap(基于树的multimap)。

职能:
unordered_multimap支持许多功能,这些功能在下面的代码中演示:

CPP
// C++ program to demonstrate various function of
// unordered_multimap
#include 
using namespace std;
 
// making typedef for short declaration
typedef unordered_multimap::iterator umit;
 
// Utility function to print unordered_multimap
void printUmm(unordered_multimap umm)
{
    // begin() returns iterator to first element of map
    umit it = umm.begin();
 
    for (; it != umm.end(); it++)
        cout << "<" << it->first << ", " << it->second
             << ">  ";
 
    cout << endl;
}
 
// Driver code
int main()
{
    // empty initialization
    unordered_multimap umm1;
 
    // Initialization bu intializer list
    unordered_multimap umm2(
        { { "apple", 1 },
          { "ball", 2 },
          { "apple", 10 },
          { "cat", 7 },
          { "dog", 9 },
          { "cat", 6 },
          { "apple", 1 } });
 
    // Initialization by assignment operation
    umm1 = umm2;
    printUmm(umm1);
 
    // empty returns true, if container is empty else it
    // returns false
    if (umm2.empty())
        cout << "unordered multimap 2 is empty\n";
    else
        cout << "unordered multimap 2 is not empty\n";
 
    // size returns total number of elements in container
    cout << "Size of unordered multimap 1 is "
         << umm1.size() << endl;
 
    string key = "apple";
 
    // find and return any pair, associated with key
    umit it = umm1.find(key);
    if (it != umm1.end()) {
        cout << "\nkey " << key << " is there in unordered "
             << " multimap 1\n";
        cout << "\none of the value associated with " << key
             << " is " << it->second << endl;
    }
    else
        cout << "\nkey " << key
             << " is not there in unordered"
             << " multimap 1\n";
 
    // count returns count of total number of pair
    // associated with key
    int cnt = umm1.count(key);
    cout << "\ntotal values associated with " << key
         << " are " << cnt << "\n\n";
 
    printUmm(umm2);
 
    // one insertion by makeing pair explicitly
    umm2.insert(make_pair("dog", 11));
 
    // insertion by initializer list
    umm2.insert({ { "alpha", 12 }, { "beta", 33 } });
    cout << "\nAfter insertion of  and \n";
    printUmm(umm2);
 
    // erase deletes all pairs corresponding to key
    umm2.erase("apple");
    cout << "\nAfter deletion of apple\n";
    printUmm(umm2);
 
    // clear deletes all pairs from container
    umm1.clear();
    umm2.clear();
 
    if (umm2.empty())
        cout << "\nunordered multimap 2 is empty\n";
    else
        cout << "\nunordered multimap 2 is not empty\n";
}


C++
// C++ program to implement find and erase for specific
// key-value pair for unordered_multimap
#include 
using namespace std;
 
// making typedef for short declaration
typedef unordered_multimap::iterator umit;
 
// function to check whether p is there in map or not
bool find_kv(unordered_multimap& umm,
             pair p)
{
    // equal_range returns pair of iterator of first and
    // last position associated with key
    pair it = umm.equal_range(p.first);
    umit it1 = it.first;
 
    pair tmp;
 
    // looping over all values associated with key
    while (it1 != it.second)
    {
        tmp = *it1;
        if (tmp == p)
            return true;
        it1++;
    }
    return false;
}
 
// function to delete one copy of pair p from map umm
void erase_kv(unordered_multimap& umm,
              pair p)
{
    // equal_range returns pair of iterator of first and
    // last position associated with key
    pair it = umm.equal_range(p.first);
    umit it1 = it.first;
    pair tmp;
 
    // looping over all values associated with key
    while (it1 != it.second)
    {
        tmp = *it1;
        if (tmp == p)
        {
            // iterator version of erase : deletes pair
            // at that position only
            umm.erase(it1);
            break;
        }
        it1++;
    }
}
 
// Utility function to print unordered_multimap
void printUmm(unordered_multimap umm)
{
    // begin() returns iterator to first element of map
    umit it = umm.begin();
    for (; it != umm.end(); it++)
        cout << "<" << it->first << ", " << it->second
             << "> ";
    cout << endl;
}
 
// Driver code
int main()
{
    // initializing multimap by initializer list
    unordered_multimap umm({ { "apple", 1 },
                                          { "ball", 2 },
                                          { "apple", 10 },
                                          { "cat", 7 },
                                          { "dog", 9 },
                                          { "cat", 6 },
                                          { "apple", 1 } });
 
    cout << "Initial content\n";
    printUmm(umm);
    pair kv = make_pair("apple", 1);
 
    // inserting one more  pair
    umm.insert({ "apple", 1 });
    cout << "\nAfter insertion of one more \n";
    printUmm(umm);
 
    if (find_kv(umm, kv))
        erase_kv(umm, kv);
    else
        cout << "key-value pair is not there in unordered "
                "multimap\n";
 
    cout << "\nAfter deletion one occurrence of \n";
    printUmm(umm);
}


输出
              
unordered multimap 2 is not empty
Size of unordered multimap 1 is 7

key apple is there in unordered  multimap 1

one of the value associated with apple is 1

total values associated with apple are 3

              

After insertion of  and 
                    

After deletion of apple
              

unordered multimap 2 is empty

正如我们在上面的代码中看到的那样,大多数操作的工作方式与unordered_map类似,但需要注意一些事项:
我们可以使用初始化列表来一次初始化和插入许多对。
unordered_multimap没有[]运算符,因为与键相对应的值不是唯一的,并且与一个键关联的值可能很多,因此[]运算符不能应用于它们。
擦除函数删除与提供的键关联的值的所有实例。
Find函数将迭代器返回到与该键关联的所有对中的键-值对的任何实例。

如何访问/删除密钥的特定值?
如果要检查是否存在特定项,则需要遍历与k对应的所有键值对,以类似的方式可以从数据结构中擦除特定项的一个副本。没有指定键的所有值的存储顺序。

C++

// C++ program to implement find and erase for specific
// key-value pair for unordered_multimap
#include 
using namespace std;
 
// making typedef for short declaration
typedef unordered_multimap::iterator umit;
 
// function to check whether p is there in map or not
bool find_kv(unordered_multimap& umm,
             pair p)
{
    // equal_range returns pair of iterator of first and
    // last position associated with key
    pair it = umm.equal_range(p.first);
    umit it1 = it.first;
 
    pair tmp;
 
    // looping over all values associated with key
    while (it1 != it.second)
    {
        tmp = *it1;
        if (tmp == p)
            return true;
        it1++;
    }
    return false;
}
 
// function to delete one copy of pair p from map umm
void erase_kv(unordered_multimap& umm,
              pair p)
{
    // equal_range returns pair of iterator of first and
    // last position associated with key
    pair it = umm.equal_range(p.first);
    umit it1 = it.first;
    pair tmp;
 
    // looping over all values associated with key
    while (it1 != it.second)
    {
        tmp = *it1;
        if (tmp == p)
        {
            // iterator version of erase : deletes pair
            // at that position only
            umm.erase(it1);
            break;
        }
        it1++;
    }
}
 
// Utility function to print unordered_multimap
void printUmm(unordered_multimap umm)
{
    // begin() returns iterator to first element of map
    umit it = umm.begin();
    for (; it != umm.end(); it++)
        cout << "<" << it->first << ", " << it->second
             << "> ";
    cout << endl;
}
 
// Driver code
int main()
{
    // initializing multimap by initializer list
    unordered_multimap umm({ { "apple", 1 },
                                          { "ball", 2 },
                                          { "apple", 10 },
                                          { "cat", 7 },
                                          { "dog", 9 },
                                          { "cat", 6 },
                                          { "apple", 1 } });
 
    cout << "Initial content\n";
    printUmm(umm);
    pair kv = make_pair("apple", 1);
 
    // inserting one more  pair
    umm.insert({ "apple", 1 });
    cout << "\nAfter insertion of one more \n";
    printUmm(umm);
 
    if (find_kv(umm, kv))
        erase_kv(umm, kv);
    else
        cout << "key-value pair is not there in unordered "
                "multimap\n";
 
    cout << "\nAfter deletion one occurrence of \n";
    printUmm(umm);
}
输出
Initial content
       

After insertion of one more 
        

After deletion one occurrence of 
       

unordered_multimap的方法:

  • begin()–返回一个迭代器,该迭代器指向容器中的第一个元素或其存储桶中的第一个元素。
  • end()–返回一个迭代器,该迭代器指向容器中最后一个元素之后的位置,或者指向其存储桶中最后一个元素之后的位置。
  • count()–返回容器中其键等于在参数中传递的键的元素数。
  • cbegin()–返回一个常量迭代器,该迭代器指向容器中的第一个元素或其存储桶中的第一个元素。
  • cend()–返回一个常量迭代器,该常量迭代器指向容器中最后一个元素之后的位置,或者指向其存储桶中最后一个元素之后的位置。
  • clear()–清除unordered_multimap容器的内容。
  • size()–返回unordered_multimap的大小。它表示该容器中元素的数量。
  • swap()–交换两个unordered_multimap容器的内容。两个容器的尺寸可能不同。
  • find()–返回一个迭代器,该迭代器指向具有键k的元素之一。
  • bucket_size()–返回存储桶n中的元素数。
  • empty()–如果unordered_multimap容器为空,则返回true。否则,它返回false。
  • equal_range()–返回所有元素键等于一个键的范围。
  • 运算符= –从其他容器复制/分配/移动元素。
  • max_size()–返回unordered_multimap容器可以容纳的最大元素数。
  • load_factor()–返回unordered_multimap容器中的当前负载系数。
  • key_eq()–根据比较结果返回布尔值。
  • emplace()–在unordered_multimap容器中插入新的{key,element}。
  • emplace_hint()–在unordered_multimap容器中插入一个新的{key:element}。
  • bucket_count()–返回unordered_multimap容器中的存储桶总数。
  • bucket()–返回给定密钥所在的存储桶编号。
  • max_load_factor()–返回unordered_multimap容器的最大加载因子。
  • rehash()–将容器中的存储桶数设置为N或更多。
  • reserve()–将容器中的存储桶数(bucket_count)设置为最合适的数量,以使其至少包含n个元素。
  • hash_function()–此哈希函数是一元函数,仅接受单个参数,并根据该参数返回size_t类型的唯一值。
  • max_bucket_count()–返回无序多图容器可以具有的最大存储桶数。
要从最佳影片策划和实践问题去学习,检查了C++基础课程为基础,以先进的C++和C++ STL课程基础加上STL。要完成从学习语言到DS Algo等的更多准备工作,请参阅“完整面试准备课程”