C++数据结构哈希表详解

C++数据结构哈希表详解

哈希表(Hash Table)是一种非常重要的数据结构,用于实现字典等各种应用。哈希表将关键字映射到一个固定大小的数据集合中,以支持常数时间复杂度的插入、查找和删除操作。哈希表的核心思想是将关键字通过哈希函数(Hash Function)映射到数据集合中的一个索引位置,哈希函数需要满足良好的散列性质,使得关键字能够均匀地散布在数据集合中。

哈希表的数据结构

哈希表的数据结构包含一个数组和一个哈希函数。数组用于存储数据,哈希函数用于将关键字映射到数组的索引位置。数组大小可以根据需要进行动态调整,以提高哈希表的空间利用率。

template <typename KeyType, typename ValueType>
class HashTable {
public:
  // 哈希表的构造函数
  HashTable();

  // 哈希表的析构函数
  ~HashTable();

  // 插入一个键值对
  void insert(const KeyType& key, const ValueType& value);

  // 查找一个键值对
  const ValueType* find(const KeyType& key) const;

  // 删除一个键值对
  void remove(const KeyType& key);
private:
  // 哈希表的节点结构体
  struct Node {
    KeyType key;         // 键
    ValueType value;     // 值
    Node* next;          // 指向下一个节点的指针
    Node(const KeyType& k, const ValueType& v)
        : key(k), value(v), next(nullptr) {}
  };

  std::vector<Node*> table_;          // 存储数据的数组
  int size_;                          // 哈希表中键值对的个数
  int capacity_;                      // 哈希表的容量
  const int kDefaultCapacity = 10;    // 默认的哈希表容量

  // 哈希函数,将关键字映射到一个索引位置
  int hash(const KeyType& key) const;
};

哈希函数的设计

一个好的哈希函数需要满足以下几个条件:

  1. 一致性:对于相同的输入,哈希函数总是生成相同的输出。

  2. 散列性:哈希函数需要将输入均匀地散布到输出范围内,以减少哈希冲突(Hash Collision)的发生。

  3. 易计算:哈希函数应该快速计算,以确保查找、插入和删除操作的时间复杂度为常数级别。

常用的哈希函数包括取模法、乘法哈希等,其中取模法是最简单、最常用的哈希函数之一。具体实现可以参考如下代码:

template <typename KeyType, typename ValueType>
int HashTable<KeyType, ValueType>::hash(const KeyType& key) const {
  std::hash<KeyType> hash_func;
  return hash_func(key) % capacity_;
}

哈希冲突的解决方法

哈希冲突是指将两个不同的关键字映射到同一个索引位置的情况,解决哈希冲突的方法有多种,常用的方法包括链地址法、开放地址法等。

链地址法(Chaining)是最简单也是最常用的哈希冲突解决方法,它将哈希表中每个索引位置视为一个链表的头结点,当出现哈希冲突时,只需要在对应的链表中插入新的节点即可。具体实现如下:

template <typename KeyType, typename ValueType>
void HashTable<KeyType, ValueType>::insert(const KeyType& key, const ValueType& value) {
  int index = hash(key);
  Node* node = table_[index];
  while (node != nullptr) {
    if (node->key == key) {
      node->value = value;
      return;
    }
    node = node->next;
  }
  Node* new_node = new Node(key, value);
  new_node->next = table_[index];
  table_[index] = new_node;
  ++size_;
}

示例说明1:计算单词出现频率

哈希表的应用非常广泛,下面以计算文本中每个单词出现频率为例。具体实现过程如下:

  1. 遍历文本中的每个单词,以单词为键,出现频率为值,插入哈希表中。

  2. 遍历哈希表的每个键值对,输出单词和出现频率。

void word_count() {
  std::string text =
      "This is a test of word count. This is only a test. word count is "
      "important.";
  std::istringstream iss(text);
  std::string word;
  std::unordered_map<std::string, int> freq;
  while (iss >> word) {
    ++freq[word];
  }
  for (const auto& kv : freq) {
    std::cout << kv.first << ": " << kv.second << std::endl;
  }
}

示例说明2:对数列进行去重

哈希表的另一个常见应用是对数列进行去重。具体实现过程如下:

  1. 遍历数列中的每个元素,以元素值为键,插入哈希表中。

  2. 遍历哈希表的每个键,输出去重后的数列。

void unique_numbers() {
  std::vector<int> nums = {1, 3, 2, 4, 3, 5, 1, 3};
  std::unordered_set<int> unique_nums;
  for (int num : nums) {
    unique_nums.insert(num);
  }
  for (int num : unique_nums) {
    std::cout << num << " ";
  }
}

以上是C++数据结构哈希表的详细攻略,其中涉及到了哈希表的数据结构、哈希函数的设计、哈希冲突的解决方法等核心内容。同时,给出了两条示例说明哈希表的应用场景。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++数据结构哈希表详解 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • C语言实现通用数据结构之通用椎栈

    C语言实现通用数据结构之通用椎栈 概述 通用椎栈(Generic Linked List Stack),简称GLL Stack,是一种通用的数据结构,能够以动态的方式存储和访问任意类型的数据。GLL Stack 采用链表实现,可以进行进栈(push)、出栈(pop)、查看栈顶元素(peek)、判断栈是否为空(isEmpty)等基本操作。 基本操作 数据结构定…

    数据结构 2023年5月17日
    00
  • Python 数据结构之旋转链表

    Python 数据结构之旋转链表 简介 在进行链表操作时,有时需要旋转链表的一部分,即将链表的最后几个节点移到链表的头部。本文将讲解 Python 实现旋转链表的方法。 方法 我们需要了解两个概念:旋转链表、链表反转。 旋转链表 假设链表为1-2-3-4-5,k=2,将链表后两个节点移动到链表头部,即转化为4-5-1-2-3。 做法如下: 先遍历链表,得出链…

    数据结构 2023年5月17日
    00
  • C++语言数据结构 串的基本操作实例代码

    下面是“C++语言数据结构 串的基本操作实例代码”的完整攻略。 什么是串 在计算机领域中,串是由一系列字符组成的数据结构。可以将其理解为一个字符数组,每个字符处于数组中的一个位置,并且可以通过下标位置访问对应的字符。 C++中的串类型可以使用字符数组来表示,另外还有标准库中的string类型。 基本操作 下面是实现串的基本操作的示例代码,并进行了详细的解释。…

    数据结构 2023年5月17日
    00
  • 「双端队列BFS」电路维修

    本题为3月23日23上半学期集训每日一题中B题的题解 题面 题目描述 Ha’nyu是来自异世界的魔女,她在漫无目的地四处漂流的时候,遇到了善良的少女Rika,从而被收留在地球上。Rika的家里有一辆飞行车。有一天飞行车的电路板突然出现了故障,导致无法启动。 电路板的整体结构是一个R行C列的网格( \(R,C \leq 500\) ),如右图所示。每个格点都是…

    算法与数据结构 2023年4月18日
    00
  • Java数据结构学习之栈和队列

    Java数据结构学习之栈和队列 什么是栈 栈(stack)是一种线性数据结构,它只能在一端进行插入和删除操作,这一端被称作栈顶(top)。栈的特点是先进后出(FILO,First-In-Last-Out),即最后进入的元素最先被删除。 栈的实现方式 栈可以使用数组或链表来实现。使用数组实现的栈称作顺序栈,使用链表实现的栈称作链式栈。以下是顺序栈的 Java …

    数据结构 2023年5月17日
    00
  • C语言全面讲解顺序表使用操作

    C语言全面讲解顺序表使用操作 什么是顺序表 顺序表(Sequential List)是一种常见的数据结构,它由一组连续的存储单元组成,并且支持随机访问。通常我们使用数组来实现顺序表。 顺序表的基本操作 初始化 在使用顺序表之前,需要先进行初始化。顺序表的初始化包括两个步骤:指定顺序表的大小,申请内存空间。具体代码如下: #define MAXSIZE 100…

    数据结构 2023年5月17日
    00
  • 环形队列的实现 [详解在代码中]

    1 package DataStructures.Queue.Array.Exerice; 2 3 /** 4 * @author Loe. 5 * @project DataStructures&Algorithms 6 * @date 2023/5/8 7 * @ClassInfo 环形队列 8 * 主要使用取模的特性来实现环形特征 9 */ 1…

    算法与数据结构 2023年5月8日
    00
  • ecnuoj 5042 龟速飞行棋

    5042. 龟速飞行棋 题目链接:5042. 龟速飞行棋 赛中没过,赛后补题时由于题解有些抽象,自己写个题解。 可以发现每次转移的结果只跟后面两个点的胜负状态有关。 不妨设 \(f_{u,a,b}\) 表示,\(u+1\) 号点的胜负态为 \(a\),\(u+2\) 号点的胜负态为 \(b\),此时从 \(1\) 号点出发的胜负态是什么。那么可以发现,利用 …

    算法与数据结构 2023年4月17日
    00
合作推广
合作推广
分享本页
返回顶部