C++: implementación de tabla hash y encapsulación de unorder_set y unorder_map

1.¿Qué es una tabla hash?

Una tabla hash es una estructura de datos que se utiliza para almacenar datos. Los datos almacenados en una tabla hash están desordenados y se pueden agregar, eliminar y verificar. Los datos no se pueden modificar en ese momento. Puede obtener el elemento que se buscará directamente desde la tabla a la vez sin ninguna comparación. Si construye una estructura de almacenamiento y utiliza una determinada función (hashFunc) para establecer una relación de mapeo uno a uno entre la ubicación de almacenamiento del elemento y su código clave, entonces el elemento se puede encontrar rápidamente a través de esta función durante la búsqueda. Este método es el método hash (hash), la función de conversión utilizada en el método hash se llama función hash (hash) y la estructura construida se llama tabla hash (tabla hash) (o tabla hash).
unordered_map es un contenedor asociativo que almacena pares clave-valor <clave, valor>, lo que permite una indexación rápida al valor correspondiente a través de claves.
En unordered_map, el valor clave se usa generalmente para identificar de forma única el elemento, mientras que el valor del mapa es un objeto cuyo contenido está asociado con esta clave. Las claves y los valores asignados pueden ser de diferentes tipos.
Internamente, unordered_map no ordena <kye, valor> en ningún orden específico. Para encontrar el valor correspondiente a la clave dentro de un rango constante, unordered_map coloca pares clave-valor con el mismo valor hash en el mismo depósito.
El contenedor unordered_map es más rápido que map para acceder a elementos individuales por clave, pero generalmente es menos eficiente en la iteración de rangos sobre un subconjunto de elementos.
unordered_maps implementa el operador de acceso directo (operador []), que permite el acceso directo al valor usando la clave como parámetro.
Sus iteradores son al menos iteradores directos.

unorder_set es un contenedor asociativo utilizado para almacenar <key>. Puede usarse para búsqueda rápida y deduplicación. Está organizado de manera desordenada internamente. Sus iteradores son los mismos que los de unorder_map. Otras características son las mismas que las de unorder_map Las características son casi las mismas.

2. Colisión de hash

Para las claves $k_i$ y $k_j$(i != j) de dos elementos de datos, existe $k_i$ != $k_j$, pero existe: Hash($k_i$) == Hash($k_j$)
, Es decir: diferentes palabras clave calculan la misma dirección hash a través del mismo número hash, este fenómeno se denomina conflicto hash o colisión hash. Los elementos de datos con claves diferentes pero la misma dirección hash se denominan "sinónimos".

Resolver colisiones de hash:

Una razón para los conflictos de hash puede ser que el diseño de la función hash no sea lo suficientemente razonable.
Principio de diseño de la función hash:
el dominio de la función hash debe incluir todos los códigos clave que deben almacenarse, y si la tabla hash permite m direcciones, su
rango de valores debe estar entre 0 y m-1; la función hash se calcula Las direcciones se puede distribuir uniformemente en todo el espacio; la función hash debe ser relativamente simple.

Dos formas comunes de resolver colisiones de hash son: hash cerrado y hash abierto

Hash cerrado:

Detección lineal: comenzando desde la posición donde ocurre el conflicto, detecte hacia atrás hasta encontrar la siguiente posición vacía.

Obtenga la posición del elemento que se insertará en la tabla hash a través de la función hash. Si no hay ningún elemento en la posición, inserte el nuevo elemento directamente. Si hay un conflicto hash con el elemento en la posición, use la detección lineal para busque la siguiente posición vacía e inserte el nuevo elemento.

Hash abierto:

El método hash abierto también se denomina método de dirección en cadena (método de cadena abierta). Primero, se utiliza una función hash para calcular la dirección hash del conjunto de códigos clave. Los códigos clave con la misma
dirección Los elementos de cada depósito están vinculados a través de una lista vinculada individualmente
y el nodo principal de cada lista vinculada se almacena en la tabla hash.

Comparación de hash abierto y hash cerrado:
la aplicación del método de dirección en cadena para manejar el desbordamiento requiere agregar un puntero de enlace, lo que parece aumentar la sobrecarga de almacenamiento. De hecho:
dado que el método de dirección abierta debe mantener una gran cantidad de espacio libre para garantizar la eficiencia de la búsqueda, por ejemplo, el método de exploración secundaria requiere un factor de carga a <= 0,7
y la entrada de la tabla ocupa mucho más espacio que el puntero, por lo que El uso del método de dirección en cadena no ahorra espacio de almacenamiento que el método de dirección abierta.

3. Implementación de la tabla hash.

Implementación de hash cerrado:

#include <iostream>
#include <vector>
#include <string>
//usng namespace std;
using std::cout;
using std:: endl;
using std::cin;
//闭散列
namespace open_address
{
 //处理不是整形的字符
	template<class T>
	struct DefaultHashFunc
	{
		size_t operator()(const T& t)
		{
			return size_t(value(t));

		}
	};
 //特殊化处理字符串
	template<>
	struct DefaultHashFunc<string>
	{
		const size_t operator()(const string& t)
		{
			//KeyofT value;
			size_t num=1;
			for (auto e : t)
			{
				num *= 131;
				num +=e;
			}
			return num;

		}
	};
 //枚举三种状态
	enum State
	{
		Empty,
		Exist,
		Delete
	};
 //哈希节点
	template<class T>
	struct HashDateNode
	{
	private:
		T _kv;
		State _state=Empty;
	};
//哈希表
	template<class K, class T,class KeyofT,class DefaultHashFunc>
	class HashTable
	{
		typedef HashDateNode<T> Node;
		HashTable()//初始化,开辟10个空间
		{
			_Date.resize(10);
		}
		//插入数值
		bool insert(const T& Date)
		{

			DefaultHashFunc Func;//处理字符串问题
			KeyofT value;//处理set和map的数值问题函数
			//扩容
			if (n * 10 > _Date.size() * 7)//负载因子
			{
				int newsize = _Date.size() * 2;
				vector<Node*> newHT;
				newHT.resize(newsize);//开辟空间
				for (int i = 0; i < _Date.size(); i++)
				{
					if (_Date._state == Exist)//讲旧数据写入新空间中
					{
						newHT.insert(KetofT(_Date));
					}
					_Date.swap(newHT._Date);//交换数据
				}
			}
			//插入哈希表
			size_t hashi =Func(value(Date))% _Date.size();
			while (_Date[hashi]._state == Exist)//存在就++
			{
				++hashi;
				hashi %= _Date.size();
			}
			_Date[hashi]._kv = Date;
			_Date[hashi]._state = Exist;
			n++;//存放个数加一
			return true;
		}
		//查找函数
		vector<Node*> Find(const K& t)
		{
			
			DefaultHashFunc Func;
			KeyofT value;
			size_t hashi = Func(value(t)) % _Date.size();
			while (_Date[hashi]._state != Empty)
			{
				if (_Date[hashi]._state == Exist
					&& value(_Date[hashi]) == t)
				{
					return   _Date[hashi];
				}

				++hashi;
				hashi %= _Date.size();
			}

			return nullptr;

		}
 //删除
		bool erash(const K& key)
		{
			
			vector<Node*> ret = Find(key);//查找是否存在
			if (ret)
			{
				ret._state= Exist;
				n--;
				return true;
			}
			return false;
		}

	private:
		vector<Node*> _Date;//数据
		size_t n;//存储有效个数
	};
}

Implementación de hash abierto

#include <iostream>
#include <string>
#include <vector>
using namespace std;
//处理字符
template<class T>
struct DefaultHashFunc
{
	size_t operator()(const T& t)
	{
		return size_t(t);
	}
};template<>
struct DefaultHashFunc<string>
{
	size_t operator()(const string& t)
	{
		size_t num = 0;
		for (auto e : t)
		{
			num *= 131;
			num += e;
		}
		return num;
	}
};
//哈希桶,闭散列
namespace hash_bucket
{
	template<class T> 
	struct HashDateNode
	{
		T _Date;
		HashDateNode<T>* _next;

		HashDateNode(const T& Date)
			:_Date(Date)
			,_next(nullptr)
		{}
	};
	
	template<class K, class T, class KeyofT, class HashFunc>
	class HashDate;//前置声明

	//迭代器
	//template<class K,class T,class KeyofT ,class HashFunc>//旧版
	template<class K, class T, class Ptr, class Ref, class KeyofT, class HashFunc>//新版
	struct HashIterator
	{
		typedef HashDateNode<T> Node;
		
		typedef HashIterator<K,T, Ptr, Ref,KeyofT, HashFunc> Self;
		typedef HashIterator<K, T, T*, T&, KeyofT, HashFunc> iterator;

		Node* _node;
		const HashDate<K, T, KeyofT, HashFunc>* _pht; //设置位const ,防止普通类型无法转化为const类型

		//初始化
		/*const HashIterator(Node* node, HashDate<K, T, KeyofT, HashFunc>* pht)
			:_node(node)
			, _pht(pht)
		{}*/

		//const初始化
		HashIterator(Node* node, const HashDate<K, T, KeyofT, HashFunc>*  pht)
			:_node(node)
			, _pht(pht)
		{}


		// 普通迭代器时,他是拷贝构造
		// const迭代器时,他是构造函数
		HashIterator(const iterator& it)//防止set类型的const类型与非const类型的转换(模板不同)
			:_node(it._node)
			, _pht(it._pht)
		{}


		Ref operator*()
		{
			return _node->_Date;
		}
		Ptr operator->()
		{
			return &_node->_Date;
		}
		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
			{
				HashFunc Func;
				KeyofT value;
				size_t hashi = Func(value(_node->_Date)) % _pht->_table.size(); //该用仿函数
				//从下一个哈希桶查找
				hashi++;
				while (hashi < _pht->_table.size())
				{
					if (_pht->_table[hashi])//不为空
					{
						_node = _pht->_table[hashi];
						return *this;
					}
					else//为空
					{
						++hashi;
					}
				}
				_node = nullptr;
			}
			return *this;
		}

	};

	template<class K, class T, class KeyofT, class HashFunc = DefaultHashFunc<K>>
	class HashDate
	{
		typedef HashDateNode<T> Node;
		
		// 
		//友元
		template<class K, class T, class Ptr, class Ref, class KeyofT, class HashFunc>
		friend struct HashIterator;//可以使用迭代器

	public:
		typedef HashIterator<K, T, T*, T&, KeyofT, HashFunc> iterator;
		typedef HashIterator<K, T, const T*, const T&, KeyofT, HashFunc> const_iterator;

		iterator begin()
		{
			for (size_t i = 0; i < _table.size(); i++)
			{
				Node* cur = _table[i];
				if (cur)
				{
					return iterator(cur,this);
				}
			}

			return iterator(nullptr, this);
		}

		const_iterator begin() const
		{
			for (size_t i = 0; i < _table.size(); i++)
			{
				Node* cur = _table[i];
				if (cur)
				{
					return iterator(cur, this);
				}
			}

			return iterator(nullptr, this);
		}

		iterator end() 
		{
			return iterator(nullptr, this);
		}

		
		const_iterator end() const
		{
			return iterator(nullptr, this);
		}
		HashDate()
		{
			_table.resize(10, nullptr);
		}

		~HashDate()
		{
			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;
			}
		}

		pair<iterator,bool> Insert(const T& date)
		{
			
			KeyofT value;
			HashFunc Func;
			iterator it = Find(value(date));
			//it!=end()
			if(it != end())
			{
				return make_pair(it,false);
			}

			if (n == _table.size())//扩容
			{
				int newsize = _table.size() * 2;
				vector<Node*> newHash;
				newHash.resize(newsize);
				for (size_t i = 0; i < _table.size(); i++)//旧数据
				{
					Node* cur = _table[i];
					while (cur)
					{
						Node* next = cur->_next;
						size_t hashi = Func(value(cur->_Date))% newsize;
						cur->_next = newHash[hashi];
						newHash[hashi] = cur;
						cur = next;
					}
					_table[i] = nullptr;
				}
				_table.swap(newHash);//交换数据
			}
			//插入
			size_t hashi = Func(value(date))% _table.size();//改变
			//Node* cur = _table[hashi];
			//尾插
			//Node* newNode = new Node(date);
			//while (cur)
			//{
			//	cur = cur->_next;
			//}
			//cur = newNode;
			//头插
			Node* newNode = new Node(date);//新节点
			newNode->_next = _table[hashi];//头结点
			_table[hashi] = newNode;//尾节点
		
			n++;
			return make_pair(iterator(newNode,this),true);
		}


		//查找
		iterator Find(const K& key)//Find为K类型的只用一个数值,T类型的在map中为pair<K,T>类型
		{
			HashFunc Func;
			KeyofT value;
			size_t hashi = Func(key) % _table.size();
			//size_t hashi = Func(value(key)) % _table.size();//不能使用这个
			Node* cur = _table[hashi];
			while (cur)
			{
				if (value(cur->_Date) == key)//?
				{
					return iterator(cur,this);
				}
				cur = cur->_next;
			}
			return iterator(nullptr,this);
		}

		//删除
		bool Erase(const K& key)
		{
			HashFunc Func;
			KeyofT value;
			iterator ret=Find(key);
			if (ret == end())
				return true;
			size_t x = Func(value(key))% _table.size();
			Node* cur = _table[x];
			Node* prev = nullptr;
			while (cur)
			{
				if (value(cur->_Date) == key)
				{
					if (prev == nullptr)
					{
						_table[x] = cur->_next;
					}
					else
					{
						prev->_next = cur->_next;
					}
					
				}
				prev = cur;
				cur = cur->_next;
				delete cur;
				return true;
			}
			return false;
		}
		//打印
		void Print()
		{
			for (int i = 10; i < _table.size(); i++)
			{
				Node* cur = _table[i];
				while (cur)
				{
					std::cout << cur->_Date.first<<" " << cur->_Date.second <<" " << std::endl;
					cur = cur->_next;
				}
			}
			std::cout << std::endl;
		}

	private:
		vector<Node*> _table; //存储数据
		size_t n=0; //记录容器中的个数
	};
}

4.Implementación de Unorderset y Unordermap

4.1 Desordenado

#pragma once
#include "HashTable.h"
using namespace hash_bucket;
//using namespace open_address;


template<class K>
class Unorderset
{
	struct SetKeyofT
	{
		const K& operator()(const K& k)
		{
			return k;
		}
	};
public:
	typedef typename hash_bucket::HashDate<K, K, SetKeyofT>::const_iterator iterator;
	typedef typename hash_bucket::HashDate<K, K, SetKeyofT>::const_iterator const_iterator;

	//typedef typename hash_bucket::HashDate<K, K, SetKeyofT> Hash;
public:
	const_iterator begin() const
	{
		return _ht.begin();
	}
	const_iterator end() const
	{
		return _ht.end();
	}
	pair<iterator, bool> insert(const K& k)
	{
		return _ht.Insert(k);
	}
	iterator find(const K& kk)
	{
		return _ht.Find(kk);
	}
	bool erase(const K& kk)
	{
		return _ht.Erase(kk);
	}
private:
	HashDate<K, K, SetKeyofT> _ht;
};

4.2 Mapa de desorden

#pragma once
#include "HashTable.h"
using namespace hash_bucket;
template<class K,class T>
class Unordermap
{
	struct MapkeyofT
	{
		const K& operator()(const pair<const K, T>& kt)
		{
			return kt.first;
		}
	};
public:
	typedef typename hash_bucket::HashDate<K, pair<const K, T>, MapkeyofT>::iterator iterator;//普通迭代器
	typedef typename hash_bucket::HashDate<K, pair<const K, T>, MapkeyofT>::const_iterator const_iterator;//const迭代器
	//typedef typename hash_bucket::HashDate<K, pair<K, T>, MapkeyofT> Hash;
	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,T>& kt)
	{
		return _ht.Insert(kt);
	}
	//查找
	iterator find(const K& kk)
	{
		return _ht.Find(kk);
	}
	//重载[]
	T& operator[](const K& kk)
	{
		pair<iterator, bool> ret = insert(make_pair(kk, T()));
		return ret.first->second;
	}
	//删除
	bool eraser(const K& kk)
	{
		return _ht.Erase(kk);
	}
private:
	HashDate<K, pair<const K, T>, MapkeyofT> _ht;
};

4.3 Código completo

Ps: se recomienda escribirlos por separado en la implementación específica.

#pragma once
#include "HashTable.h"
using namespace hash_bucket;
using namespace open_address;

//set实现
template<class K>
class Unorderset
{
	struct SetKeyofT
	{
		const K& operator()(const K& k)
		{
			return k;
		}
	};
public:
	typedef typename hash_bucket::HashDate<K, K, SetKeyofT>::const_iterator iterator;
	typedef typename hash_bucket::HashDate<K, K, SetKeyofT>::const_iterator const_iterator;

	//typedef typename hash_bucket::HashDate<K, K, SetKeyofT> Hash;
public:
	const_iterator begin() const
	{
		return _ht.begin();
	}
	const_iterator end() const
	{
		return _ht.end();
	}
	pair<iterator, bool> insert(const K& k)
	{
		return _ht.Insert(k);
	}
	iterator find(const K& kk)
	{
		return _ht.Find(kk);
	}
	bool erase(const K& kk)
	{
		return _ht.Erase(kk);
	}
private:
	HashDate<K, K, SetKeyofT> _ht;
};

//map实现
template<class K,class T>
class Unordermap
{
	struct MapkeyofT
	{
		const K& operator()(const pair<const K, T>& kt)
		{
			return kt.first;
		}
	};
public:
	typedef typename hash_bucket::HashDate<K, pair<const K, T>, MapkeyofT>::iterator iterator;//普通迭代器
	typedef typename hash_bucket::HashDate<K, pair<const K, T>, MapkeyofT>::const_iterator const_iterator;//const迭代器
	//typedef typename hash_bucket::HashDate<K, pair<K, T>, MapkeyofT> Hash;
	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,T>& kt)
	{
		return _ht.Insert(kt);
	}
	//查找
	iterator find(const K& kk)
	{
		return _ht.Find(kk);
	}
	//重载[]
	T& operator[](const K& kk)
	{
		pair<iterator, bool> ret = insert(make_pair(kk, T()));
		return ret.first->second;
	}
	//删除
	bool eraser(const K& kk)
	{
		return _ht.Erase(kk);
	}
private:
	HashDate<K, pair<const K, T>, MapkeyofT> _ht;
};
//底层实现
#pragma once//防止头文件重复引用
#include <iostream>
#include <vector>
#include <string>
using namespace std;


 //处理不是整形的字符
	template<class T>
	struct DefaultHashFunc
	{
		size_t operator()(const T& t)
		{
			return size_t(value(t));

		}
	};
 //特殊化处理字符串
	template<>
	struct DefaultHashFunc<string>
	{
		const size_t operator()(const string& t)
		{
			//KeyofT value;
			size_t num=1;
			for (auto e : t)
			{
				num *= 131;
				num +=e;
			}
			return num;

		}
	};
//开散列
namespace open_address
{

 //枚举三种状态
	enum State
	{
		Empty,
		Exist,
		Delete
	};
 //哈希节点
	template<class T>
	struct HashDateNode
	{
	private:
		T _kv;
		State _state=Empty;
	};
//哈希表
	template<class K, class T,class KeyofT,class DefaultHashFunc>
	class HashTable
	{
		typedef HashDateNode<T> Node;
		HashTable()//初始化,开辟10个空间
		{
			_Date.resize(10);
		}
		//插入数值
		bool insert(const T& Date)
		{

			DefaultHashFunc Func;//处理字符串问题
			KeyofT value;//处理set和map的数值问题函数
			//扩容
			if (n * 10 > _Date.size() * 7)//负载因子
			{
				int newsize = _Date.size() * 2;
				vector<Node*> newHT;
				newHT.resize(newsize);//开辟空间
				for (int i = 0; i < _Date.size(); i++)
				{
					if (_Date._state == Exist)//讲旧数据写入新空间中
					{
						newHT.insert(KetofT(_Date));
					}
					_Date.swap(newHT._Date);//交换数据
				}
			}
			//插入哈希表
			size_t hashi =Func(value(Date))% _Date.size();
			while (_Date[hashi]._state == Exist)//存在就++
			{
				++hashi;
				hashi %= _Date.size();
			}
			_Date[hashi]._kv = Date;
			_Date[hashi]._state = Exist;
			n++;//存放个数加一
			return true;
		}
		//查找函数
		vector<Node*> Find(const K& t)
		{
			
			DefaultHashFunc Func;
			KeyofT value;
			size_t hashi = Func(value(t)) % _Date.size();
			while (_Date[hashi]._state != Empty)
			{
				if (_Date[hashi]._state == Exist
					&& value(_Date[hashi]) == t)
				{
					return   _Date[hashi];
				}

				++hashi;
				hashi %= _Date.size();
			}

			return nullptr;

		}
 //删除
		bool erash(const K& key)
		{
			
			vector<Node*> ret = Find(key);//查找是否存在
			if (ret)
			{
				ret._state= Exist;
				n--;
				return true;
			}
			return false;
		}

	private:
		vector<Node*> _Date;//数据
		size_t n;//存储有效个数
	};
}

//哈希桶,闭散列
namespace hash_bucket
{
	template<class T> 
	struct HashDateNode
	{
		T _Date;
		HashDateNode<T>* _next;

		HashDateNode(const T& Date)
			:_Date(Date)
			,_next(nullptr)
		{}
	};
	
	template<class K, class T, class KeyofT, class HashFunc>
	class HashDate;//前置声明

	//迭代器
	//template<class K,class T,class KeyofT ,class HashFunc>//旧版
	template<class K, class T, class Ptr, class Ref, class KeyofT, class HashFunc>//新版
	struct HashIterator
	{
		typedef HashDateNode<T> Node;
		
		typedef HashIterator<K,T, Ptr, Ref,KeyofT, HashFunc> Self;
		typedef HashIterator<K, T, T*, T&, KeyofT, HashFunc> iterator;

		Node* _node;
		const HashDate<K, T, KeyofT, HashFunc>* _pht; //设置位const ,防止普通类型无法转化为const类型

		//初始化
		/*const HashIterator(Node* node, HashDate<K, T, KeyofT, HashFunc>* pht)
			:_node(node)
			, _pht(pht)
		{}*/

		//const初始化
		HashIterator(Node* node, const HashDate<K, T, KeyofT, HashFunc>*  pht)
			:_node(node)
			, _pht(pht)
		{}


		// 普通迭代器时,他是拷贝构造
		// const迭代器时,他是构造函数
		HashIterator(const iterator& it)//防止set类型的const类型与非const类型的转换(模板不同)
			:_node(it._node)
			, _pht(it._pht)
		{}


		Ref operator*()
		{
			return _node->_Date;
		}
		Ptr operator->()
		{
			return &_node->_Date;
		}
		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
			{
				HashFunc Func;
				KeyofT value;
				size_t hashi = Func(value(_node->_Date)) % _pht->_table.size(); //该用仿函数
				//从下一个哈希桶查找
				hashi++;
				while (hashi < _pht->_table.size())
				{
					if (_pht->_table[hashi])//不为空
					{
						_node = _pht->_table[hashi];
						return *this;
					}
					else//为空
					{
						++hashi;
					}
				}
				_node = nullptr;
			}
			return *this;
		}

	};

	template<class K, class T, class KeyofT, class HashFunc = DefaultHashFunc<K>>
	class HashDate
	{
		typedef HashDateNode<T> Node;
		
		// 
		//友元
		template<class K, class T, class Ptr, class Ref, class KeyofT, class HashFunc>
		friend struct HashIterator;//可以使用迭代器

	public:
		typedef HashIterator<K, T, T*, T&, KeyofT, HashFunc> iterator;
		typedef HashIterator<K, T, const T*, const T&, KeyofT, HashFunc> const_iterator;

		iterator begin()
		{
			for (size_t i = 0; i < _table.size(); i++)
			{
				Node* cur = _table[i];
				if (cur)
				{
					return iterator(cur,this);
				}
			}

			return iterator(nullptr, this);
		}

		const_iterator begin() const
		{
			for (size_t i = 0; i < _table.size(); i++)
			{
				Node* cur = _table[i];
				if (cur)
				{
					return iterator(cur, this);
				}
			}

			return iterator(nullptr, this);
		}

		iterator end() 
		{
			return iterator(nullptr, this);
		}

		
		const_iterator end() const
		{
			return iterator(nullptr, this);
		}
		HashDate()
		{
			_table.resize(10, nullptr);
		}

		~HashDate()
		{
			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;
			}
		}

		pair<iterator,bool> Insert(const T& date)
		{
			
			KeyofT value;
			HashFunc Func;
			iterator it = Find(value(date));
			//it!=end()
			if(it != end())
			{
				return make_pair(it,false);
			}

			if (n == _table.size())//扩容
			{
				int newsize = _table.size() * 2;
				vector<Node*> newHash;
				newHash.resize(newsize);
				for (size_t i = 0; i < _table.size(); i++)//旧数据
				{
					Node* cur = _table[i];
					while (cur)
					{
						Node* next = cur->_next;
						size_t hashi = Func(value(cur->_Date))% newsize;
						cur->_next = newHash[hashi];
						newHash[hashi] = cur;
						cur = next;
					}
					_table[i] = nullptr;
				}
				_table.swap(newHash);//交换数据
			}
			//插入
			size_t hashi = Func(value(date))% _table.size();//改变
			//Node* cur = _table[hashi];
			//尾插
			//Node* newNode = new Node(date);
			//while (cur)
			//{
			//	cur = cur->_next;
			//}
			//cur = newNode;
			//头插
			Node* newNode = new Node(date);//新节点
			newNode->_next = _table[hashi];//头结点
			_table[hashi] = newNode;//尾节点
		
			n++;
			return make_pair(iterator(newNode,this),true);
		}


		//查找
		iterator Find(const K& key)//Find为K类型的只用一个数值,T类型的在map中为pair<K,T>类型
		{
			HashFunc Func;
			KeyofT value;
			size_t hashi = Func(key) % _table.size();
			//size_t hashi = Func(value(key)) % _table.size();//不能使用这个
			Node* cur = _table[hashi];
			while (cur)
			{
				if (value(cur->_Date) == key)//?
				{
					return iterator(cur,this);
				}
				cur = cur->_next;
			}
			return iterator(nullptr,this);
		}

		//删除
		bool Erase(const K& key)
		{
			HashFunc Func;
			KeyofT value;
			iterator ret=Find(key);
			if (ret == end())
				return true;
			size_t x = Func(value(key))% _table.size();
			Node* cur = _table[x];
			Node* prev = nullptr;
			while (cur)
			{
				if (value(cur->_Date) == key)
				{
					if (prev == nullptr)
					{
						_table[x] = cur->_next;
					}
					else
					{
						prev->_next = cur->_next;
					}
					
				}
				prev = cur;
				cur = cur->_next;
				delete cur;
				return true;
			}
			return false;
		}
		//打印
		void Print()
		{
			for (int i = 10; i < _table.size(); i++)
			{
				Node* cur = _table[i];
				while (cur)
				{
					std::cout << cur->_Date.first<<" " << cur->_Date.second <<" " << std::endl;
					cur = cur->_next;
				}
			}
			std::cout << std::endl;
		}

	private:
		vector<Node*> _table; //存储数据
		size_t n=0; //记录容器中的个数
	};
}

Supongo que te gusta

Origin blog.csdn.net/weixin_66828150/article/details/133030844
Recomendado
Clasificación