標籤:方法 key back src 運行 組成 ack strong 記錄
散列表,英文叫做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的散列情況和刪除操作之後的散列情況:
本人原創,轉載請註明出處,謝謝合作!
[C++]實現散列表的分離連結法的資料結構