algorithm
  • README
  • 算法题目
    • Page 1
  • 算法基础
    • 堆(大/小顶堆 、优先队列)
      • swift
      • js
      • C++
    • 哈希表(HashTable)
      • 线性探测
        • 稠密哈希表
        • 密集探测哈希表vs线性探测哈希表
      • C拉链法
        • 拉链法是否需要根据负载因子扩容?
      • set的实现
      • map的实现
    • 二叉树
      • 类型
        • AVL树和红黑树的关系与区别比较
      • 存储方式
      • 遍历
        • 前中后序遍历(深度)
          • 递归方式
          • 迭代法
        • 层次遍历(广度)
      • 二叉搜索树
        • 基本概念
        • 代码实现
      • AVL树
        • 基本概念
        • 代码实现
        • 疑问
          • AVL为什么LL的时候右转呢?
          • AVL树中的LR的情况
          • AVL树的调整
          • 删除节点的逻辑
      • 红黑树
        • 基本概念
        • 代码实现
        • 疑问
          • 红黑树和AVL的关系与区别
          • 红黑树和哈希表的关系与区别
          • 为什么有红黑树,比AVL优势在哪里?
    • 运算符
      • 交换两个数(不用临时变量)
  • leetcode结构
    • Javascript
      • 优先队列
    • C++
  • 公司面试题目
    • 汇丰银行
      • 跑步同一个脚印问题
      • 销售系统问题
Powered by GitBook
On this page
  1. 算法基础
  2. 哈希表(HashTable)

C拉链法

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

#define TABLE_SIZE 100

typedef struct KeyValue {
    char *key;
    char *value;
    struct KeyValue *next; // 链表中的下一个元素
} KeyValue;

typedef struct HashTable {
    KeyValue **array; // 指向链表的指针数组
} HashTable;

// 哈希函数
unsigned int hash_function(const char *key) {
    unsigned long hash = 5381;
    int c;

    while ((c = *key++)) {
        hash = ((hash << 5) + hash) + c; // hash * 33 + c
    }

    return hash % TABLE_SIZE;
}

// 创建哈希表
HashTable *create_table() {
    HashTable *table = malloc(sizeof(HashTable));
    table->array = malloc(sizeof(KeyValue *) * TABLE_SIZE);
    
    for (int i = 0; i < TABLE_SIZE; i++) {
        table->array[i] = NULL; // 初始化为 NULL
    }
    
    return table;
}

// 插入元素
void insert(HashTable *table, const char *key, const char *value) {
    unsigned int index = hash_function(key);
    
    KeyValue *new_entry = malloc(sizeof(KeyValue));
    new_entry->key = strdup(key); // 复制键
    new_entry->value = strdup(value); // 复制值
    new_entry->next = table->array[index]; // 新节点指向链表的头
    table->array[index] = new_entry; // 更新链表头
}

// 查找元素
char *find(HashTable *table, const char *key) {
    unsigned int index = hash_function(key);
    KeyValue *current = table->array[index];
    
    while (current != NULL) {
        if (strcmp(current->key, key) == 0) {
            return current->value; // 找到值
        }
        current = current->next; // 继续查找
    }
    
    return NULL; // 未找到
}

// 删除元素
void delete(HashTable *table, const char *key) {
    unsigned int index = hash_function(key);
    KeyValue *current = table->array[index];
    KeyValue *prev = NULL;
    
    while (current != NULL) {
        if (strcmp(current->key, key) == 0) {
            if (prev == NULL) {
                table->array[index] = current->next; // 删除头节点
            } else {
                prev->next = current->next; // 删除中间节点
            }
            free(current->key);
            free(current->value);
            free(current);
            return;
        }
        prev = current;
        current = current->next;
    }
}

// 释放哈希表
void free_table(HashTable *table) {
    for (int i = 0; i < TABLE_SIZE; i++) {
        KeyValue *current = table->array[i];
        while (current != NULL) {
            KeyValue *temp = current;
            current = current->next;
            free(temp->key);
            free(temp->value);
            free(temp);
        }
    }
    free(table->array);
    free(table);
}

// 测试哈希表
int main() {
    HashTable *table = create_table();
    insert(table, "name", "Alice");
    insert(table, "age", "30");

    printf("Name: %s\n", find(table, "name"));
    printf("Age: %s\n", find(table, "age"));

    delete(table, "name");
    printf("Name after deletion: %s\n", find(table, "name"));

    free_table(table);
    return 0;
}

说明

  • 这个实现使用链表来处理哈希冲突。

  • 每个链表节点保存键值对以及指向下一个节点的指针。

  • create_table、insert、find、delete 和 free_table 函数分别实现了创建哈希表、插入、查找、删除和释放哈希表的功能。

Previous密集探测哈希表vs线性探测哈希表Next拉链法是否需要根据负载因子扩容?

Last updated 7 months ago