数据结构--------哈希表

哈希表(Hash Table),也称为散列表,是一种特殊的数据结构,它允许通过关键码值(key-value)进行快速查找、插入和删除操作。以下是哈希表的详细学习笔记:

一、基本概念

  1. 哈希表:根据关键码值而直接进行访问的数据结构,通过哈希函数将关键字映射到表中的一个位置,以便快速访问。
  2. 哈希函数:也称为散列函数,是哈希表的映射函数,它可以把任意长度的输入(关键字)变换成固定长度的输出(哈希值),用于确定数据在表中的存储位置。
  3. 哈希冲突(哈希碰撞):不同的关键字通过同一个哈希函数可能得到同一哈希值的现象,导致它们被映射到表中的同一位置。

二、哈希函数的设计

设计哈希函数的目标是尽量减少哈希冲突的发生,常见的哈希函数设计方法包括:

  1. 直接定址法:取关键字的某个线性函数值为哈希地址,如Hash(key) = a*key + b(a、b为常数)。
  2. 除留余数法:以关键码除以p的余数作为哈希地址,通常取p为小于等于哈希表长度m的质数,如Hash(key) = key mod p
  3. 平方取中法:先通过求关键字平方值的方式扩大相近数之间的差别,然后根据表长度取关键字平方值的中间几位数为哈希地址。
  4. 折叠法:将关键字分割成位数相等的几部分(最后一部分位数可以短些),然后将这几部分叠加求和,并按哈希表表长,取后几位作为哈希地址。
  5. 随机数法:选择一个随机函数,取关键字的随机函数值为哈希地址。

三、哈希冲突的处理

当哈希冲突发生时,需要采用适当的方法解决,以保证数据的正确存储和快速访问。常见的哈希冲突处理方法包括:

  1. 开放地址法(Open Addressing)
    • 线性探测法:当哈希地址冲突时,依次探测下一个地址,直到找到空地址或探测到表尾。
    • 二次探测法:当哈希地址冲突时,按照二次方序列进行探测,以减小聚集现象。
    • 双重散列法:使用多个哈希函数,当第一个哈希函数发生冲突时,使用第二个哈希函数计算新的地址。
  2. 链地址法(Chaining)
    • 将具有相同哈希地址的元素存储在同一个链表中,即哈希表的每个槽位指向一个链表的头节点。当发生冲突时,只需在对应的链表中进行插入或查找操作。
#include <stdio.h>
#include "hash.h"
#include <stdlib.h>
#include <string.h>

HSnode_t *hashtable[HASH_SIZE]= {NULL};

int hash_function(char key)
{
    if(key >='a'&&key <='z')
    {
        return key-'a';
    }
    else if(key>='A'&&key<='Z')
    {
        return key-'A';
    }
    else 
    {
        return HASH_SIZE-1;
    }
}
int inser_hashtable(HSDataType data)
{
    int addr = hash_function(data.name[0]);
    HSnode_t *p =(HSnode_t *)malloc(sizeof(HSnode_t));
    if(NULL == p)
    {
        perror("fail malloc");
        return -1;
    }
    p->data = data;
    if(hashtable[addr]==NULL)
    {
        p->pnext =NULL;
        hashtable[addr]=p;
        return 0;
    }

    p->pnext = hashtable[addr]->pnext;
    hashtable[addr]->pnext=p;
    return 0;

}
HSnode_t *find_hash(char *name)
{
    int addr =hash_function(name[0]);
    HSnode_t *p =hashtable[addr];
    if(p == NULL)
    {
        return NULL;
    }
    while(p!=NULL)
    {
        if(strcmp(p->data.name,name)==0)
        {
            break;
        }
        p=p->pnext;
    }
    printf("%s %s\n",p->data.name,p->data.tel);
    return p;
}
int printf_hash()
{
    for(int i=0;i<27;++i)
    {
        HSnode_t *p = hashtable[i];
        while(p!=NULL)
        {
            printf("%s %s\n",p->data.name,p->data.tel);
            p=p->pnext;
        }
    }
    return 0;
}
void destroy_hash()
{
    for(int i=0;i<27;++i)
    {
        HSnode_t *p = hashtable[i];
        while(p!=NULL)
        {
            free(p);
            p=p->pnext;
        }
    }
    return;
}

四、哈希表的应用

哈希表由于其快速查找、插入和删除的特性,在许多领域都有广泛应用,如:

  • 数据库索引:通过哈希表可以快速定位到数据库中的记录。
  • 缓存系统:利用哈希表实现快速缓存访问,提高数据访问速度。
  • 编程语言实现:许多编程语言中的字典(Dictionary)、映射(Map)等数据结构都是基于哈希表实现的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值