简单算法养成(二)---hash算法

147 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第5天 点击查看活动详情

散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。

hash算法在runtime中运用的还是比较频繁的,比如找cache_t 缓存列表里的函数等,下面就简单通过一个例子来说说,hash算法是如何运用的。

使用HASH算法找到字符串中第一个只出现一次的字符

比如有个字符串,aabbccddegh,如何去找到第一个只出现一次的字符 『e』?

废话先不多说,上代码!

char findFirstChar(char* cha){
    
    char result = '\0';
    
    //定义一个数组,用来存储各个字母出现的次数
    int array[256];
    
    //对数组进行初始化操作
    for(int i = 0; i < 256 ; i++){
        array[i] = 0;
    }
    //定义一个指针 指向当前字符串头部
    char*p = cha;
    
    // 遍历每个字符
    while (*p != '\0'){
        // 在字母对应存储位置,进行出现次数+1操作
        // array['a'] = array['a'] + 1
        array[*p]++;
        p++;
    }
    
    // 将p指针重新指向字符串头部
    p = cha;
    
    // 遍历每个字母出现的次数
    while(*p != '\0'){
        // 遇到第一个出现次数为1的字符 打印结果
        if (array[*p] == 1){
            result = *p;
            break;
        }
        
        // 反之继续向后遍历
        p++;
    }
    return  result;
}

接下来我们来详细说说

第一步

     //定义一个数组,用来存储各个字母出现的次数
    int array[256];
    
    //对数组进行初始化操作
    for(int i = 0; i < 256 ; i++){
        array[i] = 0;
    }

这个是定义一个长度为256的数组,并将数组的每一位初始化为0。

为什么是256的长度呢?

因为根据 ASCII码有128个,ASCII扩展码有128个,合计256个。

为什么要都初始化为0呢?

这个0是代表出现次数,初始化的时候,这些ASCII码出现的次数都是0次。


第二步

 //定义一个指针 指向当前字符串头部
    char*p = cha;
    
    // 遍历每个字符
    while (*p != '\0'){
        // 在字母对应存储位置,进行出现次数+1操作
        // array['a'] = array['a'] + 1
        array[*p]++;
        p++;
    }

定义一个指针 指向当前字符串头部,开始循环找到ASCII码在数组中出现的位置,并将次数+1,然后移动指针。

其实这一步是关键。

举个栗子,

就像地上摆256个桶子,每个桶子上贴着ASCII码标签(比如 第65个桶贴着『A』标签,第66个桶贴着『B』标签),然后我们从左往右看给的字符串aabbccddegh,第一个『a』,所以应该在贴着『a』标签的桶里放一根箭,第二个也是『a』,然后再在贴着『a』标签的桶里方一根箭,以此类推。

这样子,就将给定字符串中,每个字符对应的桶里,都加上了箭,箭的个数就是这每个字符出现的次数。

p++就是表示,指针向后移动一位。

第三步

 // 将p指针重新指向字符串头部
    p = cha;
    
    // 遍历每个字母出现的次数
    while(*p != '\0'){
        // 遇到第一个出现次数为1的字符 打印结果
        if (array[*p] == 1){
            result = *p;
            break;
        }
        
        // 反之继续向后遍历
        p++;
    }

这一步比较好理解,就是重新循环这个数组array,看数组中哪个桶里箭的个数是1,就将这个桶找出来,并返回。

这样就完成了这个题的解法。

我们在结合文章开头的定义,

它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度

不难发现,前面的第二步就是完成关键码映射到数组动的动作。


结语

希望通过这个简单的算法,来加深大家对hash的了解。

大家可以下载一下,自己试试 用xcode写算法

大家觉得不错的话,不妨点个赞👍🏻