哈希表链式

链式基操:

#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
using namespace std;

// 链式哈希表
class HashTable
{
public:
	HashTable(int size = primes_[0], double loadFactor = 0.75)
		: useBucketNum_(0)
		, loadFactor_(loadFactor)
		, primeIdx_(0)
	{
		if (size != primes_[0])
		{
			for (; primeIdx_ < PRIME_SIZE; primeIdx_++)
			{
				if (primes_[primeIdx_] >= size)
					break;
			}

			if (primeIdx_ == PRIME_SIZE)
			{
				primeIdx_--;
			}
		}

		table_.resize(primes_[primeIdx_]);
	}

public:
	// 增加元素 不能重复插入key
	void insert(int key)
	{
		// 判断扩容
		double factor = useBucketNum_ * 1.0 / table_.size();
		cout << "factor:" << factor << endl;
		if (factor > loadFactor_)
		{
			expand();
		}

		int idx = key % table_.size();  // O(1)
		if (table_[idx].empty())
		{
			useBucketNum_++;
			table_[idx].emplace_front(key);
		}
		else
		{
			// 使用全局的::find泛型算法,而不是调用自己的成员方法find
			auto it = ::find(table_[idx].begin(), table_[idx].end(), key);  // O(n)
			if (it == table_[idx].end())
			{
				// key不存在
				table_[idx].emplace_front(key);
			}
		}
	}

	// 删除元素
	void erase(int key)
	{
		int idx = key % table_.size();  // O(1)
		// 如果链表节点过长:如果散列结果比较集中(散列函数有问题!!!)
		//                 如果散列结果比较离散,链表长度一般不会过程,因为有装载因子
		auto it = ::find(table_[idx].begin(), table_[idx].end(), key); // O(n)
		if (it != table_[idx].end())
		{
			table_[idx].erase(it);
			if (table_[idx].empty())
			{
				useBucketNum_--;
			}
		}
	}

	// 搜索元素
	bool find(int key)
	{
		int idx = key % table_.size();  // O(1)
		auto it = ::find(table_[idx].begin(), table_[idx].end(), key); // 
		return it != table_[idx].end();
	}

private:
	// 扩容函数
	void expand()
	{
		if (primeIdx_ + 1 == PRIME_SIZE)
		{
			throw "hashtable can not expand anymore!";
		}

		primeIdx_++;
		useBucketNum_ = 0;

		vector<list<int>> oldTable;
		// swap会不会效率很低??? 交换了两个容器的成员变量
		table_.swap(oldTable);
		table_.resize(primes_[primeIdx_]);

		for (auto list : oldTable)
		{
			for (auto key : list)
			{
				int idx = key % table_.size();
				if (table_[idx].empty())
				{
					useBucketNum_++;
				}
				table_[idx].emplace_front(key);
			}
		}
	}

private:
	vector<list<int>> table_; // 哈希表的数据结构
	int useBucketNum_;        // 记录桶的个数
	double loadFactor_;       // 记录哈希表装载因子

	static const int PRIME_SIZE = 10; // 素数表的大小
	static int primes_[PRIME_SIZE];   // 素数表
	int primeIdx_; // 当前使用的素数下标
};

int HashTable::primes_[PRIME_SIZE] = { 3, 7, 23, 47, 97, 251, 443, 911, 1471, 42773 };


int main()
{
	HashTable htable;
	htable.insert(21);
	htable.insert(32);
	htable.insert(14);
	htable.insert(15);

	htable.insert(22);

	htable.insert(67);

	cout << htable.find(67) << endl;
	htable.erase(67);
	cout << htable.find(67) << endl;

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值