实现一个哈希表的核心功能

代码

hash.c

/*
 * @Author: ZPY
 * @TODO: 创建一个哈希表,实现其功能
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define LOAD_FACTOR 0.7	// 装载因子

typedef struct hash
{
    char **str;		// 字符串数组
    int capacity;
    int size;
} Hash;

// 哈希表操作
void init(Hash *hash);
void insert(Hash *hash, char *str);
void delete(Hash *hash, char *str);
void display(Hash *hash);
void incr(Hash *hash);
void destory(Hash *hash);
int get_num(char *str);
int size(Hash *hash);
char *get_str();

char buf[1024] = {'\0'};    // 全局字符数组

int main(int argc, char const *argv[])
{
    int choice;
    Hash *hash = malloc(sizeof(Hash));

    printf("欢迎使用哈希表!\n");
    init(hash);     // 初始化哈希表
    while (1)
    {
        printf("============字符串哈希表 1.0============\n");
        printf("==============1. 存入字符串=============\n");
        printf("==============2. 删除字符串=============\n");
        printf("==============3. 查看字符串=============\n");
        printf("==============4. 退出本系统=============\n");

        scanf("%d", &choice);
        getchar(); // 吸收换行符
        char *str;
        switch (choice)
        {
        case 1:
            str = get_str();
            insert(hash, str);
            break;
        case 2:
            str = get_str();
            delete (hash, str);
            break;
        case 3:
            display(hash);
            break;
        case 4:
            destory(hash);
            return 0;
        }
    }

    return 0;
}

void init(Hash *hash)
{
    hash->capacity = 5;
    hash->size = 0;
    hash->str = malloc(sizeof(char *) * hash->capacity);
    for (int i = 0; i < hash->capacity; i++)
    {
        hash->str[i] = NULL;
    }
}

void insert(Hash *hash, char *str)
{
    if (hash->size > hash->capacity * LOAD_FACTOR) // 如果当前哈希表存储内容大于装载比例,就扩容
    {
        incr(hash);
    }

    int index = get_num(str) % hash->capacity;
    while (hash->str[index])
    {
        index++;
        index = index % hash->capacity; // 如果当前位置已经有值了,就往后找空位
    }
    hash->str[index] = strdup(str);
    hash->size++;
}

void delete(Hash *hash, char *str)
{
    int index = get_num(str) % hash->capacity;
    int i;

    for (i = 0; i < hash->capacity; i++)
    {
        if (hash->str[index] && strcmp(hash->str[index], str) == 0) // 先判断字符串是不空再比较
        {
            free(hash->str[index]); // 先释放字符串内存空间
            hash->str[index] = NULL;
            break;
        }
        else
        {
            index++;
            index %= hash->capacity;
        }
    }
    if (i == hash->capacity) // 如果没找到这个字符串
    {
        printf("哈希表内未保存此字符串。\n");
        return;
    }
    printf("删除成功!\n");
    hash->size--;
}

void display(Hash *hash)
{
    for (int i = 0; i < hash->capacity; i++)
    {
        if (hash->str[i])
        {
            printf("hash[%d] = %s\n", i, hash->str[i]);
        }
        else
        {
            printf("hash[%d] = NULL\n", i);
        }
    }
    printf("hash->size = %d\n", size(hash));
}

void incr(Hash *hash)   // 每次扩容之后要重新散列字符串
{
    // 记录原来的容量和内容
    int old_capacity = hash->capacity;
    char **old_str = hash->str;

    hash->capacity = hash->capacity << 1; // 扩容为原来的两倍
    hash->str = malloc(hash->capacity * sizeof(char *));// 在新的空间上分配
    for (int i = 0; i < hash->capacity; i++)
    {
        hash->str[i] = NULL;
    }
    
    hash->size = 0;     // 哈希表长度归零
    for (int i = 0; i < old_capacity; i++)
    {
        if (old_str[i])
        {
            insert(hash, old_str[i]);   // 将原来的内容重新散列
            free(old_str[i]);           // 释放原来的内容
        }
    }
    free(old_str);
}

void destory(Hash *hash)
{
    for (int i = 0; i < hash->capacity; i++)
    {
        free(hash->str[i]); // 依次释放字符串内容
    }
    free(hash->str);
    free(hash); // 释放哈希表
}

int get_num(char *str)
{
    int res = 0;
    int len = strlen(str);

    while (len--)
    {
        res += str[len];
    }

    return res;
}

char *get_str()
{
    printf("请输入字符串:");
    fgets(buf, sizeof(buf), stdin);
    buf[strcspn(buf, "\n")] = '\0'; // 去除末尾换行符

    return buf;
}

int size(Hash *hash)
{
    return hash->size;
}

编译

gcc hash.c -o hash
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值