数据结构-HashTable的简单

最近复习数据结构相关的知识,自己实现一个简单的散列表:

散列表的总结

  1. 散列表是键与值得对应,最主要的优点就是查找的速度很快。
  2. 通过一个hash函数f(k),将key计算得到一个唯一的hash值,然后通过这hash值作为数组的下标来访问元素。
  3. 如果数据量很多或者hash函数选择不当,那么很可能多个多个key计算出来对应了一个数组的下标,这个称为冲突,解决冲突的方法从两个方面入手
    1. 哈希函数:哈希函数的公式比较多,最简单的应该就是取模运算了
    2. 冲突解决:如果真的发生了,那么可以使用额外的步骤来存储这些元素,我这里使用了链表来存储这些元素
  4. 一个简单的示意图,左边代表了一个数组,数组元素指向一个链表,这个链表保存了hash值相同的元素。

  5. 下面是我自己的简单的一个实现,一些优化
    1. Hash函数
    2. 可以实时的调整hash表的大小的,比如当前存储的元素与最大的元素比例到达80%,那么此时可以扩大从而减小冲突
    3. 如果模板的参数是一个引用类型,编译不过
  6. // hashtable.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include <Windows.h>
    #include <iostream>
    using namespace std;
    
    
    
    
    typedef struct _hash_table
    {
    
    } hash_table_t;
    
    
    
    template <typename K, typename V>
    class hashtable
    {
    private:
    	typedef	struct _hash_entry
    	{
    		K key;
    		V value;
    		struct _hash_entry *next;
    
    	} hash_entry_t;
    
    	typedef struct _iterator_data
    	{
    		hash_entry_t *cur_entry;
    		hash_entry_t *next_entry;
    		UINT		cur_index;
    		bool		it_started;
    	} iterator_data_t;
    
    	hash_entry_t **table;
    
    	UINT max_number;
    	UINT persist_number;
    	UINT cur_entry;
    
    	iterator_data_t it_data;
    	UINT get_hashkey(K &key);
    public:
    	hashtable(UINT max_number = 10, UINT(*hash_key)(K &key) = NULL);
    	~hashtable();
    
    	bool insert(K key, V value);
    	bool lookup(K key, V &value);
    	bool remove(K key, V &value);
    	void remove_all();
    
    	bool start_iterator();
    	bool has_next();
    	bool next_entry(K &key, V &value);
    	bool end_iterator();
    
    	UINT(*hash_key)(K &key);
    };
    
    
    
    template<typename K, typename V>
    hashtable<K, V>::hashtable(UINT max_number, UINT(*hash_key)(K &key))
    {
    	this->hash_key = hash_key;
    	this->max_number = max_number;
    	persist_number = 0;
    	cur_entry = 0;
    
    	table = new hash_entry_t*[this->max_number];
    	memset(table, 0x00, sizeof(hash_entry_t*) * this->max_number);
    
    	memset(&it_data, 0x00, sizeof(it_data));
    }
    
    template<typename K, typename V>
    hashtable<K, V>::~hashtable()
    {
    	remove_all();
    	delete table;
    	table = NULL;
    }
    
    template<typename K, typename V>
    UINT hashtable<K, V>::get_hashkey(K &key)
    {
    	if (hash_key)
    	{
    		return hash_key(key);
    	}
    	else
    	{
    		UINT val = (UINT)key;
    		return val % max_number;
    	}
    }
    
    template<typename K, typename V>
    bool hashtable<K, V>::insert(K key, V value)
    {
    	UINT index = get_hashkey(key);
    
    	hash_entry_t *entry = table[index];
    	hash_entry_t *prev_entry = NULL;
    	do
    	{
    		if (entry)
    		{
    			if (entry->key == key)
    			{
    				return false;
    			}
    			else
    			{
    				prev_entry = entry;
    				entry = entry->next;
    			}
    
    		}
    		else
    		{
    			entry = new hash_entry_t;
    
    			entry->key = key;
    			entry->value = value;
    			entry->next = NULL;
    
    			if (prev_entry)
    			{
    				prev_entry->next = entry;
    			}
    			else
    			{
    				table[index] = entry;
    			}
    			break;
    		}
    
    	} while (TRUE);
    
    	return true;
    }
    
    template<typename K, typename V>
    bool hashtable<K, V>::lookup(K key, V & value)
    {
    	UINT index = get_hashkey(key);
    
    	if (table[index])
    	{
    		hash_entry_t *entry = table[index];
    
    		while (entry)
    		{
    			if (entry->key == key)
    			{
    				value = entry->value;
    				return true;
    			}
    			entry = entry->next;
    		}
    	}
    	return false;
    }
    
    template<typename K, typename V>
    bool hashtable<K, V>::remove(K key, V & value)
    {
    	UINT index = get_hashkey(key);
    
    	if (table[index])
    	{
    		hash_entry_t *entry = table[index];
    		hash_entry_t *prev_entry = NULL;
    
    		while (entry)
    		{
    			if (entry->key == key)
    			{
    				value = entry->value;
    				if (prev_entry)
    				{
    					prev_entry->next = entry->next;
    					delete entry;
    					entry = NULL;
    				}
    				else
    				{
    					table[index] = NULL;
    					delete entry;
    					entry = NULL;
    				}
    
    				return true;
    			}
    			prev_entry = entry;
    			entry = entry->next;
    		}
    	}
    	return false;
    }
    
    template<typename K, typename V>
    void hashtable<K, V>::remove_all()
    {
    	for (UINT index = 0; index < max_number; index++)
    	{
    		if (table[index])
    		{
    			hash_entry_t *entry = table[index];
    
    			while (entry)
    			{
    				hash_entry_t *entry_temp = entry;
    				entry = entry->next;
    				delete entry_temp;
    				entry_temp = NULL;
    			}
    
    			table[index] = NULL;
    		}
    	}
    }
    
    template<typename K, typename V>
    bool hashtable<K, V>::start_iterator()
    {
    	if (it_data.it_started)
    	{
    		return false;
    	}
    
    	it_data.cur_entry = NULL;
    	it_data.cur_index = -1;
    	it_data.it_started = true;
    	return true;
    }
    
    
    template<typename K, typename V>
    bool hashtable<K, V>::has_next()
    {
    	if (it_data.cur_entry)
    	{
    		it_data.cur_entry = it_data.cur_entry->next;
    		if (it_data.cur_entry)
    		{
    			return true;
    		}
    	}
    
    	for (it_data.cur_index++; it_data.cur_index < max_number; it_data.cur_index++)
    	{
    		it_data.cur_entry = table[it_data.cur_index];
    
    		if (it_data.cur_entry)
    		{
    			return true;
    		}
    	}
    
    	return false;
    }
    
    template<typename K, typename V>
    bool hashtable<K, V>::next_entry(K &key, V &value)
    {
    	if (it_data.cur_entry)
    	{
    		key = it_data.cur_entry->key;
    		value = it_data.cur_entry->value;
    		return true;
    	}
    	return false;
    }
    
    template<typename K, typename V>
    bool hashtable<K, V>::end_iterator()
    {
    	if (!it_data.it_started)
    	{
    		return false;
    	}
    	it_data.cur_entry = NULL;
    	it_data.cur_index = -1;
    	it_data.it_started = false;
    	return true;
    }
    
    
    
    
    int main()
    {
    
    
    	hashtable<int, int> table;
    
    	for (int i = 0; i < 200; i++)
    	{
    		table.insert(i, i * 20);
    	}
    
    	for (int i = 200; i >= 0; i--)
    	{
    		int value;
    		if (table.lookup(i, value))
    		{
    			cout << "Lookup:" << i << " = " << value << endl;
    		}
    		else
    		{
    			cout << "Lookup " << i << " failed" << endl;
    		}
    	}
    	int value;
    	table.remove(10, value);
    	table.remove(50, value);
    
    	for (int i = 200; i >= 0; i--)
    	{
    		int value;
    		if (table.lookup(i, value))
    		{
    			cout << "Lookup:" << i << " = " << value << endl;
    		}
    		else
    		{
    			cout << "Lookup " << i << " failed" << endl;
    		}
    	}
    
    	table.start_iterator();
    
    	while (table.has_next())
    	{
    		int key, value;
    		table.next_entry(key, value);
    
    		cout << key << " : " << value << endl;
    	}
    	table.end_iterator();
    
    	return 0;
    }
    


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值