嵌入式学习---哈希表

1.哈希表(Hash table),也被称为散列表,是一种根据关键值(Key value)而直接进行访问的数据结构。它通过把关键值映射到表中的一个位置来访问记录,从而加快查找的速度。这个映射函数被称为散列函数或哈希函数,而存放记录的数组则被称为散列表或哈希表。

基本概念
散列函数:将任意长度的输入(称为预映射或pre-image)通过散列算法变换成固定长度的输出,该输出即为散列值或哈希值。这个转换过程是一种压缩映射,不同的输入可能会映射到相同的输出。
散列表:用于存放通过散列函数处理后的记录的数组。


工作原理
哈希表的基本工作原理是将关键字(Key)通过哈希函数转换为一个整型数字(哈希值),然后将该数字对数组长度进行取余操作,取余结果作为数组的下标,将对应的值(Value)存储在该下标对应的数组空间中。当进行查找时,再次使用哈希函数将关键字转换为对应的数组下标,并直接定位到该空间获取值。

2.哈希表处理冲突
由于哈希表的特殊性质,不同的关键字可能会映射到相同的散列地址,这种现象称为哈希冲突。处理冲突的方法主要有以下几种:

1.开放寻址法:当发生冲突时,使用某种探测序列在散列表中查找一个空闲的位置,并将记录存入。
2.再散列法:当发生冲突时,使用另一个散列函数计算新的散列地址,直到冲突不再发生。
3.链地址法:将具有相同散列地址的记录存储在同一个链表中,每个散列地址对应一个链表

3.使用后哈希表存储数据的优缺点

优点

1.快速访问:哈希表通过哈希函数将关键字映射到数组的一个索引位置,从而实现快速的数据访问。在平均情况下,哈希表的查找、插入和删除操作的时间复杂度都是O(1),即常数时间复杂度。

2.高效的空间利用率:相比于其他需要维持数据顺序的数据结构(如链表、树),哈希表在存储相同数量的元素时,通常能够占用更少的空间。这是因为哈希表通过哈希函数直接定位元素的存储位置,避免了元素之间的额外空间浪费。

3.灵活性:哈希表支持动态扩容,当元素数量超过当前容量的一定比例时,可以自动增加容量并重新计算哈希值,从而避免性能下降。此外,哈希表也支持删除操作,可以灵活地管理数据。

适用范围广:哈希表广泛应用于各种场景,包括缓存、数据去重、计数、快速查找等。

缺点

1.冲突问题:由于哈希函数的输出范围有限,而输入范围可能很大,因此不同的关键字可能会映射到相同的索引位置,即发生冲突。虽然可以通过各种冲突解决方法(如开放寻址法、链地址法等)来处理冲突,但这些方法可能会增加哈希表的查找、插入和删除操作的时间复杂度。

2.哈希函数的选择:哈希表的性能很大程度上取决于哈希函数的选择。一个好的哈希函数应该尽可能减少冲突的发生,并且具有较快的计算速度。然而,找到一个完美的哈希函数是非常困难的,因为不同的应用场景对哈希函数的要求也不同。

3.扩容和重新哈希的代价:当哈希表的元素数量超过当前容量的一定比例时,需要进行扩容并重新计算所有元素的哈希值。这个过程可能会比较耗时,并且需要额外的内存空间来存储新的哈希表。

4.数据无序:哈希表中的数据是无序的,即无法直接通过索引来遍历哈希表中的元素。如果需要遍历哈希表中的所有元素,通常需要额外的数据结构(如链表)来记录元素的顺序。

5.空间浪费:虽然哈希表在大多数情况下能够高效地利用空间,但在某些情况下可能会浪费一些空间。例如,当哈希表的负载因子(已填充元素与总容量的比例)较低时,哈希表中可能会存在大量的空闲空间。此外,如果哈希表的容量设置得过大,也可能会导致空间的浪费。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#ifndef _HASH_H
#define _HASH_H

#define HASH_SIZE 27

typedef struct per
{
    char name[32];
    char tel[32];
}HSDataTYpe;

typedef struct hsnode
{
    HSDataTYpe data;
    struct hsnode *pnext;
}HSNode_t;

extern int hash_function(char key);
extern int insert_hashtable(HSDataTYpe data);
extern void printf_hashtable();
extern HSNode_t *serch_hashtable(char *name);
extern void destory_hashtable();
#endif

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 insert_hashtable(HSDataTYpe data)
{
    int addr = hash_function(data.name[0]);
    HSNode_t *pnode = malloc(sizeof(HSNode_t));
    if(NULL == pnode)
    {
        perror("fail malloc");
        return -1;
    }

    pnode->data = data;
    pnode->pnext = NULL;
    
    if(hashtable[addr] == NULL)
    {
        hashtable[addr] = pnode;
        return -1;
    }
    pnode->pnext = hashtable[addr];
    hashtable[addr] = pnode;
}
int main(int argc,char *argv[])
{
    HSDataTYpe pers[] = {{"zhangsan","110"},
                        {"lisi","120"},
                        {"wanger","911"},
                         {"zhaowu","12306"}};
    insert_hashtable(pers[0]);
    insert_hashtable(pers[1]);
    insert_hashtable(pers[2]);
    insert_hashtable(pers[3]);

    printf_hashtable();
    
    HSNode_t * p = serch_hashtable("zhangsan");
    if(p ==NULL)
    {
        return -1;
    }
    printf("%s  %s \n",p->data.name,p->data.tel);
    destory_hashtable();
    
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值