hash查找

查找算法中 hash查找是最快的.但是它需要先构造hash表,构造hash表之后利用hash函数在hash表中查找的速度是非常迅速的 所以时间复杂度是O(1)

最常用的构造散列函数的方法是: 除留余数法
F(key) = key mod P (P <= M)
散列表的长度是M, 通常p为小于或等于表长(最好接近于m)的最小质数,或不包含小于20质因子的合数.

hash表的生成和查找都会存在冲突问题, 解决冲突的方法有很多,这里采用 开放定址法即线性探测法
Fi(key) = ( F(key) + Di ) mod M (Di = 1,2,3,4,…,M-1)

c语言代码如下
//hash表的生成和查找 
//hash函数是 除留余数法
//冲突采用 开放定址法 线性探测 
#include<stdio.h>
#include<stdlib.h> 

#define ERROR 0
#define OK 1
#define HASHSIZE 12
#define NULLKEY -32768  //初始化的默认值 
#define arr_length(array) (sizeof(array) / (sizeof(array[0])))  //定义一个宏 求数组长度 

typedef int Status; 
typedef struct{
    int *elem;  //数据元素的存储基址 
    int count;  //当前数据元素的个数 
} HashTable;

int m = 0;  //散列表长度

//初始化 散列表
Status initHashTable(HashTable *H){
    int i;
    m = HASHSIZE;
    H->count = m;
    H->elem = (int *)malloc(m * sizeof(int));   //在堆中开辟空间 
    for(i = 0; i < m; i++){
        H->elem[i] = NULLKEY;   //初始化数据 
    }
    return OK;
}

//散列函数 计算散列地址 
int hash(int key){
    return key % m; //除留余数法 
} 

//插入关键字进散列表
void insertHash(HashTable *H, int key){
    int addr = hash(key);   //求散列地址
    while(H->elem[addr] != NULLKEY){    //冲突产生了. 
        addr = (addr + 1) % m;  //开放定址法 线性探测 
    } 
    H->elem[addr] = key;    //如果有空位插入关键字 
} 

//散列表查找关键字 用*addr返回 
Status 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)){ //循环回到原点 说明关键字不存在 
            printf("查找的关键字不存在\n");
            return ERROR; 
        }
    }
    return OK;
}

//遍历
void traverse(HashTable H, int len) {
    if(len <= 0){
        printf("长度不合法\n");
        return ;
    } 
    int i = 0;
    for(i; i < len; i++){
        printf("%d ", H.elem[i]);       
    }
    printf("\n");
}

int main(void){
    int array[12] = {12,67,56,16,25,37,22,29,15,47,48,34};
    HashTable H;
    initHashTable(&H);
    printf(" 1.初始化散列表\n 2.插入散列值\n 3.查找\n 4.遍历\n 0.退出\n");
    int option = 1, key;
    int i, length, addr, res; 
    while(option){
        scanf("%d", &option);
        switch(option){
            case 1:
                res= initHashTable(&H);
                if(res == OK){
                    printf("初始化成功!\n");
                } 
                break;
            case 2:
                initHashTable(&H);
                length = arr_length(array);
                for(i = 0; i < length; i++){
                    insertHash(&H, array[i]);
                }
                printf("插入成功\n");
                break;
            case 3:
                printf("请输入要超找的关键字\n");
                scanf("%d", &key);
                res = searchHash(H, key, &addr); 
                if(res == OK){
                    printf("查找成功  关键字的下标是 %d\n", addr);
                }
                break;
            case 4:
                length = arr_length(array);
                traverse(H, length);
                break;
            case 0:
                return OK; 
            default:
                printf(" 1.初始化散列表\n 2.插入散列值\n 3.查找\n 4.遍历\n 0.退出\n");
                break; 
        }
    } 
    return 0;
}

上述代码产生的hash表如下

下标01234567891011
关键字122537151629486756342247
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值