C语言实现hashset

koaker 发布于 2025-06-03 C语言


typedef struct HashSetNode {
    void *key;
    struct HashSetNode *next;
} HashSetNode;
typedef struct HashSet {
    HashSetNode ** table;
    size_t size;
    size_t capacity;

    unsigned int (*hash_function)(const void *key);
    int (*key_compare_function)(const void *key1, const void *key2);
    void (*key_destroy_function)(void *key);
} HashSet;

HashSet *hashset_create(size_t capacity, 
                         unsigned int (*hash_function)(const void *key),
                         int (*key_compare_function)(const void *key1, const void *key2),
                         void (*key_destroy_function)(void *key)) {
    HashSet *set = malloc(sizeof(HashSet));
    if (!set) return NULL;
    set->capacity = capacity;
    set->size = 0;
    set->table = calloc(capacity, sizeof(HashSetNode *));
    if (!set->table) {
        free(set);
        return NULL;
    }
    set->hash_function = hash_function;
    set->key_compare_function = key_compare_function;
    set->key_destroy_function = key_destroy_function;
    return set;
}

void hashset_destroy(HashSet *set) {
    if (!set) return ;
    if (!set->table) {
        free(set);
        return ;
    }
    for (size_t i = 0; i < set->capacity; i++) {
        HashSetNode *node = set->table[i];
        while (node) {
            HashSetNode *temp = node;
            node = node->next;
            set->key_destroy_function(temp->key);
            free(temp);
        }
    }
    free(set->table);
    free(set);
    return ;
}
#define VOS_OK 0
#define VOS_ERR 1
int hashset_insert(HashSet *set, void *key) {
    if (!set || !key) return VOS_ERR;
    if (set->table == NULL) {
        return VOS_ERR;
    }
    unsigned int hash = set->hash_function(key) % set->capacity;
    HashSetNode *new_node = malloc(sizeof(HashSetNode));
    if (!new_node) return VOS_ERR;
    new_node->key = key;
    new_node->next = set->table[hash];
    set->table[hash] = new_node;
    set->size++;
    return VOS_OK;
}

int hashset_remove(HashSet *set, void *key) {
    if (!set|| !key) return VOS_ERR;
    unsigned int hash = set->hash_function(key) % set->capacity;
    HashSetNode *node = set->table[hash];
    if (!node) return VOS_ERR;
    if (set->key_compare_function(node->key, key) == 0) {
        set->table[hash] = node->next;
        set->key_destroy_function(node->key);
        free(node);
        set->size--;
        return VOS_OK;
    } else {
        while(node->next) {
            if (set->key_compare_function(node->next->key, key) == 0) {
                HashSetNode *temp = node->next;
                node->next = temp->next;
                set->key_destroy_function(temp->key);
                free(temp);
                set->size--;
                return VOS_OK;
            }
            node = node->next;
        }
        return VOS_ERR;
    }
}

int hashset_contains(const HashSet *set, const void *key) {
    if (!set || !key) return VOS_ERR;
    unsigned int hash = set->hash_function(key) % set->capacity;
    HashSetNode *node = set->table[hash];
    while (node) {
        if (set->key_compare_function(node->key, key) == 0) {
            return VOS_OK;
        }
        node = node->next;
    }
    return VOS_ERR;
}

size_t hashset_size(const HashSet *set) {
    if (!set) return 0;
    return set->size;
}

HashSet *hashset_resize(HashSet *set, size_t new_capacity) {
    if (!set || new_capacity <= set->capacity) return NULL;
    
    HashSet *new_set = hashset_create(new_capacity, set->hash_function, set->key_compare_function, set->key_destroy_function);
    if (!new_set) return NULL;

    for (size_t i = 0; i < set->capacity; i++) {
        HashSetNode *node = set->table[i];
        while (node) {
            hashset_insert(new_set, node->key);
            node = node->next;
        }
    }

    hashset_destroy(set);
    return new_set;
}


unsigned int Hash_Function(const void *key) {
    return (unsigned int)(*(char *)key);
}

int Key_Compare_Function(const void *key1, const void *key2) {
    if (*(char*)key1 > *(char*)key2) {
        return 1;
    } else if (*(char*)key1 < *(char*)key2) {
        return -1;
    } 
    return 0;
}
void Key_Destroy_Function(void *key) {
    free(key);
}

//使用时需要先创建,然后进行插入之类的操作。
此作者没有提供个人介绍。
最后更新于 2025-06-03