数据结构--哈希表

哈希表

总体表述

开发过程,经常需要对数据集合进行维护。
维护数据结合的数据结构可统称为容器。
哈希是维护数据集合的容器的一种,
本文所述的基于数组+双向链表的哈希表,
是综合了数组和链表的复合容器。
通过合理的哈希函数,
在最理想情况下,对n个元素,m个槽情况下,
每个槽均通过双向链表存储 n/m个元素。
这样向哈希表,上述理想情况下,
向哈希表插入元素时间复杂度Θ(1),
删除元素最多时间复杂度Θ(n/m),
搜索元素最多时间复杂度Θ(n/m)。
但由于哈希表,不具备数组的索引访问,排序,
且一般无法达到上述理想的效果。故实际上略显鸡肋。

接口设计

template<typename Key, typename Value>
class ListHash
{
public:
	class Pair
	{
	public:
		Pair()
		{
		}

		Pair(const Key& nKey_, const Value& nValue_)
		{
			m_nKey = nKey_;
			m_nValue = nValue_;
		}

		~Pair()
		{
		}
	public:
		Key m_nKey;
		Value m_nValue;
	};

public:
	ListHash(int nSoltNums_, 
		std::function<int(const Key&, int)> hashFun_ = [](const Key& nKey_, int nSlotsNum_)->int
	{
		return (nKey_ % nSlotsNum_);
	});
	~ListHash();
	ListHash(const ListHash& hash_);
	ListHash& operator=(const ListHash& hash_);

	void Insert(const Pair& nPair_);
	void Delete(const Key& nKey_);
	bool Search(const Key& nKey_, Value& nValue_) const;
private:
	Array::DynArray<List::DoubleList<Pair>*> m_arrSlots;
	std::function<int(const Key&, int)> m_fHashFun;
};

实现

构造

template<typename Key, typename Value>
ListHash<Key, Value>::ListHash(int nSoltNums_, std::function<int(const Key&, int)> hashFun_)
	:m_arrSlots(nSoltNums_, nullptr), m_fHashFun(hashFun_)
{
	for (int _i = 0; _i < nSoltNums_; _i++)
	{
		List::DoubleList<Pair>* _pList = nullptr;
		try
		{
			_pList = new List::DoubleList<Pair>();
		}
		catch (...)
		{
			_pList = nullptr;
			throw "out of memory";
		}
		
		m_arrSlots[_i] = _pList;
	}
}

拷贝构造

template<typename Key, typename Value>
ListHash<Key, Value>::ListHash(const ListHash& hash_)
	: m_arrSlots(hash_.m_arrSlots.GetSize(), nullptr), 				m_fHashFun(hash_.m_fHashFun)
{
	int _nSize = hash_.m_arrSlots.GetSize();
	for (int _i = 0; _i < _nSize; _i++)
	{
		List::DoubleList<Pair>* _pList = nullptr;
		try
		{
			_pList = new List::DoubleList<Pair>(hash_.m_arrSlots[_i]);
		}
		catch (...)
		{
			_pList = nullptr;
			throw "out of memory";
		}

		m_arrSlots[_i] = _pList;
	}
}

赋值

template<typename Key, typename Value>
typename ListHash<Key, Value>& ListHash<Key, Value>::operator=(const ListHash& hash_)
{
	if (this == &hash_)
	{
		return *this;
	}

	this->~ListHash();
	int _nSize = hash_.m_arrSlots.GetSize();
	m_arrSlots = Array::DynArray<List::DoubleList<Pair>*>(_nSize, nullptr);
	for (int _i = 0; _i < _nSize; _i++)
	{
		List::DoubleList<Pair>* _pList = nullptr;
		try
		{
			_pList = new List::DoubleList<Pair>(hash_.m_arrSlots[_i]);
		}
		catch (...)
		{
			_pList = nullptr;
			throw "out of memory";
		}

		m_arrSlots[_i] = _pList;
	}

	m_fHashFun = hash_.m_fHashFun;
	return *this;
}

析构

template<typename Key, typename Value>
ListHash<Key, Value>::~ListHash()
{
	int _nSize = m_arrSlots.GetSize();
	for (int _i = 0; _i < _nSize; _i++)
	{
		delete m_arrSlots[_i];
		m_arrSlots[_i] = nullptr;
	}
}

插入

template<typename Key, typename Value>
void ListHash<Key, Value>::Insert(const Pair& nPair_)
{
	int _nSize = m_arrSlots.GetSize();
	int _nIndex = m_fHashFun(nPair_.m_nKey, _nSize);
	List::DoubleList<Pair> *_pList = m_arrSlots[_i];
	_pList->Add(nPair_);
}

删除

template<typename Key, typename Value>
void ListHash<Key, Value>::Delete(Key nKey_)
{
	int _nSize = m_arrSlots.GetSize();
	int _nIndex = m_fHashFun(nKey_, _nSize);
	List::DoubleList<Pair> *_pList = m_arrSlots[_nIndex];
	List::DoubleList<Pair>::Node* _pNode = _pList->Find([nKey_](const Pair& nPair_)->bool
	{
		if (nPair_.m_nKey == nKey_)
		{
			return true;
		}
		else
		{
			return false;
		}
	});

	if (_pNode)
	{
		_pList->Delete(_pNode);
	}
}

搜索

template<typename Key, typename Value>
bool ListHash<Key, Value>::Search(const Key& nKey_, Value& nValue_) const
{
	int _nSize = m_arrSlots.GetSize();
	int _nIndex = m_fHashFun(nKey_, _nSize);
	List::DoubleList<Pair> *_pList = m_arrSlots[_nIndex];
	List::DoubleList<Pair>::Node* _pNode = _pList->Find([nKey_](const Pair& nPair_)->bool
	{
		if (nPair_.m_nKey == nKey_)
		{
			return true;
		}
		else
		{
			return false;
		}
	});

	if (_pNode == nullptr)
	{
		return false;
	}
	else
	{
		Pair _nPair = _pNode->GetValue();
		nValue_ = _nPair.m_nValue;
		return true;
	}
}

时间复杂度

假设元素个数n,槽个数m
假设可以达到理想效果,即每个槽中均有n/m个元素

构造

时间复杂度Θ(n)

拷贝构造

时间复杂度Θ(n)

赋值

时间复杂度Θ(n)

析构

时间复杂度Θ(n)

插入

时间复杂度Θ(1)

删除

时间复杂度O(n/m)

查找

时间复杂度O(n/m)
发布了117 篇原创文章 · 获赞 84 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/x13262608581/article/details/105421277