標籤:雜湊
雜湊表/散列表,是根據關鍵字(key)直接存取在記憶體儲存位置的資料結構。
構造雜湊表的常用方法:
-
直接地址法---取關鍵字的某個線性函數為散列地址,Hash(Key) = Key或Hash(key) = A*Key + B,
A,B為常數。
-
除留餘數法---取關索引值被某個不大於散列表長m的數p除後的所得的餘數為散列地址。
Hash(key) = key % p。
若採用直接地址法(Hash(Key) = Key)存在一定的缺陷。
當Key值特別大時,而Key之前的數很少,就會造成空間浪費。大多時候採取除留餘數法。
雜湊衝突/雜湊碰撞
不同的Key值經過雜湊函數Hash(Key)處理以後可能產生相同的雜湊地址,我們稱這種情況為雜湊衝突。任何的散列函數都不能避免產生衝突。
散列表的載荷因子定義為a = 填入表中元素的個數/散列表的長度
載荷因子越大,衝突的可能性就越大。
解決衝突的辦法:
(1)線性探測
650) this.width=650;" src="http://s5.51cto.com/wyfs02/M00/80/E8/wKiom1dEOC3AwU7_AAAgmRPnoLI040.png" style="float:none;" title="1.PNG" alt="wKiom1dEOC3AwU7_AAAgmRPnoLI040.png" />
(2)二次探測
650) this.width=650;" src="http://s5.51cto.com/wyfs02/M01/80/E8/wKiom1dEOC3hxQKcAAAhTSAbGWM948.png" style="float:none;" title="2.PNG" alt="wKiom1dEOC3hxQKcAAAhTSAbGWM948.png" />
#pragma once#include <iostream>#include <string>using namespace std;enum State{EMPTY,DELETE,EXITS,};//以key形式實現線性探測template <class T>class HashTable{public:HashTable(T capacity = 10):_tables(new T[capacity]),_states(new State[capacity]),_capacity(capacity),_size(0){for(size_t i=0;i < _capacity;++i){_states[i] = EMPTY;}}~HashTable(){delete[] _tables;delete[] _states;_tables = NULL;_states = NULL;}HashTable(const HashTable<T>& ht) //拷貝構造{_tables = new T[ht._capacity];_states = new State[ht._capacity];for(size_t i=0;i<ht._capacity;++i){if(ht._tables[i] != EMPTY){_tables[i] = ht._tables[i];_states[i] = ht._states[i];}}_capacity = ht._capacity;_size = ht._size;}//HashTable<T>& operator=(const HashTable<T>& ht) //賦值操作符重載//{//if(this != &ht)//{//delete[] _tables;//delete[] _states;//_tables = new T[ht._capacity];//_states = new State[ht._capacity];//for(size_t i=0;i<ht._capacity;++i)//{//if(ht._tables[i] != EMPTY)//{//_tables[i] = ht._tables[i];//_states[i] = ht._states[i];//}//}//_capacity = ht._capacity;//_size = ht._size;//}//return *this;//}//現代寫法HashTable<T>& operator=(HashTable<T> ht) //賦值操作符重載{this->Swap(ht);return *this;}public:bool Insert(const T& key) //插入{_CheckCapacity();size_t index = HashFunc(key);while(_states[index] == EXITS) {if(_tables[index] == key) //冗餘{return false;}++index;if(index == _capacity) //到達雜湊表尾部{index = 0;}}_tables[index] = key;_states[index] = EXITS;++_size;return true;}bool Find(const T& key) //尋找{size_t index = HashFunc(key); size_t start = index;while(_states[index] == EXITS){if(_tables[index] == key) {return true;}++index;if(index == _capacity){index = 0;} if(start == index) //雜湊表查完 { return false; }}return false;}bool Remove(const T& key) //刪除{size_t index = HashFunc(key);size_t start = index;while(_states[index] == EXITS){if(_tables[index] == key){_states[index] = DELETE;return true;}++index;if(index == _capacity) //到達雜湊表的尾部{index = 0;} if(start == index) //雜湊表查完 { return false; }}return false;}public:size_t HashFunc(const T& key) //雜湊函數{return key%10;}void _CheckCapacity() //檢查容量{if(_size*10 % _capacity == 7) //載荷因子{HashTable<T> tmp(2*_capacity);for(size_t i=0;i<_capacity;++i){if(_states[i] == EXITS){tmp.Insert(_tables[i]);}}Swap(tmp);}}void Swap(HashTable<T>& ht){swap(_tables,ht._tables);swap(_states,ht._states);swap(_size,ht._size);swap(_capacity,ht._capacity);}void Print(){for(size_t i=0;i<_capacity;++i){cout<<"["<<_states[i]<<","<<_tables[i]<<"]"<<" ";}cout<<endl;}private:T* _tables; //雜湊表State* _states; //狀態表size_t _size; //資料的個數size_t _capacity; //容量};//以key形式實現二次探測//enum State//{//EMPTY,//DELETE,//EXITS,//};//template <class T>//class HashTableSecond//{//public://HashTableSecond(T capacity = 10)//:_tables(new T[capacity])//,_states(new State[capacity])//,_capacity(capacity)//,_size(0)//{//for(size_t i=0;i < _capacity;++i)//{//_states[i] = EMPTY;//}//}////~HashTableSecond()//{//delete[] _tables;//delete[] _states;//_tables = NULL;//_states = NULL;//}////HashTableSecond(const HashTableSecond& ht) //拷貝構造//{//_tables = new T[ht._capacity];//_states = new State[ht._capacity];//for(size_t i=0;i<ht._capacity;++i)//{//if(ht._tables[i] != EMPTY)//{//_tables[i] = ht._tables[i];//_states[i] = ht._states[i];//}//}//_capacity = ht._capacity;//_size = ht._size;//}////HashTableSecond& operator=(const HashTableSecond& ht) //賦值操作符重載//{//if(this != &ht)//{//delete[] _tables;//delete[] _states;//_tables = new T[ht._capacity];//_states = new State[ht._capacity];//for(size_t i=0;i<ht._capacity;++i)//{//if(ht._tables[i] != EMPTY)//{//_tables[i] = ht._tables[i];//_states[i] = ht._states[i];//}//}//_capacity = ht._capacity;//_size = ht._size;//}//return *this;//}////public://bool Insert(const T& key) //插入//{//_CheckCapacity();//size_t start = HashFunc(key);//size_t index = start;//size_t i = 1;//while(_states[index] == EXITS) //{//if(_tables[index] == key)//{//return false;//}//index = start + i * i;//++i;//index %= _capacity;//}//_tables[index] = key;//_states[index] = EXITS;//++_size;//return true;//}//bool Find(const T& key) //尋找//{//size_t start = HashFunc(key);//size_t index = start;//size_t i = 1;//while(_states[index] == EXITS)//{//if(_tables[index] == key)//{//return true;//}//index = start + i * i;//++i;//index %= _capacity;//}//return false;//}//bool Remove(const T& key) //刪除//{//size_t start = HashFunc(key);//size_t index = start;//size_t i = 1;//while(_states[index] == EXITS)//{//if(_tables[index] == key)//{//_states[index] = DELETE;//return true;//}//index = start + i * i;//++i;//index %= _capacity;//}//return false;//}//public://size_t HashFunc(const T& key) //雜湊函數//{//return key%10;//}////void _CheckCapacity() //檢測容量//{//if(_size*10 % _capacity == 7)//{//HashTableSecond<T> tmp(2*_capacity);//for(size_t i=0;i<_capacity;++i)//{//if(_states[i] == EXITS)//{//tmp.Insert(_tables[i]);//}//}//Swap(tmp);//}//}////void Swap(HashTableSecond<T>& ht)//{//swap(_tables,ht._tables);//swap(_states,ht._states);//swap(_size,ht._size);//swap(_capacity,ht._capacity);//}////void Print()//{//for(size_t i=0;i<_capacity;++i)//{//cout<<"["<<_states[i]<<","<<_tables[i]<<"]"<<" ";//}//cout<<endl;//}//private://T* _tables; //雜湊表//State* _states; //狀態表//size_t _size; //資料的個數//size_t _capacity; //容量//};//以key/value形式實現二次探測,支援字典查詢//enum State//{//EMPTY,//DELETE,//EXITS,//};template <class T,class K>struct HashTableNode //節點{T key;K value;};template <class T>struct __HashFunc //重載(){size_t operator()(const T& key){return key;}};template<>struct __HashFunc<string> //特化{size_t operator()(const string& key){size_t hash = 0;for(size_t i=0;i<key.size();++i){hash += key[i];}return hash;}};template <class T,class K,class HashFunc = __HashFunc<T> >class HashTableSecond{public:HashTableSecond(size_t capacity = 10):_tables(new HashTableNode<T,K>[capacity]),_states(new State[capacity]),_capacity(capacity),_size(0){for(size_t i=0;i < _capacity;++i){_states[i] = EMPTY;}}~HashTableSecond(){delete[] _tables;delete[] _states;_tables = NULL;_states = NULL;}public:bool Insert(const T& key,const K& value) //插入{_CheckCapacity();size_t start = __HashFunc(key);size_t index = start;size_t i = 1;while(_states[index] == EXITS) {if(_tables[index].key == key){return false;}index = start + i * i;++i;index %= _capacity;}_tables[index].key = key;_tables[index].value = value;_states[index] = EXITS;++_size;return true;}HashTableNode<T,K>* Find(const T& key) //尋找{size_t start = __HashFunc(key);size_t index = start;size_t i = 1;while(_states[index] == EXITS){if(_tables[index].key == key){return &(_tables[index]);}index = start + i * i;++i;index %= _capacity;}return NULL;}bool Remove(const T& key) //刪除{size_t start = __HashFunc(key);size_t index = start;size_t i = 1;while(_states[index] == EXITS){if(_tables[index].key == key){_states[index] = DELETE;return true;}index = start + i * i;++i;}return false;}public:size_t __HashFunc(const T& key) //雜湊函數{HashFunc hfun;return hfun(key)%_capacity;} void _CheckCapacity() //檢測容量{if(_size*10 % _capacity == 7){HashTableSecond<T,K> tmp(2*_capacity);for(size_t i=0;i<_capacity;++i){if(_states[i] == EXITS){tmp.Insert(_tables[i].key,_tables[i].value);}}Swap(tmp);}}void Swap(HashTableSecond<T,K>& ht){swap(_tables,ht._tables);swap(_states,ht._states);swap(_size,ht._size);swap(_capacity,ht._capacity);}void Print(){for(size_t i=0;i<_capacity;++i){cout<<"["<<_tables[i].key<<","<<_tables[i].value<<"]"<<" ";}cout<<endl;}private:HashTableNode<T,K>* _tables; //雜湊表State* _states; //狀態表size_t _size; //資料的個數size_t _capacity; //容量};
本文出自 “一起去看星星” 部落格,轉載請與作者聯絡!
雜湊表/散列表