哈希表及其應用

散列表(Hash table,也叫哈希表),是根據關鍵碼值(Key value)而直接進行訪問的數據結構。也就是說,它經過把關鍵碼值映射到表中一個位置來訪問記錄,以加快查找的速度。這個映射函數叫作散列函數,存放記錄的數組叫作散列表java

給定表M,存在函數f(key),對任意給定的關鍵字值key,代入函數後若能獲得包含該關鍵字的記錄在表中的地址,則稱表M爲哈希(Hash)表,函數f(key)爲哈希(Hash) 函數。c++

散列函數能使對一個數據序列的訪問過程更加迅速有效,經過散列函數,數據元素將被更快地定位。數組

1. 直接尋址法:取關鍵字或關鍵字的某個線性函數值爲散列地址。即H(key)=key或H(key) = a·key + b,其中a和b爲常數(這種散列函數叫作自身函數)。若其中H(key)中已經有值了,就往下一個找,直到H(key)中沒有值了,就放進去。數據結構

2. 數字分析法:分析一組數據,好比一組員工的出生年月日,這時咱們發現出生年月日的前幾位數字大致相同,這樣的話,出現衝突的概率就會很大,可是咱們發現年月日的後幾位表示月份和具體日期的數字差異很大,若是用後面的數字來構成散列地址,則衝突的概率會明顯下降。所以數字分析法就是找出數字的規律,儘量利用這些數據來構造衝突概率較低的散列地址。函數

3. 平方取中法:當沒法肯定關鍵字中哪幾位分佈較均勻時,能夠先求出關鍵字的平方值,而後按須要取平方值的中間幾位做爲哈希地址。這是由於:平方後中間幾位和關鍵字中每一位都相關,故不一樣關鍵字會以較高的機率產生不一樣的哈希地址。code

4. 摺疊法:將關鍵字分割成位數相同的幾部分,最後一部分位數能夠不一樣,而後取這幾部分的疊加和(去除進位)做爲散列地址。數位疊加能夠有移位疊加和間界疊加兩種方法。移位疊加是將分割後的每一部分的最低位對齊,而後相加;間界疊加是從一端向另外一端沿分割界來回摺疊,而後對齊相加。htm

5. 隨機數法:選擇一隨機函數,取關鍵字的隨機值做爲散列地址,一般用於關鍵字長度不一樣的場合。get

6. 除留餘數法:取關鍵字被某個不大於散列表表長m的數p除後所得的餘數爲散列地址。即 H(key) = key MOD p,p<=m。不只能夠對關鍵字直接取模,也可在摺疊、平方取中等運算以後取模。對p的選擇很重要,通常取素數或m,若p選的很差,容易產生同義詞。hash

哈希衝突解決方法io

解決哈希衝突方法有許多,可分爲開放定址法和拉鍊法兩大類。

1. 開放尋址法:Hi=(H(key) + di) MOD m,i=1,2,…,k(k<=m-1),其中H(key)爲散列函數,m爲散列表長,di爲增量序列,可有下列三種取法:

1.1. di=1,2,3,…,m-1,稱線性探測再散列;

1.2. di=1^2,-1^2,2^2,-2^2,⑶^2,…,±(k)^2,(k<=m/2)稱二次探測再散列;

1.3. di=僞隨機數序列,稱僞隨機探測再散列。

2. 再散列法:Hi=RHi(key),i=1,2,…,k RHi均是不一樣的散列函數,即在同義詞產生地址衝突時計算另外一個散列函數地址,直到衝突再也不發生,這種方法不易產生「彙集」,但增長了計算時間。

3. 鏈地址法(拉鍊法)

4. 創建一個公共溢出區

例子:

1.採用除留餘數法(H(key)=key %n)創建長度爲n的哈希表,處理衝突用鏈地址法。創建鏈表的時候採用尾插法。

#include<stdio.h>

struct hash

{

    int key;

    int count;

}h[100];

int c=1;

void insert(int hashn,int x)

{

    int adr,i;

    adr=x%hashn;

//表示此地址沒有被佔用

    if(h[adr].key==-1)

    {

        h[adr].key=x;

        h[adr].count=1;

    }

    else

    {

        i=1;

        do

        {

            i++;

            adr=(adr+1)%hashn;

        }

        while(h[adr].key!=-1);

            h[adr].key=x;

        h[adr].count=i;

    }

}

void create(int hashn,int keyn,int a[])

{

    int i;

    for(i=0;i<hashn;i++)

    {

        h[i].key=-1;

        h[i].count=0;

    }

    for(i=0;i<keyn;i++)

        insert(hashn,a[i]);

}

int search(int hashn,int key)

{

    int adr;

    adr=key%hashn;

    while(h[adr].key!=key)

    {

        adr=(adr+1)%hashn;

        c++;

        if(c==hashn+1)

            return -1;

    }

    return adr;

}

int main()

{

    int hashn,keyn,key,a[100],loca;

    int i;

    scanf("%d%d",&hashn,&keyn);

    for(i=0;i<keyn;i++)

        scanf("%d",&a[i]);

    scanf("%d",&key);

    create(hashn,keyn,a);

    loca=search(hashn,key);

    if(loca==-1)

        printf("-1");

    else

        printf("%d,%d",loca,c);

    return 0;

}
相關文章
相關標籤/搜索