哈希表

来源:互联网 发布:美国大非农数据公布时间 编辑:程序博客网 时间:2024/05/21 06:01

哈希表:不同的Key值经过哈希函数Hash(Key)处理以后可能产生相同的值哈希地址,我们称这种情况为哈希冲突。所以用哈希冲突的开链法(哈希桶)进行处理,其结构如下:

wKiom1cx1Imzr3sxAAAjmbzKkKc289.png

代码如下:

#define _CRT_SECURE_NO_WARNINGS 1#include<iostream>#include<vector>using namespace std;template<class k,class v>struct HashTableNode{k _key;v _value;HashTableNode<k, v>* _next;HashTableNode<k,v>(const k& key, const v& value) //构造函数:_key(key), _value(value), _next(NULL){}   HashTableNode()    //构造无参函数:_key(0), _value(0), _next(NULL){}};template<class k, class v>class HashTable{typedef HashTableNode<k, v> Node;public:HashTable<k,v>():_size(0), _tables(NULL){}HashTable<k,v>(const HashTable<k,v>& ht)  //拷贝构造函数{_tables.resize(ht._size);_size = ht._size;for (size_t i = 0; i < _size; i++){Node* cur1 = ht._tables[i];Node* cur2 = NULL;while (cur1){if (_tables[i] == NULL){   //当链表为空,则开辟新节点,并将地址返回给_tables[i]_tables[i] = new Node(cur1->_key, cur1->_value);cur2 = _tables[i];}else{  //其他情况则将新开辟的节点地址返回给cur2的nextcur2->_next = new Node(cur1->_key, cur1->_value);}cur1 = cur1->_next;}}}~HashTable(){    if (_size != 0){for (size_t i = 0; i < _size; i++){Node* del = _tables[i];while (del) //del不为空,则将del后的节点删除{Node* next = del->_next;delete del;del = next;_size--;}_tables[i] = NULL;}}}HashTable<k, v> &operator=(HashTable<k, v> ht)   //现代写法{   //函数传参时会构造一个对象,此时只需将对象中的_tables和_size相互交换就行了             if (this != &ht){if (&ht != this){swap(_tables, ht._tables);swap(_size, ht._size);}return *this; }}bool Insert(const k& key, const v& value){if (_size == _tables.size()){_CheckExpand();  //先进行检查容量,如若不够则需扩容}size_t index = _HashFunc(key); //将下标赋值给indexNode* begin = _tables[index];while (begin){if (begin->_key == key){return false; //查找key,如若有则返回false}begin = begin->_next;}Node* tmp = new Node(key, value);tmp->_next = _tables[index];_tables[index] = tmp;_size++;return true;}size_t _HashFunc(const k&key)  //返回key所在的下标{return key%_tables.size();}void _CheckExpand()   //检查扩容{size_t newsize = _GetNextPrime();if (newsize == _size)//若果当前容量等于newsize,函数返回{return;}vector<Node*> newTables;newTables.resize(newsize); //开辟newsize大小的容量for (size_t i = 0; i < _tables.size(); i++){  //将空间的每个节点都初始化Node* cur = _tables[i];while (cur){Node* tmp = cur;cur = cur->_next;size_t index = _HashFunc(tmp->_key);tmp->_next = newTables[index];newTables[index] = tmp;}_tables[i] =NULL;}_tables.swap(newTables);}size_t  _GetNextPrime()  //定义28个素数表,因为素数有利于降低载荷因子{static 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 (int i = 0; i < _PrimeSize; i++){if (_PrimeList[i]> _tables.size()){return _PrimeList[i];}}return _PrimeList[_PrimeSize - 1];}Node* Find(const k& key)     //查找节点 并返回该节点地址{size_t index = _HashFunc(key);Node* cur = _tables[index];while (cur){if (cur->_key == key){return cur;}cur = cur->_next;}return NULL;}bool Remove(const k& key)    //删除某个节点{size_t index = _HashFunc(key);Node* cur = _tables[index];Node* prev = NULL;while (cur){if (cur->_key == key){break;}prev = cur;cur = cur->_next;}if (cur == _tables[index]){_tables[index] = cur->_next;return true;}else{prev->_next = cur->_next;delete cur;return true;}return false;}void PrintTables(){printf("哈希表如下:\n");for (size_t i = 0; i < _tables.size(); i++){Node* cur = _tables[i];while (cur){ /*cout << cur->_key << " ";cur = cur->_next;*/printf("[%d]=%c & %d  ", i, cur->_value,cur->_key);cur = cur->_next;if (cur==NULL){printf("\n");}}}printf("\n");}protected:size_t _size;vector<Node*> _tables;};测试代码如下:void Test(){   typedef HashTableNode<int, char> Node;    HashTable<int, char> ht;ht.Insert(1, 'a');ht.Insert(2, 'b');ht.Insert(3, 'c');ht.Insert(4, 'd');ht.Insert(5, 'e');ht.Insert(54, 'x');ht.Insert(55, 'y');ht.Insert(56, 'z');ht.PrintTables();HashTable<int, char> ht2;ht2.Insert(54, 'x');ht2.Insert(55, 'y');ht2.Insert(56, 'z');ht2.Insert(1, 'a');ht2.Insert(2, 'b');ht2.Insert(3, 'c');ht2.Insert(4, 'd');ht2.Insert(5, 'e');ht2.PrintTables();ht=ht2;ht.PrintTables();/*Node* ret = ht.Find(55);cout << ret->_value << endl;*//*ht.Remove(4);ht.PrintTables();*//*HashTable<int, char> ht1(ht);ht1.PrintHashTable();*/}int main(){Test();system("pause");return 0;}


本文出自 “零点时光” 博客,请务必保留此出处http://10741764.blog.51cto.com/10731764/1771939

0 0