哈希表——直接定址法

“test.cpp”

<strong><span style="font-size:18px;">#include<iostream>
using namespace std;
#include<vector>

enum Status
{
	EMPTY,
	EXIST,
	DELETE,
};

template<class K,class V>
struct HashTableNode
{
	K _key;
	V _value;
	Status _status;

	HashTableNode(const K& key = K(),const V& value = V())
		:_key(key)
		,_value(value)
		,_status(EMPTY)
	{}
};

template<class K,class V>
class HashTable
{
	typedef HashTableNode<K,V> Node;
public:
	HashTable()
		:_size(0)
	{
		_table.resize(0);
		//_table.resize(_GetNextPrime(0));
	}

	bool Insert(const K& key,const V& value)
	{
		//检查负载因子,查看是否需要扩容
		_Check();
		int index = _HashFunc(key);
		
		while(_table[index]._status != EMPTY)
		{
			++index;
			if(index == _table.size())
			{
				index = 0;
			}		
		}

		_table[index]._key = key;
		_table[index]._value = value;
		_table[index]._status = EXIST;
		_size++;
	}
	Node* Find(const K& key)
	{
		size_t index = _HashFunc(key);
		//记录第一次查找的下标
		size_t src = index;

		while(_table[index]._status != EMPTY)
		{
			if(_table[index]._key == key)
			{
				if(_table[index]._status != DELETE)
					return &_table[index];
				else
					return NULL;
			}
			++index;

			if(index == _table.size())
				index = 0;
			
			//避免死循环操作
			if(index == src)
				return NULL;
		}

		return NULL;
	}

	bool Remove(const K& key)
	{
		Node* ret = Find(key);

		if(ret)
		{
			ret->_status = DELETE;
			--_size;
			return true;
		}

		return false;
	}

	void Display()
	{
		for(int i = 0;i < _table.size();i++)
		{
			if(_table[i]._status == DELETE)
				_table[i]._key = 0;

			cout<<"["<<i<<"] "<<_table[i]._key<<endl;
		}
		cout<<"size = "<<_size<<endl;
	}
protected:
	void _Check()
	{
		if(_table.size() != 0 &&_size*10 / _table.size() < 8)
			return;
		
		//负载因子超过或等于0.8,需要进行扩容
		size_t newsize = _GetNextPrime(_table.size());
		HashTable<K,V> hash;
		hash._table.resize(newsize);
		for(int i = 0;i < _table.size();i++)
		{
			if(_table[i]._status == EXIST)
			{
				hash.Insert(_table[i]._key,_table[i]._value);
			}
		}
		this->_Swap(hash);
	}
	void _Swap(HashTable<K,V>& ht)
	{
		_table.swap(ht._table);
		swap(_size,ht._size);
	}
	size_t _HashFunc(int key)
	{
		return key % _table.size();
	}
	size_t _GetNextPrime(int num)
	{
		const int _PrimeSize = 28;
		static const unsigned long _PrimeList[_PrimeSize] =\
		{\
			53ul,97ul,193ul,389ul,769ul,1543ul,3079ul,6151ul,12289ul,24593ul,49157ul,98317ul,196613ul,393241ul,786433ul,1572869ul,3145739ul,6291469ul,12582917ul,25165843ul,50331653ul,100663319ul,201326611ul,402653189ul,805306457ul,1610612741ul,3221225473ul,4294967291ul\
		};

		for(size_t i = 0;i < _PrimeSize;i++)
		{
			if(_PrimeList[i] > num)
				return _PrimeList[i];
		}

		return _PrimeList[_PrimeSize-1];
	}
private:
	vector<Node> _table;
	size_t _size;
};

void test()
{
	HashTable<int,int> hs;
	int a[] = {89,18,49,58,9};
	for(int i = 0;i < sizeof(a)/sizeof(a[0]);i++)
	{
		hs.Insert(a[i],i);
	}
	hs.Display();
	hs.Remove(18);
	hs.Display();

}
int main()
{
	test();
	return 0;
}</span></strong>


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
哈希表是一种高效的数据结构,可以用来存储和查找键值对。其中,哈希函数将键映射到一个特定的桶中,每个桶中存储一组键值对。在哈希表中,如果两个键被映射到同一个桶中,就会发生碰撞。为了解决这个问题,可以使用链表法。 链表法是一种解决哈希表碰撞问题的方法。具体来说,对于哈希表中的每个桶,可以使用一个链表来存储所有映射到该桶的键值对。如果发生碰撞,只需要将新的键值对添加到链表的末尾即可。 下面是一个使用链表法实现哈希表的示例代码: ```python class Node: def __init__(self, key, value): self.key = key self.value = value self.next = None class HashTable: def __init__(self, capacity): self.capacity = capacity self.buckets = [None] * capacity def hash_function(self, key): return hash(key) % self.capacity def put(self, key, value): index = self.hash_function(key) node = self.buckets[index] while node: if node.key == key: node.value = value return node = node.next new_node = Node(key, value) new_node.next = self.buckets[index] self.buckets[index] = new_node def get(self, key): index = self.hash_function(key) node = self.buckets[index] while node: if node.key == key: return node.value node = node.next return None def remove(self, key): index = self.hash_function(key) node = self.buckets[index] prev = None while node: if node.key == key: if prev: prev.next = node.next else: self.buckets[index] = node.next return prev = node node = node.next ``` 在这个示例中,我们定义了一个Node类来表示哈希表中的每个节点,每个节点包含一个键、一个值和一个指向下一个节点的指针。我们还定义了一个HashTable类来实现哈希表,其中包含一个桶数组和一些基本的操作方法,如put、get和remove。 在put方法中,我们首先使用哈希函数计算出键的索引,然后遍历桶中的链表,查找该键是否已经存在于哈希表中。如果找到了该键,我们只需要更新其对应的值即可。否则,我们创建一个新的节点,并将其添加到链表的开头。 在get方法中,我们同样使用哈希函数计算出键的索引,然后遍历桶中的链表,查找该键的值。如果找到了该键,我们返回其对应的值。否则,返回None。 在remove方法中,我们首先使用哈希函数计算出键的索引,然后遍历桶中的链表,查找该键。如果找到了该键,我们将其从链表中删除即可。 总的来说,链表法是一种简单且常用的哈希表解决碰撞问题的方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值