Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/126.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在C+;中使用HashMap的最佳方式是什么+;?_C++_Hashmap - Fatal编程技术网

C++ 在C+;中使用HashMap的最佳方式是什么+;?

C++ 在C+;中使用HashMap的最佳方式是什么+;?,c++,hashmap,C++,Hashmap,我知道STL有一个HashMapAPI,但我找不到任何好的、完整的文档,其中有关于这个的好例子 任何好的例子都将不胜感激。标准库包括有序和无序的映射(和)容器。在有序映射中,元素按键、插入和访问顺序进行排序。通常,标准库在内部用于有序映射。但这只是一个实现细节。在无序映射中,插入和访问位于O(1)中。它只是哈希表的另一个名称 带有(有序)std::map的示例: #include <map> #include <iostream> #include <cassert

我知道STL有一个HashMapAPI,但我找不到任何好的、完整的文档,其中有关于这个的好例子


任何好的例子都将不胜感激。

标准库包括有序和无序的映射(和)容器。在有序映射中,元素按键、插入和访问顺序进行排序。通常,标准库在内部用于有序映射。但这只是一个实现细节。在无序映射中,插入和访问位于O(1)中。它只是哈希表的另一个名称

带有(有序)
std::map
的示例:

#include <map>
#include <iostream>
#include <cassert>

int main(int argc, char **argv)
{
  std::map<std::string, int> m;
  m["hello"] = 23;
  // check if key is present
  if (m.find("world") != m.end())
    std::cout << "map contains key world!\n";
  // retrieve
  std::cout << m["hello"] << '\n';
  std::map<std::string, int>::iterator i = m.find("hello");
  assert(i != m.end());
  std::cout << "Key: " << i->first << " Value: " << i->second << '\n';
  return 0;
}

它也是boost的一部分,也就是说,您可以使用相应的来提高可移植性。

A
hash\u map
是一个较旧的非标准化版本,出于标准化目的,它被称为
unordered\u map
(最初在TR1中,从C++11开始就包含在标准中)。顾名思义,它与
std::map
的主要区别在于无序——例如,如果您从
begin()
end()
迭代一个映射,您将按键1按顺序获取项目,但如果您从
begin()
end()
迭代一个
无序的映射,则,您可以或多或少随意地获取项目

无序的_映射
通常具有恒定的复杂性。也就是说,无论表中有多少项,插入、查找等通常需要固定的时间。
std::map
的复杂性与存储的项目数成对数关系,这意味着插入或检索项目的时间会增加,但随着map的增大,速度会非常缓慢。例如,如果查找100万项中的一项需要1微秒,那么您可以预期查找200万项中的一项需要2微秒,查找400万项中的一项需要3微秒,查找800万项中的一项需要4微秒,等等

从实际的角度来看,这并不是全部。从本质上讲,一个简单的哈希表具有固定的大小。使其适应通用容器的可变大小要求有些不简单。因此,(可能)增加表的操作(例如插入)可能相对较慢(也就是说,大多数操作相当快,但周期性地会慢得多)。无法更改表大小的查找通常要快得多。因此,与插入次数相比,进行大量查找时,大多数基于哈希的表往往处于最佳状态。对于插入大量数据,然后在表中迭代一次以检索结果(例如,计算文件中的唯一字数)的情况,
std::map
可能同样快,甚至更快(但是,计算复杂度也是不同的,因此也可能取决于文件中唯一单词的数量)


1其中,在创建映射时,顺序由第三个模板参数定义,默认情况下,
std::less

这里有一个更完整、更灵活的示例,它没有忽略生成编译错误所需的包括:

#include <iostream>
#include <unordered_map>

class Hashtable {
    std::unordered_map<const void *, const void *> htmap;

public:
    void put(const void *key, const void *value) {
            htmap[key] = value;
    }

    const void *get(const void *key) {
            return htmap[key];
    }

};

int main() {
    Hashtable ht;
    ht.put("Bob", "Dylan");
    int one = 1;
    ht.put("one", &one);
    std::cout << (char *)ht.get("Bob") << "; " << *(int *)ht.get("one");
}
#包括
#包括
类哈希表{
std::无序地图htmap;
公众:
无效放置(常量无效*键,常量无效*值){
htmap[key]=值;
}
常量无效*获取(常量无效*键){
返回htmap[key];
}
};
int main(){
哈希表ht;
ht.put(“鲍勃”、“迪伦”);
int-one=1;
ht.put(“一”和“一”);

std::cout证明
std::unordered_map
在GCC stdlibc++6.4中使用哈希映射的证据

这一点在中提到:但在以下回答中:我已经通过以下方式为GCC stdlibc++6.4实现提供了进一步的证据:

  • GDB在类中逐步调试
  • 性能特性分析
下面是该答案中描述的性能特征图的预览:

如何将自定义类和哈希函数与
无序映射一起使用

这个答案很准确:

摘录:平等:

struct Key
{
  std::string first;
  std::string second;
  int         third;

  bool operator==(const Key &other) const
  { return (first == other.first
            && second == other.second
            && third == other.third);
  }
};
散列函数:

namespace std {

  template <>
  struct hash<Key>
  {
    std::size_t operator()(const Key& k) const
    {
      using std::size_t;
      using std::hash;
      using std::string;

      // Compute individual hash values for first,
      // second and third and combine them using XOR
      // and bit shifting:

      return ((hash<string>()(k.first)
               ^ (hash<string>()(k.second) << 1)) >> 1)
               ^ (hash<int>()(k.third) << 1);
    }
  };

}
名称空间std{
模板
结构散列
{
std::size\u t运算符()(常数键和k)常数
{
使用std::size\u t;
使用std::hash;
使用std::string;
//计算第一个的单个散列值,
//第二个和第三个,并使用XOR组合它们
//和位移位:
返回((hash()(k.first)
^(散列()(k.second)>1)

^(hash()(k.third)对于那些试图找出如何在仍然使用标准模板的情况下对自己的类进行散列的人,有一个简单的解决方案:

  • 在您的类中,您需要定义一个等式运算符重载
    =
    。如果您不知道如何做到这一点,Geeksforgeks有一个很棒的教程

  • 在标准名称空间下,声明一个名为hash的模板结构,并将您的类名作为类型(见下文)我发现了一篇很棒的博客文章,其中也展示了一个使用XOR和位移位计算哈希的示例,但这超出了这个问题的范围,但它也包含了关于如何使用哈希函数的详细说明

  • 名称空间std{
    模板
    结构散列{
    size\u t运算符()(常量my\u type&k){
    //在这里执行哈希函数
    ...
    }
    };
    }
    
  • 因此,要使用新的哈希函数实现哈希表,只需像通常一样创建
    std::map
    std::unordered_map
    ,并使用
    my_type
    作为键,标准库将自动使用您之前定义的哈希函数(在步骤2中)对键进行哈希
  • #包括
    int main(){
    std::无序_图我的_图;
    }
    
    你是在问C++1x哈希映射,还是在问std::map?我想要一个类似java.util的东西。
    struct Key
    {
      std::string first;
      std::string second;
      int         third;
    
      bool operator==(const Key &other) const
      { return (first == other.first
                && second == other.second
                && third == other.third);
      }
    };
    
    namespace std {
    
      template <>
      struct hash<Key>
      {
        std::size_t operator()(const Key& k) const
        {
          using std::size_t;
          using std::hash;
          using std::string;
    
          // Compute individual hash values for first,
          // second and third and combine them using XOR
          // and bit shifting:
    
          return ((hash<string>()(k.first)
                   ^ (hash<string>()(k.second) << 1)) >> 1)
                   ^ (hash<int>()(k.third) << 1);
        }
      };
    
    }