散列表(开放寻址法)

散列表是一种搜索算法,它可以跟据各个元素的值来确定存储位置,然后将位置保管在散列表中,从而实现数据的高速搜索。器中散列表是一种数据结构,能对包含关键字的数据集合高效的执行插入,搜索,删除操作。

散列表由容纳m个元素的数组T,以及跟据关键字决定数组下标的函数共同组成,也就是说,我们要将数据的关键字输入该函数,由该函数决定数据在数组中的位置。

h(k)称为散列函数,该函数的返回值成为散列值,散列函数求出的值范围为0至m-1之间(m为数组T的长度)。为了满足这一条件,函数内使用取余运算,保证输出值为0至m-1之间的整数。

h(k)=kmodm

就是这么一种散列函数,会产生不同key对应同一散列值的情况,即出现“冲突”。

开放寻址法是解决这类问题的常用手段

在双散列结构中一旦出现冲突,程序会调用第二个散列函数来求散列值

H(k)=h(k,i)=(h1(k)+i*h2(k))modm

散列函数h(k,i)拥有关键字k和整数i两个参数,这里的i是发生冲突后计算下一个散列值的次数。也就是说,只要散列函数H(K)起了冲突,就会依次调用h(k,0),h(k,1),h(k,2)....,直到不发生冲突为止,然后返回这个h(k,i)的值作为散列值。

要注意的是,因为下标每次移动h(k)个位置,所以必须保证T的长度m与h2(k)互质,否则会出现无法生成下标的情况,这种时候,我们可以特意让m为质数,然后取一个小于m的值作为h2(k),从而避免上述情况发生。


扫描二维码关注公众号,回复: 1069025 查看本文章
int h1(int key)
{
    return key%m;
}

int h2(int key)
{
    return 1+(key%(m-1));
}

int h(int key,int i)
{
    return (h1(key)+i*h2(key))%m;
}

int insert(int key)
{
    int i=0;
    while(true){
        j=h(key,i);
        if(t[j]==NIL){//来判断当前位置是否为空
            t[j]=key;
            return j;
        }else{
            i=i+1;
        }
    }
}

int search(int key)
{
    i=0;
    while(true){
        j=h(key,i);
        if(t[j]==key){
            return j;
        }else if(t[i]==NIL||i>=m){
            return NIL;
        }else{
            i=i+1;
        }
    }
}

散列表用途不同会用到各种算法(比如加密技术),有时候还会用到启发式搜索。

例题:AOJ ALDS1_4C:Dictionary

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;

const int m=1046527;
const int NIL=-1;
const int l=14;

typedef long long LL;

char H[m][l];

int getchar(char ch)
{
    if(ch=='A'){
        return 1;
    }else if(ch=='C'){
        return 2;
    }else if(ch=='G'){
        return 3;
    }else if(ch=='T'){
        return 4;
    }else{
        return 0;
    }
}

LL getkey(char str[])
{
    LL sum=0,p=1;
    int len=strlen(str);
    for(int i=0;i<len;i++){
        sum+=p*(getchar(str[i]));
        p*=5;
    }
    return sum;
}

int h1(int key)
{
    return key%m;
}

int h2(int key)
{
    return 1+(key%(m-1));
}

int find(char str[])
{
    LL key;
    key=getkey(str);
    for(int i=0;;i++){
        int h=(h1(key)+i*h2(key))%m;
        if(strcmp(H[h],str)==0){
            return 1;
        }else if(strlen(H[h])==0){
            return 0;
        }
    }
    return 0;
}

int insert(char str[])
{
    LL key;
    key=getkey(str);
    for(int i=0;;i++){
        int h=(h1(key)+i*h2(key))%m;
        if(strcmp(H[h],str)==0){
            return 1;
        }else if(strlen(H[h])==0){
            strcpy(H[h],str);
            return 0;
        }
    }
    return 0;
}

int main()
{
    int n;
    char str[l],com[9];
    for(int i=0;i<m;i++){
        H[i][0]=0;
    }
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%s %s",com,str);
        if(com[0]=='i'){
            insert(str);
        }else{
            if(find(str)){
                printf("yes\n");
            }else{
                printf("no\n");
            }
        }
    }
    return 0;
}
/*
6
insert AAA
insert AAC
find AAA
find CCC
insert CCC
find CCC
*/


猜你喜欢

转载自blog.csdn.net/zhouzi2018/article/details/80302659