Hash算法:雙重散列


  雙重散列線性開型尋址散列開放尋址法)中的沖突解決技術。雙重散列使用在發生沖突時將第二個散列函數應用於的想法。

  此算法使用:

     (hash1(key) + i * hash2(key)) % TABLE_SIZE 

  來進行雙哈希處理。hash1()hash2() 是哈希函數,而 TABLE_SIZE 是哈希表的大小。當發生碰撞時,我們通過重復增加 步長i 來尋找鍵。

  第一個Hash函數:hash1(key) = key % TABLE_SIZE

1     /**
2      * 計算首次的Hash值
3      *
4      * @param key
5      * @return
6      */
7     private int hash1(int key) {
8         return (key % TABLE_SIZE);
9     }

  第二個Hash函數是:hash2(key) = PRIME – (key % PRIME),其中 PRIME 是小於 TABLE_SIZE 的質數

1     /**
2      * 發生碰撞是時繼續計算Hash值
3      *
4      * @param key
5      * @return
6      */
7     private int hash2(int key) {
8         return (PRIME - (key % PRIME));
9     }

  第二個Hash函數表現好的特征:

  • 絕對不會產生 0 索引

  • 能在整個HashTable 循環探測

  • 計算會快點

  • 與第一個Hash函數互相獨立

  • PRIME 與 TABLE_SIZE 是 “相對質數”

  

Java實現代碼:

  1 package algorithm.hash;
  2 
  3 /**
  4  *  雙重哈希
  5  */
  6 public class DoubleHash {
  7     private static final int TABLE_SIZE = 13;   // 哈希表大小
  8     private static int PRIME = 7;               // 散列函數值
  9 
 10     private int[] hashTable;
 11     private int curr_size;                      // 當前表中存的元素
 12 
 13     public DoubleHash() {
 14         this.hashTable = new int[TABLE_SIZE];
 15         this.curr_size = 0;
 16         for (int i = 0; i < TABLE_SIZE; i++)
 17             hashTable[i] = -1;
 18     }
 19 
 20     private boolean isFull() {
 21         return curr_size == TABLE_SIZE;
 22     }
 23 
 24     /**
 25      * 計算首次的Hash值
 26      *
 27      * @param key
 28      * @return
 29      */
 30     private int hash1(int key) {
 31         return (key % TABLE_SIZE);
 32     }
 33 
 34     /**
 35      * 發生碰撞是時繼續計算Hash值
 36      *
 37      * @param key
 38      * @return
 39      */
 40     private int hash2(int key) {
 41         return (PRIME - (key % PRIME));
 42     }
 43 
 44     /**
 45      * 向Hash表中存值
 46      *
 47      * @param key
 48      */
 49     private void insertHash(int key) {
 50         /* 表是否已滿 */
 51         if (isFull()) {
 52             return;
 53         }
 54 
 55         /* 獲取首次的Hash值 */
 56         int index = hash1(key);
 57 
 58         // 如果發生碰撞
 59         if (hashTable[index] != -1) {
 60             /* 計算第二次的Hash值 */
 61             int index2 = hash2(key);
 62             int i = 1;
 63             while (true) {
 64                 /* 再次合成新的地址 */
 65                 int newIndex = (index + i * index2) % TABLE_SIZE;
 66 
 67                 // 如果再次尋找時沒有發生碰撞,把key存入表中的對應位置
 68                 if (hashTable[newIndex] == -1) {
 69                     hashTable[newIndex] = key;
 70                     break;
 71                 }
 72                 i++;
 73             }
 74         } else {
 75             // 一開始沒有發生碰撞
 76             hashTable[index] = key;
 77         }
 78         curr_size++;    // Hash表中當前所存元素數量加1
 79     }
 80 
 81     /**
 82      * 打印Hash表
 83      */
 84     private void displayHash() {
 85         for (int i = 0; i < TABLE_SIZE; i++) {
 86             if (hashTable[i] != -1)
 87                 System.out.println(i + " --> " + hashTable[i]);
 88             else
 89                 System.out.println(i);
 90         }
 91     }
 92 
 93     public static void main(String[] args) {
 94         int[] a = {19, 27, 36, 10, 64};
 95 
 96         DoubleHash doubleHash = new DoubleHash();
 97         for (int i = 0; i < a.length; i++)
 98             doubleHash.insertHash(a[i]);
 99 
100         doubleHash.displayHash();
101     }
102 
103 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM