C++中的无序映射

时间:2020-02-23 14:30:08  来源:igfitidea点击:

在本文中,我们将介绍如何在C++中使用无序映射数据结构。

这是C++标准模板库(STL)的一部分,并且是非常有用的数据结构。

让我们使用一些说明性示例更详细地了解这一点。

无序映射数据结构

这是一个关联容器,可以将元素存储为键值对。

其中您将键与映射值相关联。
我们可以通过此键访问此映射值。

使用此数据结构的优势是由于其插入和删除时间非常快(平均O(1)时间复杂度)。

由于无序地图使用哈希表,因此将直接为我们提供非常快速的访问时间!

现在,我们使用一些说明性示例来理解这一点。

在C++ STL中使用无序映射

这是C++中STL的一部分,在 <unordered_map>中定义。

#include <unordered_map>

template <class Key, class Value> class unordered_map;

最常见的参数是"键"和"值",这是键值对。

您还可以将其他参数传递给std :: unordered_map,但是为了说明起见,我们将不再使用它们。
(您可以在这里参考它们)

现在开始吧!

C++ STL中的无序映射–一些示例

让我们看一些C++中无序映射的示例。

1.插入到无序地图

首先,通过将其分配给变量来声明我们的容器结构。

#include <iostream>
#include <unordered_map>
#include <string>

int main() {
  //We declare our unordered map (int, string)
  //Here, the key is an int, and the value is a string
  std::unordered_map<int, std::string> my_map;

  //Direct array-like access!
  my_map[10] = "Hello from theitroad!";
  my_map[20] = "Sample String";

  std::cout << my_map[10] << std::endl;
  std::cout << my_map[20] << std::endl;

  return 0;
}

请注意,此数组与数组之间的相似之处在于分配和访问的方式相同!

输出

Hello from theitroad!
Sample String

使用类似数组的索引进行分配和修改看起来非常容易。
现在,我们要遍历无序地图。

根据定义,由于无序映射不定义任何顺序,因此我们不能保证元素按顺序打印。

请记住,这是一个哈希表。
因此,这些值将基于其哈希值插入一个随机位置。

2.搜索无序地图

由于这是STL的一部分,因此我们可以使用迭代器对其进行迭代。

如果要搜索整个地图,可以直接使用" for-each"循环。

#include <iostream>
#include <unordered_map>
#include <string>

int main() {
  //We declare our unordered map (int, string)
  //Here, the key is an int, and the value is a string
  std::unordered_map<int, std::string> my_map;

  //Directly array-like access!
  my_map[10] = "Hello from theitroad!";
  my_map[20] = "Sample String";

  //We can traverse using a for-each loop
  for (const auto& it: my_map) {
      //Here, it.first -&gt; Key
      //and it.seconds -> Value
      std::cout << it.first << ": " << it.second << std::endl;
  }

  return 0;
}

输出

20: Sample String
10: Hello from theitroad!

请注意,在我的情况下,不保留搜索顺序。
这确实表明地图是无序的。

如果要查找特定键是否存在,可以使用" find"方法进行元素查找。

#include <iostream>
#include <unordered_map>
#include <string>

int main() {
  //We declare our unordered map (int, string)
  //Here, the key is an int, and the value is a string
  std::unordered_map<int, std::string> my_map;

  //Directly array-like access!
  my_map[10] = "Hello from theitroad!";
  my_map[20] = "Sample String";

  std::cout << "Searching for element with key = 10\n";
  auto it = my_map.find(10);
  std::cout << it->first << ": " << it->second << std::endl;

  std::cout << "Searching for element with key = 30\n";
  it = my_map.find(30);
  std::cout << it->first << ": " << it->second << std::endl;

  return 0;
}

输出

Searching for element with key = 10
10: Hello from theitroad!
Searching for element with key = 30
[1]    243 segmentation fault (core dumped)  ./a.out

虽然我们可以在第一种情况下获得键值对(10),但在第二种情况下发生了什么?

由于在地图中找不到键30,因此迭代器没有"第一"或者"第二"成员。

为避免这种情况,我们必须检查密钥是否不存在。

如果密钥不存在,我们将获得特殊的迭代器" std :: unordered_map.end()"。

让我们为搜索添加过滤条件。

#include <iostream>
#include <unordered_map>
#include <string>

int main() {
  //We declare our unordered map (int, string)
  //Here, the key is an int, and the value is a string
  std::unordered_map<int, std::string> my_map;

  //Directly array-like access!
  my_map[10] = "Hello from theitroad!";
  my_map[20] = "Sample String";

  std::cout << "Searching for element with key = 10\n";
  auto it = my_map.find(10);
  if (it != my_map.end())
      std::cout << it->first << ": " << it->second << std::endl;
  else
      std::cout << "Key not found\n";

  std::cout << "Searching for element with key = 30\n";
  it = my_map.find(30);
  if (it != my_map.end())
      std::cout << it->first << ": " << it->second << std::endl;
  else
      std::cout << "Key not found\n";

  return 0;
}

输出

Searching for element with key = 10
10: Hello from theitroad!
Searching for element with key = 30
Key not found

现在,只要在地图上找不到键,我们就可以正确指出。

3.从无序地图中删除

与插入和搜索类似,我们还可以从无序映射中删除元素。

STL为我们提供了" erase()"方法。

我们可以通过多种方式擦除元素:

  • 使用迭代器(my_map.erase(mymap.begin()))
  • 使用密钥(my_map.erase(key))
  • 通过范围(`my_map.erase(my_map.find(key),my_map.end()))

第一种方法将删除第一个索引处的元素(如果存在)。

第二种方法将从映射中删除键值对(如果存在)。

第三种方法将使用基于范围的迭代器来擦除它们之间的所有元素!

#include <iostream>
#include <unordered_map>
#include <string>

int main() {
  //We declare our unordered map (int, string)
  //Here, the key is an int, and the value is a string
  std::unordered_map<int, std::string> my_map;

  //Directly array-like access!
  my_map[10] = "Hello from theitroad!";
  my_map[20] = "Sample String";
  my_map[30] = "Text";

  std::cout << "Initially, map contains:\n";
  for (const auto& it: my_map) {
      std::cout << it.first << ": " << it.second << std::endl;
  }

  std::cout << "Deleting Key: 10...\n";

  my_map.erase(10);

  std::cout << "Map now contains:\n";
  for (const auto& it: my_map) {
      std::cout << it.first << ": " << it.second << std::endl;
  }

  //Erase everything! From beginning to the end
  my_map.erase(my_map.begin(), my_map.end());

  std::cout << "Map now contains:\n";
  for (const auto& it: my_map) {
      std::cout << it.first << ": " << it.second << std::endl;
  }

  return 0;
}

输出

Initially, map contains:
30: Text
20: Sample String
10: Hello from theitroad!
Deleting Key: 10...
Map now contains:
30: Text
20: Sample String
Map now contains:

如您所见,我们能够获得正确的输出!删除键10之后,我们只剩下了另外两对。

使用范围过滤器删除后,我们就可以删除地图上的所有内容!