数据结构 ----- 哈希表(链地址法--开散列)

在上一篇文章中已经提到过链地址法,现在具体看下图例子:
这里写图片描述
实现代码如下:
hash.h

#pragma once

#include <stddef.h>
#define HashMaxSize 1000

typedef int KeyType;
typedef int ValType;

//此结构相当于是链表的一个节点
typedef struct HashElem{
    KeyType key;
    ValType value;
    struct HashElem* next;
}HashElem;

typedef size_t (*HashFunc)(KeyType key);

typedef struct HashTable{
    HashElem* data[HashMaxSize];//不带头结点的链表
    size_t size;
    HashFunc func;
}HashTable;

void HashInit(HashTable* ht,HashFunc hash_func);

int HashFind(HashTable* ht,KeyType key,ValType* value);

void HashRemove(HashTable* ht ,KeyType key);

hash.c

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

size_t HashFuncDefualt(KeyType key){
    return key % HashMaxSize;
}

HashElem* CreateElem(KeyType key,ValType value){
    HashElem* new_node = (HashElem*)malloc(sizeof(HashElem));
    new_node->key = key;
    new_node->value = value;
    new_node->next = NULL;
    return new_node;
}

void DestroyElem(HashElem* node){
    free(node);
}

void HashInit(HashTable* ht,HashFunc hash_func){
    if(ht == NULL){
        return;
    }
    ht->size = 0;
    ht->func = hash_func;
    size_t i = 0;
    for(;i < HashMaxSize;i++){
        ht->data[i] = NULL;
    }
    return;
}

void HashDestroy(HashTable* ht){
    if(ht == NULL){
        return;
    }
    ht->size = 0;
    ht->func = NULL;
    //遍历所有链表,进行释放操作
    size_t i = 0;
    for(;i < HashMaxSize;i++){
        HashElem* cur = ht->data[i];
        while(cur != NULL){
            HashElem* next = cur->next;
            DestroyElem(cur);
            cur = next;
        }
    }
    return;
}
HashElem* HashBucketFind(HashElem* head,KeyType to_find){
    if(head == NULL){
        return NULL;
    }
    HashElem* cur = head;
    for(;cur != NULL;cur = cur->next){
        if(to_find == cur->key){
            break;
        }
    }
    return cur == NULL ? NULL:cur;
}
void HashInsert(HashTable* ht ,KeyType key,ValType value){
    if(ht == NULL){
        return;
    }
    size_t offset = ht->func(key);
    HashElem* ret = HashBucketFind(ht->data[offset],key);
    if(ret != NULL){
        //存在与key值一样的元素,插入失败
        return;
    }
    //采用头插方式
    HashElem* new_node = CreateElem(key,value);
    new_node->next = ht->data[offset];
    ht->data[offset] = new_node;
    ++ht->size;
    return;
}

int HashBucketFind(HashElem* head,KeyType to_find){
    if(head == NULL){
        return 0;
    }
    HashElem* cur = head;
    while(cur != NULL){
        if(cur->key == to_find){
            return 1;
       }else{
            cur = cur->next;
        }
    }
    return 0;
}
int HashFind(HashTable* ht,KeyType key,ValType* value){
    if(ht == NULL){
        return 0;
    }
    size_t offset = ht->func(key);
    HashElem* ret = HashBucketFind(ht->data[offset],key);
    if(ret == NULL){
        //没找到
        return 0;
    }
    *value = ret->value;
    return 1;
}

int HashBucketFindEx(HashElem* head,KeyType to_find,HashElem** pre_node,
                     HashElem** cur_node){
    if(head == NULL){
        return 0;
    }
    HashElem* cur = head;
    HashElem* pre = NULL;
    for(;cur != NULL;pre=cur,cur=cur->next){
        if(to_find == cur->key){
            break;
        }
    }
    if(cur == NULL){
        return 0;
    }
    *pre_node = pre;
    *cur_node = cur;
    return 1;
}
void HashRemove(HashTable* ht,KeyType key){
    if(ht == NULL){
        return;
    }
    if(ht->size == 0){
        return;
    }
    size_t offset = ht->func(key);
    HashElem* pre = NULL;
    HashElem* cur = NULL;
    int ret = HashBucketFindEx(ht->data[offset],key,&pre,&cur);
    if(ret == 0){
        //没找到
        return;
    }
    if(pre == NULL){
        //删除头节点
        ht->data[offset] = cur->next;
    }else{
        pre->next = cur->next;
    }
    DestroyElem(cur);
    --ht->size;
    return;
}

猜你喜欢

转载自blog.csdn.net/liru_1996/article/details/80525096