散列表,英文叫做Hash Table,因此也叫哈希表,是一種根據關鍵字值來確定主存中存儲位置的數據結構.通過一個散列函數(關於鍵值的函數),來確定存儲該關鍵字的位置.
主要的方法有: 1.分離鏈接法(拉鏈法)
分離鏈接法的散列函數為 position = key % n. 即關鍵字的存儲位置為關鍵字的值對表項的數量取模.若表項大小為13,對於關鍵值為27的項,存儲在1(27 % 13 = 1)的表項處.為了減少沖突,n往往取素數.對於同余的關鍵字,采用 隊列(鏈表) 的方式連接在一起,新放入的元素放入隊頭或者隊尾均可.用圖描述如下:
2.線性探查法
線性探查法是根據沖突次數,來從目標位置後移沖突次數次位置來避免沖突的,即position_new = (position + i) % n,其中i為沖突次數,n為表項大小.
3.平方探查法
與線性探查法類似,只不過是散列函數的不同,其position_new = (position + i2 ) % n
4. 雙散列,再散列等
分離鏈接法的數據結構的數據結構的構造,使用一個名為HashTable的類來封裝整個表的操作和屬性.用vector<deque<int>>來表示整個數據結構,即整個表是一個由(雙端)
隊列組成的向量(數組).類中還包含其他的函數,用來訪問類中的私有屬性.
類的聲明如下:
1 class HashTable { 2 public: 3 HashTable(int = 11); 4 ~HashTable() = default; 5 int getHashItemSize(const int) const; //獲得隊列長度 6 int getHashTableSize() const; //獲得表項的大小 7 bool insertRecord(int); //插入一個值 8 void removeRecord(const int); //刪除一個值 9 bool isEmpty() const; //判斷哈希表是否為空 10 void print() const; //打印哈希表 11 12 private: 13 vector<deque<int>> HashItem; //結構定義 14 int HashTableSize = 0; //哈希表表項數 15 };
構造函數定義:
1 HashTable::HashTable(int n) //構造函數定義 2 { 3 HashTableSize = n; 4 5 for (int i = 0; i < n; ++i) 6 { 7 deque<int> adeque; 8 HashItem.push_back(adeque); //向向量中壓入足夠的空隊列 9 } 10 }
插入記錄的函數的定義:
1 bool HashTable::insertRecord(int data) //插入一個指定值的記錄 2 { 3 int position = data % HashTableSize; //映射規則 4 5 if (position >= HashTableSize || position < 0) //合法性判斷 6 return false; 7 8 else 9 { 10 HashItem.at(position).push_front(data); //根據時間局部性原理,插入到隊頭 11 return true; 12 } 13 }
刪除記錄的函數定義
1 void HashTable::removeRecord(const int aim) //刪除一個指定值的記錄 2 { 3 int i = 0; 4 int j = 0; 5 6 for (; i < HashTableSize; ++i) //遍歷表項 7 { 8 9 for (j = 0; j < static_cast<int>(HashItem.at(i).size()); ++j) //遍歷隊列 10 { 11 if (HashItem.at(i).at(j) == aim) 12 HashItem.at(i).erase(HashItem.at(i).begin() + j); //刪除記錄 13 } 14 } 15 16 }
打印函數:
1 void HashTable::print() const 2 { 3 for (int i = 0; i < getHashTableSize(); ++i) //遍歷表項 4 { 5 deque<int> temp = HashItem.at(i); 6 7 for (auto &j : temp) //遍歷隊列 8 cout << j << ' '; 9 10 cout << endl; 11 } 12 }
對於主函數,寫了一點測試語句來進行測試:
1 int main() 2 { 3 HashTable hashtable(13); 4 5 for (int i = 0; i < 100; ++i) 6 hashtable.insertRecord(i); 7 8 hashtable.print(); 9 10 cout << endl; 11 12 hashtable.removeRecord(91); 13 hashtable.removeRecord(70); 14 15 hashtable.print(); 16 17 return 0; 18 }
插入0到99的關鍵字,散列到表項大小為13的散列表中,在刪除91和70兩個關鍵值.
運行結果輸出了0到99的散列情況和刪除操作之後的散列情況:
本人原創,轉載請注明出處,謝謝合作!