哈希存储、哈希表、哈希表的基本操作、算法的一些概念

我要成为嵌入式高手之3月25日数据结构第七天!!
—————————————————————————————

搜索(查找)二叉树

思想:左大右小

主要为了进行二分查找,由于根节点选择不合适,容易造成树不平衡,故产生了平衡二叉树

哈希存储(散列存储)

为了快速定位数据

哈希表

哈希冲突 / 哈希矛盾

关键字不一样,但是映射之后结果一样

如何避免 哈希矛盾?

1、重新设计哈希函数,尽可能均匀散列分布在哈希表

2、开放定址法:向下寻找未存储的位置进行存放数据

3、链地址法: 将数据链表的首地址存入哈希表,只需将数据结点往链表后链接即可

1、创建哈希表

HASH_NODE *hash_table[HASH_SIZE] = {NULL};

2、设计哈希函数

int HashFun(char ch)
{
    if (ch >= 'a' && ch <= 'z')
    {
        return ch - 'a';
    }
    else if (ch >= 'A' && ch <= 'Z')
    {
        return ch - 'A';
    }
    else
    {
        return HASH_SIZE-1;
    }
}

3、数据插入哈希表

int InsertHashTable(DATA_TYPE data)
{
    HASH_NODE *pnode = malloc(sizeof(HASH_NODE));
    if (NULL == pnode)
    {
        perror("fail to malloc pnode");
        return -1;
    }
    pnode->data = data;
    pnode->pnext = NULL;

    int addr = HashFun(data.name[0]);

    if (IsEmpty(addr))
    {
        hash_table[addr] = pnode;
    }
    else
    {
        pnode->pnext = hash_table[addr];
        hash_table[addr] = pnode;
    }
}

4、数据查找

int SearchInHashTable(char *tmpname)
{
    HASH_NODE *ptmp = NULL;

    int addr = HashFun(tmpname[0]);
    if (IsEmpty(addr))
    {
        printf("查无此人!\n");
        return -1;
    }
    else
    {
        ptmp = hash_table[addr];
        while (ptmp != NULL)
        {
            if (!strcmp(ptmp->data.name, tmpname))
            {
                printf("该人的信息如下:\n");
                printf("name: %s\n tel: %s\naddr: %s\n", ptmp->data.name, ptmp->data.tel, ptmp->data.addr);
                return 0;
            }
            else
            {
                ptmp = ptmp->pnext;
            }
        }
        printf("查无此人!\n");
        return -1;
    }
}

5、销毁哈希表

int DestroyHashTable()
{
    HASH_NODE *ptmp = NULL;
    HASH_NODE *pfree = NULL;

    int addr = 0;
    for (addr =0; addr < HASH_SIZE; ++addr)
    {
        if (IsEmpty(addr))
        {
            continue;
        }
        ptmp = hash_table[addr];
        while (ptmp != NULL)
        {
            pfree = ptmp;
            ptmp = ptmp->pnext;
            free(pfree);
        }
    }
}

6、遍历

void SearchAll()
{
    HASH_NODE *ptmp = NULL;
    int i = 0;
    
    for (i = 0; i < HASH_SIZE; ++i)
    {
        if (IsEmpty(i))
        {
            continue;
        }
        else
        {
            ptmp = hash_table[i];
            while (ptmp != NULL)
            {
                printf("name[%d]: %s\n", i, ptmp->data.name);
                ptmp = ptmp->pnext;
            }
        }
    }
}

总程序:

main.c

#include "hash.h"

int main()
{
    DATA_TYPE pers[4] = {
        {"zhangsan", "110", "xian"},
        {"lisi", "120", "beijing"},
        {"wangwu", "119", "guangzhou"},
        {"liuqi", "12315", "shenzhen"},
    };

    InsertHashTable(pers[0]);
    InsertHashTable(pers[1]);
    InsertHashTable(pers[2]);
    InsertHashTable(pers[3]);

    char  tmp[32] = {0};
    printf("请输入要查找的人的名字: ");
    fgets(tmp, sizeof(tmp), stdin);
    tmp[strlen(tmp)-1] = '\0';
    SearchInHashTable(tmp);
    printf("==============================\n");

    SearchAll();

    DestroyHashTable();

    return 0;
}

hash.c

#include "hash.h"

HASH_NODE *hash_table[HASH_SIZE] = {NULL};

int HashFun(char ch)
{
    if (ch >= 'a' && ch <= 'z')
    {
        return ch - 'a';
    }
    else if (ch >= 'A' && ch <= 'Z')
    {
        return ch - 'A';
    }
    else
    {
        return HASH_SIZE-1;
    }
}

int IsEmpty(int addr)
{
    if (hash_table[addr] == NULL)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

int InsertHashTable(DATA_TYPE data)
{
    HASH_NODE *pnode = malloc(sizeof(HASH_NODE));
    if (NULL == pnode)
    {
        perror("fail to malloc pnode");
        return -1;
    }
    pnode->data = data;
    pnode->pnext = NULL;

    int addr = HashFun(data.name[0]);

    if (IsEmpty(addr))
    {
        hash_table[addr] = pnode;
    }
    else
    {
        pnode->pnext = hash_table[addr];
        hash_table[addr] = pnode;
    }
}

void SearchAll()
{
    HASH_NODE *ptmp = NULL;
    int i = 0;
    
    for (i = 0; i < HASH_SIZE; ++i)
    {
        if (IsEmpty(i))
        {
            continue;
        }
        else
        {
            ptmp = hash_table[i];
            while (ptmp != NULL)
            {
                printf("name[%d]: %s\n", i, ptmp->data.name);
                ptmp = ptmp->pnext;
            }
        }
    }
}

int SearchInHashTable(char *tmpname)
{
    HASH_NODE *ptmp = NULL;

    int addr = HashFun(tmpname[0]);
    if (IsEmpty(addr))
    {
        printf("查无此人!\n");
        return -1;
    }
    else
    {
        ptmp = hash_table[addr];
        while (ptmp != NULL)
        {
            if (!strcmp(ptmp->data.name, tmpname))
            {
                printf("该人的信息如下:\n");
                printf("name: %s\n tel: %s\naddr: %s\n", ptmp->data.name, ptmp->data.tel, ptmp->data.addr);
                return 0;
            }
            else
            {
                ptmp = ptmp->pnext;
            }
        }
        printf("查无此人!\n");
        return -1;
    }
}

int DestroyHashTable()
{
    HASH_NODE *ptmp = NULL;
    HASH_NODE *pfree = NULL;

    int addr = 0;
    for (addr =0; addr < HASH_SIZE; ++addr)
    {
        if (IsEmpty(addr))
        {
            continue;
        }
        ptmp = hash_table[addr];
        while (ptmp != NULL)
        {
            pfree = ptmp;
            ptmp = ptmp->pnext;
            free(pfree);
        }
    }
}

hash.h

#ifndef _HASH_H
#define _HASH_H

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

#define HASH_SIZE 27

typedef struct per
{
    char name[32];
    char tel[32];
    char addr[64];
}DATA_TYPE;

typedef struct hasnode
{
    DATA_TYPE data;
    struct hasnode *pnext;
}HASH_NODE;

extern int HashFun(char ch);
extern int IsEmpty(int addr);
extern int InsertHashTable(DATA_TYPE data);
extern void SearchAll();
extern int SearchInHashTable(char *tmpname);
extern int DestroyHashTable();


#endif

算法

解决特定问题求解步骤

算法的设计

1、正确性

        语法正确

        合法的输入能得到合理的结果

        对非法的输入,给出满足要求的规格说明;对精心选择,甚至刁难的测试都能正常运行,结果正确

2、可读性

        便于交流,阅读,理解,高内聚,低耦合

3、健壮性

        输入非法数据,能进行相应的处理,而不是产生异常

4、高效率

        时间复杂度

        执行这个算法所花时间的度量

将数据量增长和时间增长用函数表示出来,这个函数就叫做时间复杂度

一般用大O表示法:O(n) —— 时间复杂度是关于数据n的一个函数,随着n的增加,时间复杂度增长较慢的算法时间复杂度低

时间复杂度的计算规则

        1,用常数1 取代运行时间中的所有加法常数

        2,在修改后的运行函数中,只保留最高阶项。

        3,如果最高阶存在且系数不是1,则去除这个项相乘的常数。

5、低储存

         空间复杂度

  • 11
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
哈希表是一种常用的数据结构,它通过哈希函数将键映射到存储位置,以实现高效的数据查找和插入操作。哈希函数是一种提取数据特征的算法,根据不同的数据形式和场景,可以选择不同的哈希算法。常见的哈希算法包括MD5等。\[1\] 在哈希表中,哈希函数的优劣直接影响到哈希表的查找效率。优秀的哈希函数可以减少冲突的发生,提高查找效率。哈希函数的设计方法有多种,其中常见的包括直接寻址法、除留余数法、平方取中法等。不同的哈希函数适用于不同的数据类型和规律。\[3\] 哈希冲突是指不同的键经过哈希函数计算后得到相同的哈希值,导致数据存储位置冲突的情况。为了解决哈希冲突,常用的方法有开放寻址法和链地址法。开放寻址法是指当发生冲突时,通过一定的规则在哈希表中寻找下一个可用的位置来存储数据。链地址法是指在哈希表的每个位置上维护一个链表,将哈希值相同的键值对存储在同一个链表中。\[2\] 总结来说,哈希表是一种通过哈希函数将键映射到存储位置的数据结构,常用的哈希算法有多种,哈希函数的设计方法也有多种,而哈希冲突的处理方法包括开放寻址法和链地址法。这些算法数据结构的选择取决于具体的应用场景和需求。 #### 引用[.reference_title] - *1* [详解哈希数据结构,手写哈希表](https://blog.csdn.net/CRMEB/article/details/120820682)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [数据结构哈希表以及常用哈希算法表达(含全部代码)](https://blog.csdn.net/weixin_53050357/article/details/126666617)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [哈希表-数据结构(C语言)](https://blog.csdn.net/weixin_44681349/article/details/124782035)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值