本篇文章給大家分享的是有關java數據結構中哈希表的線性探測算法是什么,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
構造哈希表常用的方法是:
除留余數法--取關鍵值被某個不大于散列表長m的數p除后的所得的余數為散列地址。HashKey= Key % P。
直接定址法--取關鍵字的某個線性函數為散列地址HashKey= Key 或 HashKey= A*Key + BA、B為常數。
我在這里主要使用一下除留余數法Hash(key) =Key%P,(P這里是哈希表的長度)p最好是素數考慮降低哈希沖突的原因,我并沒有在這上面過于追究此處哈希表長度10,見線性探測圖。
哈希表經常遇到的一個問題就是哈希沖突。
哈希沖突是什么呢?哈希沖突指的是:不同的關鍵字經過相同的哈希函數映射到相同的的哈希地址處。
要解決哈希沖突閉散列方法主要有兩個:線性探測與二次探測。
在這里,我將線性探測的原理用下圖表述:
線性探測
線性探測代碼如下:
#define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> using namespace std; #include<string> //線性探測的特化處理可以處理自定義類型的數據 enum State { EMPTY,//該位置未存放元素 DELETE,//該位置元素已被刪除 EXIST,//該位置存在元素 }; //處理基本類型 template<class K> struct DefaultFuncer { size_t operator()(const K& key) { return key; } }; //處理自定義類型 template<> struct DefaultFuncer<string> { size_t value = 0; size_t operator()(const string& str) { for (int i = 0; i < str.size(); i++) { value += str[i]; } return value; } }; template<class K, template<class>class HashFuncer = DefaultFuncer> class HashTable { public: HashTable() :_size(0) , _capacity(0) , _state(NULL) , _table(NULL) {} HashTable(size_t size) :_size(0) , _capacity(size) , _state(new State[size]) , _table(new K[size]) { for (int i = 0; i < _capacity; i++)//全部狀態初始化成EMPTY { _state[i] = EMPTY; } } //線性探測計算出元素存放位置(假設不哈希沖突) int _HashFunc(const K& key) { HashFuncer<K> hf; return hf(key) % _capacity; //匿名對象調用operator() /*return HashFuncer<K>()(key) % _capacity;*/ } void Swap(HashTable<K> tmp) { swap(_size, tmp._size); swap(_capacity, tmp._capacity); swap(_state, tmp._state); swap(_table, tmp._table); } void _CheckCapacity() { HashTable<K> tmp(2*_capacity); for (int i = 0; i < _capacity; i++) { tmp.Insert(_table[i]); } Swap(tmp); } bool Insert(const K& key) { //靜態哈希表 /*if (_size == _capacity) { cout<<"HashTable is full!"<<endl; return false; }*/ //動態哈希表 //高效哈希表的載荷因子大概穩定在0.7-0.8較好 if (10 * _size >= 7 * _capacity) { _CheckCapacity(); } int index = _HashFunc(key); while (_state[index] == EXIST) { index++; if (index == _capacity) { index = 0; } } _table[index] = key; _state[index] = EXIST; _size++; return true; } int Find(const K& key) { int index = _HashFunc(key); while (_state[index] == EXIST || _state[index]== DELETE) //while(_state[index] != EMPTY) //空狀態找不到,非空狀態找得到 { if (_table[index] == key && _state[index] == EXIST) { return index; } ++index; if (index == _capacity) { index = 0; } } return -1; } bool Remove(const K& key) { int index = Find(key); if (index != -1) { _state[index] = DELETE; --_size; return true; } return false; } void PrintTable() { for (int i = 0; i < _capacity; i++) { if (_state[i] == EXIST ) { cout << i << "(EXIST):" << _table[i] << endl; } /*我將DELETE狀態元素也打印出來,便于觀察。 而Insert處理時,DELETE狀態下的位置可以插上新的元素*/ else if (_state[i] == DELETE) { cout << i << "(DELETE):" << _table[i] << endl; } else { cout << i << "(EMPTY):" << _table[i] << endl; } } } private: size_t _size;//實際存放元素個數 size_t _capacity;//哈希表長度 State* _state; K* _table; }; //POD(基本類型)的測試用例 void TestHashTablePOD() { HashTable<int> ht(10); ht.Insert(89); ht.Insert(18); ht.Insert(49); ht.Insert(58); ht.Insert(9); ht.PrintTable(); int ret = ht.Find(89); cout << ret << endl; ht.Remove(89); ht.PrintTable(); ht.Remove(18); ht.PrintTable(); } //自定義類型的測試用例 void TestHashTable() { HashTable<string,DefaultFuncer> ht(10); ht.Insert("信息化"); ht.Insert("時代"); ht.Insert("電腦"); ht.Insert("測試工程師"); ht.PrintTable(); int ret = ht.Find("測試工程師"); cout << ret << endl; ht.Remove("電腦"); ht.PrintTable(); ht.Remove("時代"); ht.PrintTable(); } int main() { TestHashTable(); system("pause"); return 0; }
以上就是java數據結構中哈希表的線性探測算法是什么,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。