当前位置:   article > 正文

【C++】模拟实现哈希表(线性探测法、链地址法)_哈希表模拟实现

哈希表模拟实现

目录

【C++】模拟实现哈希表(闭散列、开散列)

哈希表的概念

哈希表的模拟实现

线性探测法的实现

具体实现

链地址法的实现

具体实现

哈希表的具体实现

迭代器的具体实现


哈希表的概念

  • 哈希表(Hash Table)是一种基于哈希函数实现的数据结构,用于存储键值对(Key-Value pairs)。它通过将键映射到哈希表的索引位置来实现快速的数据检索。哈希表的核心思想是将键通过哈希函数转换成一个固定大小的索引,然后将值存储在该索引位置上。

  • 哈希函数(Hash Function):

哈希函数是将任意长度的输入(键)映射为固定长度的输出(哈希值)的函数。 哈希函数应该是高效的,即能够在常数时间内计算出哈希值。理想情况下,哈希函数应该具有良好的均匀性,即能够将键均匀地分布到哈希表的索引位置上,从而减少哈希冲突的发生。

  • 哈希冲突(Hash Collision):

哈希冲突是指两个不同的键被哈希函数映射到了相同的索引位置上。 哈希冲突是不可避免的,在实际应用中需要使用特定的方法来处理冲突,以确保哈希表的性能和正确性。

  • 存储桶(Bucket):

哈希表中存储数据的基本单元称为存储桶或哈希槽。 每个存储桶可以存储一个或多个键值对,具体取决于哈希表的实现方式。 解决冲突的方法:

  • 链地址法(Chaining):在每个存储桶中维护一个链表或其他数据结构,将哈希冲突的键值对存储在同一个桶中。

开放定址法(Open Addressing):在发生哈希冲突时,尝试寻找另一个空闲的存储位置来存储冲突的键值对,常见的方法包括线性探测、二次探测和双重散列等。

  • 负载因子(Load Factor):

负载因子是哈希表中已存储的键值对数量与哈希表容量之比。 负载因子的控制对哈希表的性能有重要影响,通常当负载因子超过一定阈值时,需要进行哈希表的扩容操作,以减少哈希冲突的发生。

哈希表的模拟实现

  • 废话不多说直接看整段代码

线性探测法的实现

  • 命名空间和枚举常量:

命名空间 close_address 包含了整个哈希表的实现。 枚举常量 State 定义了三种状态:EMPTY 表示该位置为空,EXIST 表示该位置有有效的键值对,DELETE 表示该位置的键值对已被删除。 哈希函数对象模板:

  • HashFunc 是一个函数对象模板,用于根据键的类型计算哈希值。

对于整型键(K),哈希函数直接将键强制转换为 size_t 类型作为哈希值。 对于字符串类型键(string),哈希函数采用了经典的哈希算法(乘以 31 并加上字符 ASCII 码)。

  • 哈希数据结构:

HashData 结构体模板定义了存储在哈希表中的数据及其状态(_data 和 _s)。

  • 哈希表模板类:

Hash_Table 是哈希表的模板类,支持键(K)和值(T)的任意类型。 构造函数初始化了哈希表的大小和容量,并创建了存储数据的向量 _hashT,将每个位置的状态初始化为 EMPTY。 Insert 方法用于向哈希表中插入键值对,如果键已存在则返回 false。如果哈希表的负载因子超过阈值,则进行扩容操作。 扩容操作会创建一个新的哈希表 tmp,将原哈希表中的数据重新插入到新哈希表中,并将新哈希表与原哈希表交换。 Find 方法用于查找指定键的位置,返回指向该位置的指针。如果找到则返回指向该位置的指针,否则返回 nullptr。 Erase 方法用于删除指定键的键值对,将其状态标记为 DELETE,并更新哈希表的大小。

  • 私有成员变量:

vector _hashT 存储哈希表中的数据。 _size 记录哈希表中有效数据的个数。 _capacity 记录哈希表的总容量。 _hf 记录哈希函数对象。

  1. #define DEFAULT_CAPACITY 10
  2. namespace close_address
  3. {
  4.  enum State//状态的枚举常量
  5.  {
  6.   EMPTY,
  7.   EXIST,
  8.   DELETE
  9.  };
  10.  template<class K>
  11.  struct HashFunc
  12.  {
  13.   size_t operator()(const K& key)
  14.   {
  15.    return (size_t)key;
  16.   }
  17.  };
  18.  template<>
  19.  struct HashFunc<string>
  20.  {
  21.   size_t operator()(const string& key)
  22.   {
  23.    size_t ret = 0;
  24.    for (auto x : key)
  25.    {
  26.     ret *= 31;
  27.     ret += x;
  28.    }
  29.    return ret;
  30.   }
  31.  };
  32.  template<class K, class T>
  33.  struct HashData
  34.  {
  35.   T _data;
  36.   State _s;
  37.  };
  38.  template<class K, class T, class HashF = HashFunc<K> >
  39.  class Hash_Table
  40.  {
  41.  public:
  42.   typedef HashData<K, T> HashData;
  43.   Hash_Table(size_t capacity = DEFAULT_CAPACITY)
  44.    :_size(0),
  45.    _capacity(capacity)
  46.   {
  47.    _hashT.resize(capacity);
  48.    for (size_t i = 0; i < _capacity; i++)
  49.    {
  50.     _hashT[i]._s = EMPTY;
  51.    }
  52.   }
  53.   bool Insert(const T& value)
  54.   {
  55.    if (Find(_kot(value)))
  56.     return false;
  57.    if (_size * 10 / _capacity >= 7)//扩容部分
  58.    {
  59.     size_t newCapacity = _capacity * 2;
  60.     _capacity = newCapacity;
  61.     Hash_Table<K, T> tmp(newCapacity);
  62.     for (int i = 0; i < _size; i++)
  63.     {
  64.      tmp.Insert(_hashT[i]._data);
  65.     }
  66.     _hashT.swap(tmp._hashT);
  67.    }
  68.    size_t hashi = _hf(_kot(value)) % _capacity;
  69.    while (_hashT[hashi]._s == EXIST)
  70.    {
  71.     hashi++;
  72.     hashi %= _capacity;
  73.    }
  74.    _hashT[hashi]._data = value;
  75.    _hashT[hashi]._s = EXIST;
  76.    _size++;
  77.    return true;
  78.   }
  79.   HashData* Find(const K& key)
  80.   {
  81.    size_t hashi = _hf(key) % _capacity;
  82.    while (_hashT[hashi]._s != EMPTY)
  83.    {
  84.     if (_hashT[hashi]._s == EXIST && _hashT[hashi]._data.first == key)
  85.      return &(_hashT[hashi]);
  86.     hashi++;
  87.     hashi %= _capacity;
  88.    }
  89.    return nullptr;
  90.   }
  91.   bool Erase(const K& key)
  92.   {
  93.    HashData* pos = Find(key);
  94.    if (pos == nullptr)
  95.     return false;
  96.    pos->_s = DELETE;
  97.    _size--;
  98.    return true;
  99.   }
  100.  private:
  101.   vector<HashData> _hashT;
  102.   size_t _size;//有效数据个数
  103.   size_t _capacity;//哈希表的总容量
  104.   HashF _hf;
  105.  };
  106. }

具体实现

  • 成员变量 _hashT:一个HashData类型的vector,用于存储哈希表中的元素。 _size:哈希表中有效数据的个数。 _capacity:哈希表的总容量。 _hf:哈希函数对象,用于计算键的哈希值。
    1. private:
    2.    vector<HashData> _hashT;
    3.    size_t _size;//有效数据个数
    4.    size_t _capacity;//哈希表的总容量
    5.    HashF _hf;
  • 构造函数

构造函数接受一个可选的size_t类型的参数capacity,表示哈希表的初始容量。在构造函数中,哈希表的大小被初始化为指定的容量,并且所有桶的状态都被设置为EMPTY。

  1.   Hash_Table(size_t capacity = DEFAULT_CAPACITY)
  2.    :_size(0),
  3.    _capacity(capacity)
  4.   {
  5.    _hashT.resize(capacity);
  6.    for (size_t i = 0; i < _capacity; i++)
  7.    {
  8.     _hashT[i]._s = EMPTY;
  9.    }
  10.   }
  • 插入函数Insert

首先,检查要插入的值是否已经存在于哈希表中。如果存在,返回false。 接着,检查哈希表是否需要扩容。如果哈希表的负载因子(_size / _capacity)超过70%,则进行扩容。扩容操作是创建一个新的哈希表,将旧哈希表中的所有元素插入到新哈希表中,然后交换两个哈希表的_hashT成员。 计算键的哈希值,并在哈希表中查找一个空的桶来存储新元素。如果找到,将新元素插入到该桶中,并更新哈希表的大小。

  1.   bool Insert(const T& value)
  2.    {
  3.     if (Find(_kot(value)))
  4.      return false;
  5.     if (_size * 10 / _capacity >= 7)//扩容部分
  6.     {
  7.      size_t newCapacity = _capacity * 2;
  8.      _capacity = newCapacity;
  9.      Hash_Table<K, T> tmp(newCapacity);
  10.      for (int i = 0; i < _size; i++)
  11.      {
  12.       tmp.Insert(_hashT[i]._data);
  13.      }
  14.      _hashT.swap(tmp._hashT);
  15.     }
  16.     size_t hashi = _hf(_kot(value)) % _capacity;
  17.     while (_hashT[hashi]._s == EXIST)
  18.     {
  19.      hashi++;
  20.      hashi %= _capacity;
  21.     }
  22.     _hashT[hashi]._data = value;
  23.     _hashT[hashi]._s = EXIST;
  24.     _size++;
  25.     return true;
  26.    }
  • 查找函数Find

根据给定的键计算哈希值,并在哈希表中查找该键对应的元素。如果找到,返回指向该元素的指针;否则,返回nullptr。

  1.   HashData* Find(const K& key)
  2.    {
  3.     size_t hashi = _hf(key) % _capacity;
  4.     while (_hashT[hashi]._s != EMPTY)
  5.     {
  6.      if (_hashT[hashi]._s == EXIST && _hashT[hashi]._data.first == key)
  7.       return &(_hashT[hashi]);
  8.      hashi++;
  9.      hashi %= _capacity;
  10.     }
  11.     return nullptr;
  12.    }
  • 删除函数Erase

首先,调用Find函数查找要删除的键对应的元素。如果找到,将该元素的状态设置为DELETE,并更新哈希表的大小。

  1.     bool Erase(const K& key)
  2.   {
  3.    HashData* pos = Find(key);
  4.    if (pos == nullptr)
  5.     return false;
  6.    pos->_s = DELETE;
  7.    _size--;
  8.    return true;
  9.   }

链地址法的实现

  • 模板类定义:

template<class K, class T, class KeyOfT, class HashF = HashFunc>:这是一个模板类,它有四个模板参数。 K:键的类型。 T:值的类型。 KeyOfT:用于从值中提取键的仿函数类型。 HashF:哈希函数的类型,默认为 HashFunc。

  • 类型定义:

Node:HashNode 类型的别名,表示哈希表中的节点。 iterator 和 const_iterator:迭代器类型。

  • 成员变量:

_ht:用于存储哈希表的桶,是一个存储指向节点的指针的 vector。 _size:当前哈希表中存储的元素个数。 _capacity:哈希表的容量,即桶的总数。 _hf:哈希函数对象,用于计算键的哈希值。 _kot:从值中提取键的仿函数对象。

  • 成员函数:

begin():返回一个迭代器,指向第一个非空桶中的第一个元素。 end():返回一个迭代器,指向哈希表的末尾(超出最后一个桶的位置)。 Insert(const T& data):向哈希表中插入一个值为 data 的元素。 Find(const K& key):查找键为 key 的元素,并返回指向该元素的迭代器。 Erase(const K& key):删除键为 key 的元素。 析构函数 ~HashTable():释放哈希表占用的内存。

  • 哈希冲突处理:

使用链地址法解决冲突,即在哈希表的每个桶中使用链表来存储具有相同哈希值的元素。 当哈希表的负载因子达到1时,会进行扩容操作,将桶的数量扩大为当前容量的两倍,并重新哈希所有元素到新的桶中。

  • 内存管理:

在插入元素时,通过 new 创建新的节点,并使用链表的头插法将节点插入到相应的桶中。 在删除元素时,释放被删除节点的内存。

  1. namespace hash_bucket
  2. {
  3.  template<class T>
  4.  struct HashNode
  5.  {
  6.   HashNode(const T& data)
  7.    :_sizeext(nullptr),
  8.    _data(data)
  9.   {}
  10.   T _data;
  11.   HashNode* _sizeext;
  12.  };
  13.  template<class K>
  14.  struct HashFunc
  15.  {
  16.   size_t operator()(const K& key)
  17.   {
  18.    return (size_t)key;
  19.   }
  20.  };
  21.  template<class K, class T, class KeyOfT, class Hash>
  22.  class HashTable;
  23.  template<class K, class T, class Refclass Ptr, class KeyOfT, class Hash>
  24.  struct __HTIterator
  25.  {
  26.   typedef HashNode<T> Node;
  27.   typedef __HTIterator<K, T, Ref, Ptr, KeyOfT, Hash> Self;
  28.   Node* _sizeode;
  29.   const HashTable<K, T, KeyOfT, Hash>* _pht;
  30.   size_t _hashi;
  31.   __HTIterator(Node* node, HashTable<K, T, KeyOfT, Hash>* pht, size_t hashi)
  32.    :_sizeode(node)
  33.    , _pht(pht)
  34.    , _hashi(hashi)
  35.   {}
  36.   __HTIterator(Node* node, const HashTable<K, T, KeyOfT, Hash>* pht, size_t hashi)
  37.    :_sizeode(node)
  38.    , _pht(pht)
  39.    , _hashi(hashi)
  40.   {}
  41.   Self& operator++()
  42.   {
  43.    if (_sizeode->_sizeext)
  44.    {
  45.     // 当前桶还有节点,走到下一个节点
  46.     _sizeode = _sizeode->_sizeext;
  47.    }
  48.    else
  49.    {
  50.     // 当前桶已经走完了,找下一个桶开始
  51.     //KeyOfT kot;
  52.     //Hash hf;
  53.     //size_t hashi = hf(kot(_sizeode->_data)) % _pht._capacity;
  54.     ++_hashi;
  55.     while (_hashi < _pht->_capacity)
  56.     {
  57.      if (_pht->_ht[_hashi])
  58.      {
  59.       _sizeode = _pht->_ht[_hashi];
  60.       break;
  61.      }
  62.      ++_hashi;
  63.     }
  64.     if (_hashi == _pht->_capacity)
  65.     {
  66.      _sizeode = nullptr;
  67.     }
  68.    }
  69.    return *this;
  70.   }
  71.   Ref operator*()
  72.   {
  73.    return _sizeode->_data;
  74.   }
  75.   Ptr operator->()
  76.   {
  77.    return &_sizeode->_data;
  78.   }
  79.   bool operator!=(const Self& s)
  80.   {
  81.    return _sizeode != s._sizeode;
  82.   }
  83.  };
  84.  template<>
  85.  struct HashFunc<string>
  86.  {
  87.   size_t operator()(const string& key)
  88.   {
  89.    size_t ret = 0;
  90.    for (auto c : key)
  91.    {
  92.     ret *= 31;
  93.     ret += c;
  94.    }
  95.    return ret;
  96.   }
  97.  };
  98.  template<class K, class T, class KeyOfT, class HashF = HashFunc<K>>
  99.  class HashTable
  100.  {
  101.  public:
  102.   typedef HashNode<T> Node;//将pair改成T
  103.   typedef __HTIterator<K, T, T&, T*, KeyOfT, HashF> iterator;
  104.   typedef __HTIterator<K, T, const T&, const T*, KeyOfT, HashF> const_iterator;
  105.   iterator begin()
  106.   {
  107.    for (size_t i = 0; i < _capacity; ++i)
  108.    {
  109.     if (_ht[i] != nullptr)
  110.      return iterator(_ht[i], this, i);
  111.    }
  112.    return end();
  113.   }
  114.   iterator end()
  115.   {
  116.    return iterator(nullptr, this, _capacity);
  117.   }
  118.   HashTable(size_t capacity = DEFAULT_CAPACITY)
  119.    :_size(0),
  120.    _capacity(capacity)
  121.   {
  122.    _ht.resize(_capacity);
  123.    for (int i = 0; i < _capacity; i++)
  124.    {
  125.     _ht[i] = nullptr;
  126.    }
  127.   }
  128.   pair<iterator, bool> Insert(const T& data)
  129.   {
  130.    iterator it = Find(_kot(data));
  131.    if (it != end())
  132.     return make_pair(it, false);
  133.    // 负载因子最大到1
  134.    if (_size == _capacity)
  135.    {
  136.     vector<Node*> newTables;
  137.     newTables.resize(_capacity * 2, nullptr);
  138.     // 遍历旧表
  139.     for (size_t i = 0; i < _capacity; i++)
  140.     {
  141.      Node* cur = _ht[i];
  142.      while (cur)
  143.      {
  144.       Node* next = cur->next;
  145.       // 挪动到映射的新表
  146.       size_t hashi = hf(kot(cur->_data)) % newTables.size();
  147.       cur->_sizeext = newTables[i];
  148.       newTables[hashi] = cur;
  149.       cur = next;
  150.      }
  151.      _ht[i] = nullptr;
  152.     }
  153.     _ht.swap(newTables);
  154.    }
  155.    size_t hashi = hf(kot(data)) % _capacity;
  156.    Node* newnode = new Node(data);
  157.    // 头插
  158.    newnode->_sizeext = _ht[hashi];
  159.    _ht[hashi] = newnode;
  160.    ++_size;
  161.    return make_pair(iterator(newnode, this, hashi), true);
  162.   }
  163.   iterator Find(const K& key)
  164.   {
  165.    
  166.    size_t hashi = _hf(key) % _capacity;
  167.    Node* cur = _ht[hashi];
  168.    while (cur)
  169.    {
  170.     if (kot(cur->_data== key)
  171.     {
  172.      return iterator(cur, this, hashi);
  173.     }
  174.     cur = cur->_sizeext;
  175.    }
  176.    return end();
  177.   }
  178.   
  179.   bool Erase(const K& key)
  180.   {
  181.    size_t hashi = _hf(key) % _capacity;
  182.    Node* cur = _ht[hashi];
  183.    Node* preT = nullptr;
  184.    while (cur)
  185.    {
  186.     if (_kot(cur->_data== key)
  187.     {
  188.      if (preT == nullptr)
  189.      {
  190.       delete _ht[hashi];
  191.       _ht[hashi] = nullptr;
  192.      }
  193.      else
  194.      {
  195.       preT->_sizeext = cur->_sizeext;
  196.       delete cur;
  197.       cur = nullptr;
  198.      }
  199.      return true;
  200.     }
  201.     preT = cur;
  202.     cur = cur->_sizeext;
  203.    }
  204.    return false;
  205.   }
  206.   ~HashTable()
  207.   {
  208.    for (auto x : _ht)
  209.    {
  210.     Node* cur = x;
  211.     if (cur)
  212.     {
  213.      while (cur)
  214.      {
  215.       Node* next = cur->_sizeext;
  216.       delete cur;
  217.       cur = next;
  218.      }
  219.     }
  220.    }
  221.   }
  222.  private:
  223.   vector<Node*> _ht;
  224.   size_t _size;//有效数据个数
  225.   size_t _capacity;//桶的总数
  226.   HashF _hf;
  227.   KeyOfT _kot;
  228.  };
  229. }

具体实现

哈希表的具体实现
  • begin():

功能:返回指向哈希表中第一个非空桶的迭代器。 实现:遍历哈希表,找到第一个非空桶,并返回对应迭代器;如果没有非空桶,则返回 end() 的迭代器。

  1. iterator begin()
  2.    {
  3.     for (size_t i = 0; i < _capacity; ++i)
  4.     {
  5.      if (_ht[i] != nullptr)
  6.       return iterator(_ht[i], this, i);
  7.     }
  8.     return end();
  9.    }
  10.    
  • end():

功能:返回表示哈希表末尾的迭代器。 实现:直接返回一个表示末尾的迭代器。

  1. iterator end()
  2.    {
  3.     return iterator(nullptr, this, _capacity);
  4.    }
  • HashTable(size_t capacity = DEFAULT_CAPACITY):

功能:构造函数,初始化哈希表。 参数:可选的容量参数,默认为 DEFAULT_CAPACITY。 实现:根据指定容量初始化 _ht,并将每个桶置为空指针。

  1. HashTable(size_t capacity = DEFAULT_CAPACITY)
  2.     :_size(0),
  3.     _capacity(capacity)
  4.    {
  5.     _ht.resize(_capacity);
  6.     for (int i = 0; i < _capacity; i++)
  7.     {
  8.      _ht[i] = nullptr;
  9.     }
  10.    }
  • Insert(const T& data):

功能:向哈希表中插入数据。 参数:要插入的数据。 返回值:返回一个 pair 对象,其中 pair.first 是指向插入数据的迭代器,pair.second 表示插入是否成功。 实现:首先查找是否已存在相同键值的数据,若存在则返回失败;若哈希表容量已满,则进行扩容;然后计算插入位置的哈希值,执行头插法插入数据。

  1.   pair<iterator, bool> Insert(const T& data)
  2.    {
  3.     iterator it = Find(_kot(data));
  4.     if (it != end())
  5.      return make_pair(it, false);
  6.     // 负载因子最大到1
  7.     if (_size == _capacity)
  8.     {
  9.      vector<Node*> newTables;
  10.      newTables.resize(_capacity * 2, nullptr);
  11.      // 遍历旧表
  12.      for (size_t i = 0; i < _capacity; i++)
  13.      {
  14.       Node* cur = _ht[i];
  15.       while (cur)
  16.       {
  17.        Node* next = cur->next;
  18.        // 挪动到映射的新表
  19.        size_t hashi = hf(kot(cur->_data)) % newTables.size();
  20.        cur->_sizeext = newTables[i];
  21.        newTables[hashi] = cur;
  22.        cur = next;
  23.       }
  24.       _ht[i] = nullptr;
  25.      }
  26.      _ht.swap(newTables);
  27.     }
  28.     size_t hashi = hf(kot(data)) % _capacity;
  29.     Node* newnode = new Node(data);
  30.     // 头插
  31.     newnode->_sizeext = _ht[hashi];
  32.     _ht[hashi] = newnode;
  33.     ++_size;
  34.     return make_pair(iterator(newnode, this, hashi), true);
  35.    }
  • Find(const K& key):

功能:在哈希表中查找指定键值的数据。 参数:要查找的键值。 返回值:如果找到指定键值的数据,则返回对应的迭代器;否则返回末尾迭代器。 实现:根据键值计算哈希值,然后在对应桶中线性查找是否存在相同键值的数据。

  1.   iterator Find(const K& key)
  2.    {
  3.     
  4.     size_t hashi = _hf(key) % _capacity;
  5.     Node* cur = _ht[hashi];
  6.     while (cur)
  7.     {
  8.      if (kot(cur->_data== key)
  9.      {
  10.       return iterator(cur, this, hashi);
  11.      }
  12.      cur = cur->_sizeext;
  13.     }
  14.     return end();
  15.    }
  • Erase(const K& key):

功能:从哈希表中删除指定键值的数据。 参数:要删除的键值。 返回值:如果成功删除则返回 true,否则返回 false。 实现:根据键值计算哈希值,然后在对应桶中线性查找并删除数据。

  1.   bool Erase(const K& key)
  2.    {
  3.     size_t hashi = _hf(key) % _capacity;
  4.     Node* cur = _ht[hashi];
  5.     Node* preT = nullptr;
  6.     while (cur)
  7.     {
  8.      if (_kot(cur->_data== key)
  9.      {
  10.       if (preT == nullptr)
  11.       {
  12.        delete _ht[hashi];
  13.        _ht[hashi] = nullptr;
  14.       }
  15.       else
  16.       {
  17.        preT->_sizeext = cur->_sizeext;
  18.        delete cur;
  19.        cur = nullptr;
  20.       }
  21.       return true;
  22.      }
  23.      preT = cur;
  24.      cur = cur->_sizeext;
  25.     }
  26.     return false;
  27.    }
  • ~HashTable():

功能:析构函数,释放哈希表占用的内存。 实现:遍历每个桶,释放其中节点占用的内存。

  1.   ~HashTable()
  2.    {
  3.     for (auto x : _ht)
  4.     {
  5.      Node* cur = x;
  6.      while (cur)
  7.      {
  8.       Node* next = cur->_sizeext;
  9.       delete cur;
  10.       cur = next;
  11.      }
  12.     }
  13.    }
迭代器的具体实现
  • 成员类型定义:

Node:哈希表中节点的类型,HashNode 模板类的实例。 Self:迭代器自身的类型。

  • 成员变量:

_node:指向当前节点的指针。 _pht:指向哈希表的指针。 _hashi:当前节点所在桶的索引。

  • 构造函数:

__HTIterator(Node* node, HashTable<K, T, KeyOfT, Hash>* pht, size_t hashi):

参数:当前节点指针、哈希表指针、当前节点所在桶的索引。 实现:初始化 _node、_pht 和 _hashi。

  1.   __HTIterator(Node* node, HashTable<K, T, KeyOfT, Hash>* pht, size_t hashi)
  2.     :_node(node)
  3.     , _pht(pht)
  4.     , _hashi(hashi)
  5.    {}
  • __HTIterator(Node* node, const HashTable<K, T, KeyOfT, Hash>* pht, size_t hashi):

参数:当前节点指针、哈希表指针、当前节点所在桶的索引(常量版本)。 实现:初始化 _node、_pht 和 _hashi。

  1.   __HTIterator(Node* node, const HashTable<K, T, KeyOfT, Hash>* pht, size_t hashi)
  2.     :_node(node)
  3.     , _pht(pht)
  4.     , _hashi(hashi)
  5.    {}

迭代器操作:

  • operator++():

功能:迭代器自增操作,将迭代器指向下一个节点。 实现:首先检查当前桶是否还有节点,如果有,则将迭代器指向下一个节点;如果当前桶已经走完,则将迭代器指向下一个非空桶的第一个节点。

  1.   Self& operator++()
  2.    {
  3.     if (_node->_sizeext)
  4.     {
  5.      // 当前桶还有节点,走到下一个节点
  6.      _node = _node->_sizeext;
  7.     }
  8.     else
  9.     {
  10.      // 当前桶已经走完了,找下一个桶开始
  11.      //KeyOfT kot;
  12.      //Hash hf;
  13.      //size_t hashi = hf(kot(_node->_data)) % _pht._capacity;
  14.      ++_hashi;
  15.      while (_hashi < _pht->_capacity)
  16.      {
  17.       if (_pht->_ht[_hashi])
  18.       {
  19.        _node = _pht->_ht[_hashi];
  20.        break;
  21.       }
  22.       ++_hashi;
  23.      }
  24.      if (_hashi == _pht->_capacity)
  25.      {
  26.       _node = nullptr;
  27.      }
  28.     }
  29.     return *this;
  30.    }
  • operator*():

功能:获取当前节点的引用。 实现:返回当前节点的数据引用。

  1.   Ref operator*()
  2.    {
  3.     return _node->_data;
  4.    }
  • operator->():

功能:获取当前节点的指针。 实现:返回当前节点的数据指针。

  1.   Ptr operator->()
  2.    {
  3.     return &_node->_data;
  4.    }
  5.   
  • operator!=():
    1.  bool operator!=(const Self& s)
    2.    {
    3.     return _node != s._node;
    4.    }

功能:比较两个迭代器是否相等。 实现:比较两个迭代器的 _node 是否相等。

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/小桥流水78/article/detail/1010593
推荐阅读
相关标签
  

闽ICP备14008679号