简单HashTable的C语言实现

简单HashTable的实现,编程语言C

相关头文件和预处理

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

#define HASH_SIZE 10 //定义hashtable的桶的大小
#define list_for_table \ //用于循环遍历hashtable
    for(i = 0; i < HASH_SIZE; i++)
typedef unsigned int uint;

相关结构体定义

struct hash_node //定义hashtable的节点
{
    char *key; //char*的key
    uint value; //无符号整型的值字段
    struct hash_node *next;
};

struct hash_table //定义hashtable
{
    struct hash_node *bucket; //定义hash桶
    int number; //hashtable内的节点数
};

Hash函数采用的是BKDR, 附上参考链接

static uint bkdr_hash(char *p)
{
    uint seed, hash;
    seed = 131, hash = 0;
    while(*p != '\0')
        hash = hash * seed + (*p++);
    return hash;
}

static uint key_to_index(char *key)
{
    uint bdkr_hash, index;
    bdkr_hash = bkdr_hash(key);
    index = bdkr_hash % (HASH_SIZE - 1);
    return index;
}

Hash基本操作

/*
 * Descrition: 分配hash节点函数
 * @i: 如果分配一个,那么i设置1
 */
static struct hash_node *malloc_node(uint i)
{
    return (struct hash_node *)malloc(sizeof(struct hash_node) * i);
}

/*
 * Description: 哈希表的初始化
 */
static struct hash_table *hash_init()
{
    struct hash_table *t;
    t = (struct hash_table *)malloc(sizeof(struct hash_table));
    t->bucket = malloc_node(HASH_SIZE);
    memset(t->bucket, 0, sizeof(struct hash_node) * HASH_SIZE);
    return t;
}

/*
 * Description: 哈希表的打印
 * @t: 待打印的哈希表的地址
 */
static void hash_display(struct hash_table *t)
{
    int i;
    struct hash_node *pos;
    printf("the num of the  element of this table is %d\n", t->number);
    list_for_table
    {
        pos = t->bucket + i;
        if(!pos) continue;
        pos = pos->next;
        printf("Bucket[%d]:\n", i);
        while(pos)
        {
            printf("  key=%-10svalue=%-10d\n", pos->key, pos->value);
            pos = pos->next;
        }
    }
}

/*
 * Description: 哈希表的释放
 * @t: 待释放的哈希表的地址
 */
static void hash_free(struct hash_table *t)
{
    int i;
    struct hash_node *pos, *tmp;
    list_for_table
    {
        pos = t->bucket + i;
        if(!pos) continue;
        pos = pos->next;
        while(pos)
        {
            tmp = pos->next;
            pos->key = NULL;
            free(pos);
            pos = tmp;
        }
    }
    free(t);
}

/*
 * Description: 哈希表的插入函数
 * @key: char *, key字段
 * @value: unsigned int, 值字段
 * @t: struct hash_table *, 待插入的哈希表的地址
 */
static uint insert_table(char *key, uint value, struct hash_table *t)
{
    uint index;
    struct hash_node *pos, *tmp;
    index = key_to_index(key);
    //printf("%s, index is %d\n", __FUNCTION__, index);
    tmp = pos = t->bucket + index;
    pos = pos->next; // bucket do not store data
    while(pos)
    {
        if(strcmp(key, pos->key) == 0)
        {
            pos->value  = value;
            return 0;
        }
        tmp = pos;
        pos = pos->next;
    }
    pos = malloc_node(1);
    tmp->next = pos;
    pos->value = value;
    pos->key = key;
    pos->next = NULL; 
    t->number++;
    return 0;
}

/*
 * Description: 哈希表的查找函数
 * @key: char *, key字段
 * @t: struct hash_table *, 待查找的哈希表的地址
 */
static struct hash_node *search_table(char *key, struct hash_table *t)
{
    uint index;
    struct hash_node *pos;
    if(NULL == t) return NULL;
    index = key_to_index(key);
    //printf("%s, index is %d\n", __FUNCTION__, index);
    pos = t->bucket + index;
    pos = pos->next; //the bucket do not store data
    while(pos)
    {
        if(strcmp(key, pos->key) == 0)
            return pos;
        pos = pos->next;
    }
    return NULL;
}

/*
 * Description: 哈希表的删除节点函数
 * @key: char *, key字段
 * @t: struct hash_table *, 待删除节点的哈希表的地址
 */
static uint delete_table(char *key, struct hash_table *t)
{
    uint index;
    struct hash_node *pos, *tmp;
    index = key_to_index(key);
    //printf("%s, index is %d\n", __FUNCTION__, index);
    if(NULL == t)   return 1; //返回1, 哈希表为空
    tmp = pos = t->bucket + index;
    pos = pos->next; //bucket do not store data
    while(pos)   
    {
        if(strcmp(key, pos->key) == 0)
        {
            tmp->next = pos->next;
            pos->key = NULL;
            free(pos);
            t->number--;
            return 0; //返回0, 删除节点成功
        }
        tmp = pos;
        pos = pos->next;
    }
    return -1; //返回-1, 哈希表内无相匹配的key
}

测试代码, 将上述代码写进hash.h, 然后新建disp.c

#include <stdio.h>
#include "hash.h"

struct hash_table *t = NULL;

static void disp_menu()
{
    printf("----------------------My_Hash----------------------\n");
    printf("1. Insert Into Hash Table \n");
    printf("2. Search From Hash Table \n");
    printf("3. Delete From Hash Table \n");
    printf("4. Display Hash Table \n");
    printf("5. Quit \n");
    printf("Please Input the Number to Select the Function(1-5):\n ");
    printf("----------------------My_Hash----------------------\n");
    printf("Your Input is:");
}
static void insert_menu()
{
    char *key;
    uint value, ret;
    key = (char *)malloc(sizeof(char) * 10);
    printf("1. Insert Into Hash Table \n");
    printf("  Please Input the Key:");
    scanf("%s", key);
    //getchar();
    printf("  Please Input the Value:");
    scanf("%d", &value);
    ret = insert_table(key, value, t);
    if(!ret)
        printf("  Insert Successfully!\n");
}

static void search_menu()
{
    char *key;
    struct hash_node *node;
    key = (char *)malloc(sizeof(char) * 10);
    printf("1. Search From Hash Table \n");
    printf("  Please Input the Key:");
    scanf("%s", key);
    node = search_table(key, t);
    if(node == NULL)
        printf("  We Do Not Search the Matchable Value!\n");
    else
        printf("  key=%-10svalue=%-10d\n", node->key, node->value);
}

static void delete_menu()
{
    char *key;
    uint ret;
    key = (char *)malloc(sizeof(char) * 10);
    printf("1. Delete From Hash Table \n");
    printf("  Please Input the Key:");
    scanf("%s", key);
    ret = delete_table(key, t);
    if(ret == 1)
        printf("  Table is NULL!\n");
    else if(ret = -1)
        printf("  We Do Not Search the Matchable Value!\n");
    else
        printf("  Delete Successfully!\n");
}

static void display_menu()
{
    printf("1. Display Hash Table \n");
    hash_display(t);
}

static void disp_end()
{
    printf("  Continue Or Quit(y/n): ");
}

static void match_condition(int x)
{
    switch (x)
    {
        case 1:
            insert_menu();
            break;
        case 2:
            search_menu();
            break;
        case 3:
            delete_menu();
            break;
        case 4:
            display_menu();
            break;
        case 5:
            break;
        default:
            break;
    }
}

int main()
{
    int x;
    char ch = 'y';
    t = hash_init();
    disp_menu();
    scanf("%d", &x);
    while(x != 5)
    {
        match_condition(x);
        disp_end();
        getchar();
        ch = getchar();
        if(ch == 'n')
            break;
        else if(ch == 'y')
        {
            disp_menu();
            scanf("%d", &x);
        }
    }
    printf("----------------------Bye,Bye----------------------\n");
    return 0}

编译运行

# 实验环境 
# OS: Ubuntu18.04
# gcc version: 7.3.0-27
cd $workspace # workspace是你的代码目录
gcc disp.c -o disp
./disp

感想

这个hash的实现是参考的网上的一些资料, 随后附上

哈希表的实现没啥问题, 主要是测试里面C的一些堆栈溢出, 各种segment fault

万幸的是都解决了,

最后附上参考帖子

https://blog.csdn.net/yyyljw/article/details/80903391

https://blog.csdn.net/hu694028833/article/details/79114877

https://blog.csdn.net/boyishachang/article/details/8677875

https://blog.csdn.net/qq_32270067/article/details/61662220

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值