C语言中哈希表的使用(一)

该篇博客详细介绍了哈希表的实现原理,通过一个C语言的例子展示了如何创建、插入、查找和删除哈希表中的键值对。哈希表使用链表解决冲突,并通过特定的哈希函数确定元素存储位置。示例代码中还包含了打印和清理哈希表的功能。
摘要由CSDN通过智能技术生成

1:哈希表

哈希表是链表的一个变种。可以这么理解,一个数组放了n个指针,每个指针指向一个链表。存储的数据以key:value的形式保存。 通过key的经过一些规则可以计算出存在数组的那个位置。再遍历这个位置的链表来value的值。

2:示例

/*******************************************************************************
  * @file          hash.c
  * @verison       v1.0.0
  * @copyright     COPYRIGHT © 2020 CSG
  * @author        ShiYanKai
  * @date:         2021-08-11
  * @brief
  * @bug
  * - 2021-08-11  SYK Created
*******************************************************************************/

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

#define MAX_TABLE_SIZE 100
/*hash 节点*/
typedef struct HashNode{
    char *key;
    int value;
    struct HashNode *nextNode;
}HashNode;

/*hash 整个表,有一个数组存放了每个由节点组成的链表的位置*/
typedef struct HashTable{
    HashNode *hashNode[MAX_TABLE_SIZE];
    int currentIndex;
}HashTable;

/*初始化整个表*/
void InitHashTable(HashTable *hashTable)
{
    memset(hashTable->hashNode, 0, sizeof(HashNode *) * MAX_TABLE_SIZE);
    hashTable->currentIndex = 0;
}
/*一个规则:key转换成一个long型数据,用于确定存放在表中的那个位置*/
unsigned long HashFun(const char *key)
{
    unsigned long hash = 0;
    int len = strlen(key);
    for(int i = 0; i < len; i++)
    {   
        hash = hash * 33 + key[i];
    }   

    return hash;
}
/*插入一个新的key:value数据*/
void Insert(HashTable *hashTable, char *key, int value)
{
    int pos = HashFun(key) % MAX_TABLE_SIZE;//通过计算的key转化的值与表的大小取余,来确定存储的位置
    /*下面是创建个新节点,把key和value都存在这个节点中*/
    HashNode *newNode = (HashNode *)malloc(sizeof(HashNode));
    newNode->nextNode = NULL;
    newNode->key = (char *)malloc(sizeof(char) * (strlen(key) + 1));
    strcpy(newNode->key, key);
    newNode->key[strlen(key)] = 0;
    newNode->value = value;
	/*把新节点插入到表中去*/
    HashNode *p = hashTable->hashNode[pos];
    if(p == NULL)//如果这个位置未空就直接插入
    {
        hashTable->hashNode[pos] = newNode;
        hashTable->currentIndex++;
        return;
    }
	/*key的值已成存在,就覆盖写入value*/
    if(strcmp(p->key, key) == 0)
    {
        p->value = value;
        return;
    }
	/*通过下面,把节点查到第二个节点的位置,这里对节点的顺序没有要求*/
    HashNode *q = p->nextNode;
    newNode->nextNode = q;
    p->nextNode = newNode;
}
 /*通过给定的key,来找到表中的value。 没找到就返回NULL*/
int *Get(HashTable *hashTable, char *key)
{
    int pos = HashFun(key) % MAX_TABLE_SIZE;
    HashNode *p = hashTable->hashNode[pos];
    if (NULL == p)
    {
        return NULL;
    }
    else
    {
        HashNode *q = p;
        while(q != NULL)
        {
            if(0 == strcmp(q->key, key))
            {
                return &(q->value);
            }
            q = q->nextNode;

        }
        return NULL;
    }
}
 /*把表中名为key的节点删掉*/
int Dorp(HashTable *hashTable, char *key)
{   
    int pos = HashFun(key) % MAX_TABLE_SIZE;
    HashNode *p = hashTable->hashNode[pos];
    if (NULL == p)
    {   
        return 0;
    }
    else
    {   
        if(0 == strcmp(p->key, key))
        {   
            hashTable->hashNode[pos] = p->nextNode;
            free(p->key);
            free(p);
            return 1;
        }
        
        HashNode *q = p->nextNode;
        HashNode *last = p;
        while(NULL != q)
        {   
            
            if(0 == strcmp(q->key, key))
            {   
                last->nextNode = q->nextNode;
                free(q->key);
                free(q);
                return 1;
            }
            last = q;
            q = q->nextNode;
        }
        return 0;
    }
}
 /*打印表中的信息*/
void PrintHashTable(HashTable *hashTable)
{   
    for(int i = 0; i < MAX_TABLE_SIZE; i++)
    {   
        HashNode *head = hashTable->hashNode[i];
        if(head == NULL)
            continue;
        
        printf("\n数组下标:%d ==>", i);
        printf("(%s:%d)", head->key, head->value);
        head = head->nextNode;
        while(head)
        {
            printf("-->(%s:%d)", head->key, head->value);
            head = head->nextNode;
        }
    }
}
/*清空整个表*/
void clearHashTable(HashTable *hashTable)
{
    for (int i = 0; i < MAX_TABLE_SIZE; i++)
    {
        HashNode *head = hashTable->hashNode[i];
        while(head)
        {
            HashNode *temp = head->nextNode;
            free(head->key);
            free(head);
            head = temp;
        }
    }
}

int main()
{
    HashTable *hashTable = (HashTable *)malloc(sizeof(HashTable));
    InitHashTable(hashTable);
    Insert(hashTable, "1234", 1);
    Insert(hashTable, "11234", 1);
    Insert(hashTable, "hello", 2);
    Insert(hashTable, "word", 3);
    Insert(hashTable, "kayshi", 100);
    Insert(hashTable, "c", 1223);
    Insert(hashTable, "c+=", 321);
    Insert(hashTable, "abc", 34);
    Insert(hashTable, "fdg", 44);
    Insert(hashTable, "adgg", 89);
    Insert(hashTable, "67687", 1233);
    Insert(hashTable, "qaz", 1);
    Insert(hashTable, "wsx", 2);
    Insert(hashTable, "edc", 3);
    Insert(hashTable, "rfv", 4);
    Insert(hashTable, "tgb", 5);
    Insert(hashTable, "yhn", 6);
    Insert(hashTable, "ujm", 7);
    PrintHashTable(hashTable);
    int *data = Get(hashTable, "kayshi");
    printf("\ndata == %d\n", *data);
    Dorp(hashTable, "kayshi");
    PrintHashTable(hashTable);
    clearHashTable(hashTable);
    free(hashTable);
}

3:结果

yankaishi@zx-dev:~/test/hash$ gcc hash.c 
yankaishi@zx-dev:~/test/hash$ ./a.out 

数组下标:6 ==>(wsx:2)
数组下标:8 ==>(hello:2)
数组下标:11 ==>(yhn:6)
数组下标:20 ==>(ujm:7)
数组下标:21 ==>(tgb:5)
数组下标:27 ==>(11234:1)
数组下标:30 ==>(rfv:4)
数组下标:37 ==>(kayshi:100)
数组下标:44 ==>(word:3)
数组下标:66 ==>(abc:34)
数组下标:78 ==>(67687:1233)
数组下标:80 ==>(qaz:1)
数组下标:81 ==>(fdg:44)
数组下标:88 ==>(edc:3)
数组下标:91 ==>(c+=:321)-->(adgg:89)
数组下标:98 ==>(1234:1)
数组下标:99 ==>(c:1223)
data == 100

数组下标:6 ==>(wsx:2)
数组下标:8 ==>(hello:2)
数组下标:11 ==>(yhn:6)
数组下标:20 ==>(ujm:7)
数组下标:21 ==>(tgb:5)
数组下标:27 ==>(11234:1)
数组下标:30 ==>(rfv:4)
数组下标:44 ==>(word:3)
数组下标:66 ==>(abc:34)
数组下标:78 ==>(67687:1233)
数组下标:80 ==>(qaz:1)
数组下标:81 ==>(fdg:44)
数组下标:88 ==>(edc:3)
数组下标:91 ==>(c+=:321)-->(adgg:89)
数组下标:98 ==>(1234:1)
数组下标:99 ==>(c:1223)
yankaishi@zx-dev:~/test/hash$
  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值