散列表查找实现

1.散列表查找算法实现

首先是需要定义一个散列表的结构和一些相关的函数。其中HashTable就是散列表结构,结构当中的elem为一个动态数组。

#define SUCCESS 1
#define UNSUCCESS 0
#define HASHSIZE 12  //定义散列表长为数组的长度
#define NULLKEY -32768

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;  //除留余数法
}

初始化完成后,我们可以对散列表进行插入操作。假设我们插入的关键字集合为{12,67,56,16,25,37,22,29,15,47,48,34}。

/* 插入关键字进散列表 */
void InsertHash(HashTable *H, int key)
{
    int addr = Hash(key);  //求散列地址
    while (H->elem[addr] != NULLKEY) //如果不为空,则冲突
        addr = (addr+1) % m ;    //开放定址法的线性探测
    H->elem[addr] = key;    //直到有空位后插入关键字
}

代码中插入关键字时,首先算出散列地址,如果当前地址不为空关键字,则说明有冲突。此时我们应用开放定址法的线性探测进行重新寻址。

散列表存在后,我们在需要时就可以通过散列表查找记录。

/* 散列表查找关键字 */
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))
        {  //如果循环回到原点
            return UNSUCCESS;   //则说明关键字不存在
        }
    }
    return SUCCESS;
}

查找的代码如插入的非常类似,只需做一个不存在关键字的判断而已。

2.散列表查找性能分析

如果没有冲突,散列查找是所有查找中效率最高的,为O(1),可惜只是如果。

散列查找的平均查找长度影响因素有:

1.散列函数是否均匀,散列函数的好坏直接决定着出现冲突的频繁程度。

2.处理冲突的方法,处理方法不同,也会影响平均查找长度。比线性探测处理冲突可能会产生堆积,不如二次探测法;而链地址探测法不会产生任何堆积。

3.散列表的装填因子。所谓的装填因子α=填入表中的记录个数/散列表长度。α越大则产生冲突的可能性就越大。通常将散列表的空间设置得比查找集合大,虽然浪费了一定的空间,但是得到了较高的查找效率。

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值