1. 程式人生 > >雜湊表查詢(Java)

雜湊表查詢(Java)

雜湊(雜湊表)

1.基本思想:將關鍵字 (資料項)被對映到從0到Tablesize-1這個範圍中的某個數,並且被放到適當的單元中。其中這個對映就叫做雜湊函式

0 H(Ki) Tablesize1

如圖:




2.衝突:將兩個不同的關鍵字對映到同一表的位置。如圖:

用雜湊函式將關鍵字對映到雜湊表中(發生衝突的情況)

3.構造雜湊函式的兩個標準:(1)簡單並且能快速計算;(2)能在地址中獲取鍵的均部分。

4.構造雜湊函式的幾種常見方法:
 (1)平均取中法:具體做法是先通過關鍵字的平方值擴大相近數的差別,然後根據表長度取中間的幾位數作為雜湊值。
  例如:將一組關鍵字(0100,0110,1010,1001,0111)平方後得(0010000,0012100,1020100,1002001,0012321)若取表長為1000,則可取中間的三位數作為雜湊地址集:(100121,201,020,123)。

 (2)除餘法:用關鍵字除以一個不大於雜湊表長度m的正整數p(素數)所得的餘數作為雜湊地址的一種方法。

h(key) = key % p

 (3)摺疊法:根據雜湊表長將關鍵字儘可能分成若干段,然後將這幾段的值相加,並將最高位的進位捨去,所得結果即為其雜湊地址。
  例如:有一組關鍵字(4766934, 5656975, 4685673, 3547807,7569664),將這些數拆成2位,4位和1位數,然後再把它們相加,如下圖:


摺疊法位移構造雜湊函式示意圖

4.解決雜湊衝突
 4.1開放定址法:當衝突發生時,按照某種方法探測表中的其他儲存單元,直到找到空位置為止。
H
i
= (H(key)+di) % m (i=1,2,...k(k m1)

  (1)線性探測法:di = 1,2,3,...,m1
  (2)二次探查法:di = 12,22,32,42,...,k2
  (3)雙重雜湊法 : 一旦發生衝突, 應用第二個雜湊函式以獲取備用位置。
 4.2連結串列法:將所有關鍵字為同義詞的結點連結在同一個單鏈表中。

5.雜湊查詢的Java實現:
“`Java
/**
* 雜湊查詢的演算法的實現
*
* {1,3,66,56,34,67,343,77,31,64,0,5,6,32,55,23,56}採用雜湊表存放 用除餘法構建雜湊函式 用連結串列法解決雜湊衝突
*
* @author zww
*
*/
public class HashTableSearch {
/* 雜湊結點 */
private static class Node {
int key; // 連結串列中的鍵
Node next; // 下一個同義詞
}

/* 在雜湊表中查詢關鍵字key */
public boolean HashSearch(int[] data, int key) {
    int p = 1;
    // 尋找小於或等於最接近表長的素數
    for (int i = data.length; i > 1; i--) {
        if (isPrimes(i)) {
            p = i;
            break;
        }
    }
    // 構建雜湊表
    Node[] hashtable = createHashTable(data, p);
    // 查詢key是否在雜湊表中
    int k = key % p;
    Node cur = hashtable[k];
    while (cur != null && cur.key != key) {
        cur = cur.next;
    }
    if (cur == null) {
        return false;
    } else {
        return true;
    }

}

/*用求餘,連結串列法構建雜湊表*/
public Node[] createHashTable(int[] data, int p) {
    Node[] hashtable = new Node[p];
    int k;        //雜湊函式計算的單元地址
    for (int i = 0; i < data.length; i++) {
        Node node = new Node();
        node.key = data[i];
        k = data[i] % p;
        if (hashtable[k] == null) {
            hashtable[k] = node;
        }else {
            Node current = hashtable[k];
            while(current.next != null) {
                 current = current.next;
            }
            current.next = node;
        }
    }
    return hashtable;
}

public boolean isPrimes(int n) {
    for(int i = 2; i <= Math.sqrt(n); i++ ) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}

}

“`