unordered_map和unordered_set的封装与简单测试
//hashtable.h
#pragma once
#include <string>
#include <vector>
using namespace std;
template<class K>
struct HashFunc
{size_t operator()(const K& key){return (size_t)key;}
};
// 特化
template<>
struct HashFunc<string>
{size_t operator()(const string& key){size_t hash = 0;for (auto e : key){hash *= 131;hash += e;}return hash;}
};
namespace Hash_Bucket {template<class T>struct LHashNode {LHashNode(const T& t):_data(t), _next(nullptr){}T _data;LHashNode<T>* _next;};template<class K, class T, class KeyOfT, class Hash>class HashTable;template<class K, class T, class Ptr, class Ref, class KeyOfT, class Hash>struct HTIterator {typedef LHashNode<T> Node;typedef HTIterator<K, T, Ptr, Ref, KeyOfT, Hash> Self;Node* _node;const HashTable<K, T, KeyOfT, Hash>* _pht;HTIterator(Node* node, const HashTable<K, T, KeyOfT, Hash>* pht):_node(node), _pht(pht){}Ref operator*() {return _node->_data;}Ptr operator->() {return &_node->_data;}bool operator!=(const Self& s){return _node != s._node;}bool operator==(const Self& s){return _node == s._node;}Self operator++(){if (_node->_next) {_node = _node->_next;}else {KeyOfT kot;Hash hash;size_t index = hash(kot(_node->_data)) % (_pht->_table.size());index++;while (index < _pht->_table.size() && _pht->_table[index] == nullptr) {index++;}if (index == _pht->_table.size()) {_node = nullptr;}else {_node = _pht->_table[index];}}return *this;}};template<class K, class T, class KeyOfT, class Hash>class HashTable {public:typedef LHashNode<T> Node;// 让迭代器能访问HashTable的私有成员template<class K, class T, class Ptr, class Ref, class KeyOfT, class Hash>friend struct HTIterator;typedef HTIterator<K, T, T*, T&, KeyOfT, Hash> Iterator;typedef HTIterator<K, T, const T*, const T&, KeyOfT, Hash> ConstIterator;//迭代器相关接口Iterator Begin() {for (size_t i = 0; i < _table.size(); i++) {if (_table[i]) {return Iterator(_table[i], this);}}return End();}Iterator End() {return Iterator(nullptr, this);}ConstIterator Begin() const{if (_size == 0)return End();for (size_t i = 0; i < _table.size(); i++){Node* cur = _table[i];if (cur){return ConstIterator(cur, this);}}return End();}ConstIterator End() const{return ConstIterator(nullptr, this);}inline unsigned long __stl_next_prime(unsigned long n){// Note: assumes long is at least 32 bits.static const int __stl_num_primes = 28;static const unsigned long __stl_prime_list[__stl_num_primes] ={53, 97, 193, 389, 769,1543, 3079, 6151, 12289, 24593,49157, 98317, 196613, 393241, 786433,1572869, 3145739, 6291469, 12582917, 25165843,50331653, 100663319, 201326611, 402653189, 805306457,1610612741, 3221225473, 4294967291};const unsigned long* first = __stl_prime_list;const unsigned long* last = __stl_prime_list +__stl_num_primes;const unsigned long* pos = lower_bound(first, last, n);return pos == last ? *(last - 1) : *pos;}HashTable() {_table.resize(__stl_next_prime(0), nullptr);_size = 0;}~HashTable() {for (size_t i = 0; i < _table.size(); i++) {Node* cur = _table[i];while (cur) {Node* next = cur->_next;delete cur;cur = next;}_table[i] = nullptr;}_size = 0;}pair<Iterator, bool> Insert(const T& data) {KeyOfT kot;Hash hash;Iterator it = Find(kot(data));if (it != End())return make_pair(it, false);//扩容if (_size == _table.size()) {vector<Node*> newtable;newtable.resize(__stl_next_prime(_table.size() + 1), nullptr);for (size_t i = 0; i < _table.size(); i++) {Node* cur = _table[i];while (cur) {size_t hash0 = hash(kot(cur->_data)) % newtable.size();Node* next = cur->_next;cur->_next = newtable[hash0];newtable[hash0] = cur;cur = next;}_table[i] = nullptr;}_table.swap(newtable);}size_t hash0 = hash(kot(data)) % _table.size();Node* newnode = new Node(data);//头插法newnode->_next = _table[hash0];_table[hash0] = newnode;_size++;return make_pair(Iterator(newnode, this), true);}Iterator Find(const K& key){Hash hash;KeyOfT kot;size_t hash0 = hash(key) % _table.size();Node* cur = _table[hash0];while (cur) {if (kot(cur->_data) == key) {return Iterator(cur, this);}cur = cur->_next;}return End();}bool Erase(const K& key) {Hash hash;KeyOfT kot;size_t hash0 = hash(key) % _table.size();Node* cur = _table[hash0];Node* prev = nullptr;while (cur) {if (kot(cur -> _data) == key) {if (prev == nullptr) {_table[hash0] = cur->_next;}else {prev->_next = cur->_next;}delete cur;_size--;return true;}prev = cur;cur = cur->_next;}return false;}size_t Size() const {return _size;}private:vector<Node*> _table;size_t _size;};}
//unordered_map.h
#pragma once
#include "HashTable.h"
namespace my_unordered_map {template<class K, class V, class Hash = HashFunc<K>>class unordered_map {struct MapKeyOfT{const K& operator()(const pair<K, V>& kv){return kv.first;}};public:typedef typename Hash_Bucket::HashTable<K, pair<const K, V>, MapKeyOfT, Hash>::Iterator iterator;typedef typename Hash_Bucket::HashTable<K, pair<const K, V>, MapKeyOfT, Hash>::ConstIterator const_iterator;iterator begin(){return _ht.Begin();}iterator end(){return _ht.End();}const_iterator begin() const{return _ht.Begin();}const_iterator end() const{return _ht.End();}pair<iterator, bool> insert(const pair<K, V>& kv){return _ht.Insert(kv);}V& operator[](const K& key){pair<iterator, bool> ret = _ht.Insert(make_pair(key, V()));return ret.first->second;}iterator Find(const K& key){return _ht.Find(key);}bool Erase(const K& key){return _ht.Erase(key);}private:Hash_Bucket::HashTable<K, pair<const K, V>, MapKeyOfT, Hash> _ht;};
}
//unordered_set.h
#pragma once
#include "HashTable.h"
namespace my_unordered_set
{template<class K, class Hash = HashFunc<K>>class unordered_set{struct SetKeyOfT{const K& operator()(const K& key){return key;}};public:typedef typename Hash_Bucket::HashTable<K, const K, SetKeyOfT, Hash>::Iterator iterator;typedef typename Hash_Bucket::HashTable<K, const K, SetKeyOfT, Hash>::ConstIterator const_iterator;iterator begin(){return _ht.Begin();}iterator end(){return _ht.End();}const_iterator begin() const{return _ht.Begin();}const_iterator end() const{return _ht.End();}pair<iterator, bool> insert(const K& key){return _ht.Insert(key);}iterator Find(const K& key){return _ht.Find(key);}bool Erase(const K& key){return _ht.Erase(key);}private:Hash_Bucket::HashTable<K, const K, SetKeyOfT, Hash> _ht;};
}
//test.cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
//#include "unordered_map.h"
//
//int main() {
// // 测试插入和遍历
// my_unordered_map::unordered_map<string, int> um;
// um.insert({ "apple", 1 });
// um.insert({ "banana", 2 });
// um.insert({ "cherry", 3 });
// cout << "插入后元素:" << endl;
// for (auto& p : um) {
// cout << p.first << ":" << p.second << " ";
// }
// cout << endl; // 输出顺序不确定,取决于哈希函数
//
// // 测试operator[]
// um["date"] = 4;
// cout << "um[\"date\"] = " << um["date"] << endl; // 输出4
//
// // 测试查找
// auto it = um.Find("banana");
// if (it != um.end()) {
// cout << "找到banana:" << it->second << endl; // 输出2
// }
//
// // 测试删除
// bool erased = um.Erase("apple");
// cout << "删除apple:" << (erased ? "成功" : "失败") << endl; // 输出成功
// it = um.Find("apple");
// if (it == um.end()) {
// cout << "确认删除apple:成功" << endl;
// }
//
// // 测试遍历删除后元素
// cout << "删除后元素:" << endl;
// for (auto& p : um) {
// cout << p.first << ":" << p.second << " ";
// }
// cout << endl;
//
// return 0;
//}
#include "unordered_set.h"int main() {// 测试插入和遍历my_unordered_set::unordered_set<int> us;us.insert(10);us.insert(20);us.insert(30);us.insert(20); // 重复插入,应失败cout << "插入后元素(无序):";for (auto it = us.begin(); it != us.end(); ++it) {cout << *it << " ";}cout << endl; // 可能输出:10 20 30(顺序取决于哈希函数)// 测试查找auto it = us.Find(20);if (it != us.end()) {cout << "找到元素:" << *it << endl; // 输出20}it = us.Find(40);if (it == us.end()) {cout << "未找到元素40" << endl;}// 测试删除bool erased = us.Erase(20);cout << "删除20:" << (erased ? "成功" : "失败") << endl; // 输出成功it = us.Find(20);if (it == us.end()) {cout << "确认删除20:成功" << endl;}// 测试删除后遍历cout << "删除后元素:";for (auto val : us) { // 范围for依赖迭代器cout << val << " ";}cout << endl; // 可能输出:10 30// 测试字符串类型my_unordered_set::unordered_set<string> us_str;us_str.insert("apple");us_str.insert("banana");us_str.insert("cherry");cout << "字符串集合元素:";for (const auto& s : us_str) {cout << s << " ";}cout << endl;return 0;
}