Hash(散列函数)

概念
Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,所以不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。
常用HASH函数
直接取余法:f(x):= x mod maxM ; maxM一般是不太接近 2^t 的一个质数。
乘法取整法:f(x):=trunc((x/maxX)*maxlongit) mod maxM,主要用于实数。
平方取中法:f(x):=(x*x div 1000 ) mod 1000000); 平方后取中间的,每位包含信息比较多。
处理冲突方法
1.开放寻址法;Hi=(H(key) + di) MOD m,i=1,2,…,k(k<=m-1),其中H(key)为散列函数,m为散列表长,di为增量序列,可有下列三种取法:
1). di=1,2,3,…,m-1,称线性探测再散列;
2). di=1^2,(-1)^2,2^2,(-2)^2,(3)^2,…,±(k)^2,(k<=m/2)称二次探测再散列;
3). di=伪随机数序列,称伪随机探测再散列。
2. 再散列法:Hi=RHi(key),i=1,2,…,k RHi均是不同的散列函数,即在同义词产生地址冲突时计算另一个散列函数地址,直到冲突不再发生,这种方法不易产生“聚集”,但增加了计算时间。
3. 链地址法(拉链法)
4. 建立一个公共溢出区
通过查找关键字不需要比较就可以获得需要的记录的存储位置,在记录存储位置和它的关键字之间建立一个确定的关系使得每一个关键对应一个存储位置,查找时,根据这个确定的关系来找到对应的值。记录我们存取的这块空间就是我们所说的表(哈希表)。
优点:
查找简化了比较过程,效率大大的提高。
缺点:
需要找到合适的对应关系,同一种对应关系不一定适合二种情况,移植性不强。而且必须考虑到不同的值对应统一关键字处理。
构造函数
1.计算简单
计算复杂的算法会消耗大量的时间,也会降低效率,这样就不会体现出它本身查找速度快的优点了。
2.2.散列地址均匀
保证空间的有效利用,减少为处理冲突而消耗的时间。
总结:
散列表是一种非常高效的查找数据结构,在原理上也与前面的查找不尽相同,它回避了关键字直接反复比较的繁琐。应该说,散列表对于那种查找性能要求比较高的,记录之间关系无要求的数据有非常好的适用性。在学习中要注意的是散列函数的选择和处理冲突的方法。

简单的对冲突进行处理,代码如下:

#include 
#include 
#include
#define SUCCESS 1
#define UNSUCCESS 0
#define HASHSIZE 12
#define NULLKEY -32768
#define OK 1
typedef struct
{
    int *elem;
    int count;

}HashTable;
int m = 12;
//初始化散列表
void InitHashTable(HashTable *H)
{
    int i;
    m = HASHSIZE;
    H->elem = (int *)malloc(m * sizeof(int) );
    for(i = 0; i < m; i++)
        H->elem[i] = NULLKEY;
//  return 0;
}
//散列函数
int Hash(int key)
{
    return key % m;
}
//插入关键字进散列表
void InsertHash(HashTable *H, int key)
{
    int addr = Hash(key); //求散列地址
    int di = rand();
    while(H->elem[addr] != NULLKEY)
        addr = (addr + di) % m;
    H->elem[addr] = key;
}
//散列表查找关键字
bool SearchHash(HashTable H, int key, int *addr)
{
    *addr = Hash(key);
    while(H.elem[*addr] != key)
    {
        *addr = (*addr + 1) % m;
        if(H.elem[*addr] == NULLKEY || *addr == Hash(key))
        {
            return UNSUCCESS;
        }
    }
    return SUCCESS;
}

HashTable hash;

int main()
{
    int addr;
    InitHashTable(&hash);
    InsertHash(&hash,25);
    InsertHash(&hash,37);
    InsertHash(&hash,15);
    InsertHash(&hash,16);
    InsertHash(&hash,48);
    InsertHash(&hash,67);
    InsertHash(&hash,56);
    InsertHash(&hash,22);
    InsertHash(&hash,47);
    printf("%d\n",SearchHash(hash,223,&addr));
}

你可能感兴趣的:(C语言,算法总结,学习笔记)