哈希表---------开散列实现

HashTable.h:

#include<stddef.h>

#define HashMaxSize  1000
typedef int KeyType;
typedef int ValueType;



typedef size_t(*HashFunc)(KeyType key);
typedef struct HashElem{
    KeyType key;
    ValueType value;
    struct HashElem* next;
}HashElem;

typedef struct HashTable{
    HashElem* data[HashMaxSize];
    size_t size;
    HashFunc hash_func;
}HashTable;


void HashInit(HashTable* ht, HashFunc hash_func);

// 约定哈希表中不能包含 key 相同的值.
void HashInsert(HashTable* ht, KeyType key, ValueType value);

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

void HashRemove(HashTable* ht, KeyType key);

size_t HashSize(HashTable* ht);

int HashEmpty(HashTable* ht);

void HashDestroy(HashTable* ht);

HashTable.c

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

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


//法1.
HashElem* HashBucketFind(HashTable* head, KeyType key){
    HashElem* cur = head;
    for (; cur != NULL; cur = cur->next){
        if (cur->key == key){
            return cur;
        }
    }
    return NULL;
}

//法2.
int HashBucketFindCur_Prev(HashTable* head, KeyType key, HashElem**cur_out, HashElem** pre_out){
    HashElem* prev = NULL;
    HashElem* cur = head;
    for (; cur != NULL; prev = cur, cur = cur->next){
        if (cur->key == key){
            *cur_out = cur;
            *pre_out = prev;
            return 1;
        }
    }
    return 0;
}
HashElem* HashCreate(KeyType key, ValueType value){
    HashElem* new_node = (HashElem*)malloc(sizeof(HashElem));
    new_node->key = key;
    new_node->next = NULL;
    new_node->value = value;
    return new_node;
}
void HashInsert(HashTable* ht, KeyType key, ValueType value){
    if (ht == NULL){
        return;
    }
    size_t offset =ht->hash_func(key);
    HashElem* res = HashBucketFind(ht->data[offset], key);
    if (res != NULL){
        return;
    }
    else{
        HashElem* new_node = HashCreate(key, value);//采用头插
        new_node->next = ht->data[offset];
        ht->data[offset] = new_node;
        ++(ht->size);
    }
}

int HashFind(HashTable* ht, KeyType key, ValueType* value){
    if (ht == NULL){
        return 0;
    }
    size_t offset = ht->hash_func(key);
    HashElem* cur = ht->data[offset];
    while (cur != NULL){
        if (cur->key == key){
            *value = cur->value;
            return 1;
        }
        cur = cur->next;
    }
    return 0;
}
void HashDestroy(HashTable* ht){
    if (ht == NULL){
        return;
    }
    size_t i = 0;
    for (; i < HashMaxSize; i++){
        if (ht->data[i] != NULL){
            ht->data[i] = NULL;
        }
    }
    ht->size = 0;
    ht->hash_func = NULL;
}
void Destroy(HashElem* head){
    if (head == NULL){
        return;
    }
    free(head);
}
void HashRemove(HashTable* ht, KeyType key){
    //法1.
    //if (ht == NULL){
    //  return;
    //}
    //size_t offset = ht->hash_func(key);
    //HashElem* cur = ht->data[offset];
    //HashElem* prev = cur;
    //if (cur != NULL&&cur->key == key){
    //  ht->data[offset] = cur->next;//恰好要删除的是第一个元素
    //  free(cur);
    //  --ht->size;
    //}
    //else{
    //  while (cur != NULL){
    //      if (cur->key == key){
    //          prev->next = cur->next;
    //          free(cur);
    //          --ht->size;
    //          return;;
    //      }
    //      prev = cur;
    //      cur = cur->next;
    //  }
    //}
    //法2.
    if (ht == NULL){
        return;
    }
    size_t offset = ht->hash_func(key);
    HashElem* prev = NULL;
    HashElem* cur  = NULL;
    int ret = HashBucketFindCur_Prev(ht->data[offset], key,&cur,&prev);
    if (ret == 0){
        return;
    }
    if (cur == ht->data[offset]){
        ht->data[offset] = cur->next;
    }
    else{
        prev->next = cur->next;
    }
    Destroy(cur);
    ht->size--;
}

int HashEmpty(HashTable* ht){
    if (ht == NULL){
        return;
    }
    return ht->size == 0;
}


size_t HashSize(HashTable* ht){
    if (ht == NULL||ht->data==NULL){
        return 0;
    }
    return ht->size;
}
////////////////////////////////////////////////////
//测试代码
////////////////////////////////////////////////////
#if 1
#include<stdio.h>
#define TEST_HEADER  printf("\n=========================%s=======================\n",__FUNCTION__);
void Display(HashTable* ht){
    size_t i = 0;
    for (; i < HashMaxSize; i++){
        if (ht->data[i] == NULL){
            continue;
        }

        HashElem* cur = ht->data[i];
        for (; cur != NULL; cur = cur->next){
            printf("%lu-> %d %d\n", i,cur->key, cur->value);
        }

    }
}
void testHashInit(){
    TEST_HEADER;
    HashTable ht;
    HashInit(&ht, HashFuncDefault);
    printf("ht.size expect 0,actual %lu\n", ht.size);
    printf("ht->hashfunc expect %p,actual %p\n", HashFuncDefault, ht.hash_func);
    int i = 0;
    for (; i < HashMaxSize; i++){
        if (ht.data[i] != NULL){
            printf("初始化不成功");
        }
    }
}
void testHashInsert(){
    TEST_HEADER;
    HashTable ht;
    HashInit(&ht, HashFuncDefault);
    HashInsert(&ht, 1, 100);
    HashInsert(&ht, 2, 200);
    HashInsert(&ht, 1001, 300);
    HashInsert(&ht, 1002, 400);
    printf("插入四个元素:\n");
    Display(&ht);
}
void testHashFind(){
    TEST_HEADER;
    HashTable ht;
    HashInit(&ht, HashFuncDefault);
    HashInsert(&ht, 1, 100);
    HashInsert(&ht, 2, 200);
    HashInsert(&ht, 1001, 300);
    HashInsert(&ht, 1002, 400);
    int  value=0;
    int ret=HashFind(&ht, 1001, &value);
    printf("ret expect 1,actual %d\n", ret);
    printf("value expect 300,actual %d\n", value);
     ret = HashFind(&ht, 1003, &value);
    printf("ret expect 0,actual %d\n", ret);
}
void testHashRemove(){
    TEST_HEADER;
    HashTable ht;
    HashInit(&ht, HashFuncDefault);
    HashInsert(&ht, 1, 100);
    HashInsert(&ht, 2, 200);
    HashInsert(&ht, 1001, 300);
    HashInsert(&ht, 1002, 400);
    Display(&ht);
    printf("ht->size=%d\n", ht.size);
    HashRemove(&ht, 1);
    printf("ht->size=%d\n", ht.size);
    Display(&ht);
    printf("删除第一个元素:\n");
    HashRemove(&ht, 1001);
    printf("ht->size=%d\n", ht.size);
}
void testHashDestroy(){
    TEST_HEADER;
    HashTable ht;
    HashInit(&ht, HashFuncDefault);
    HashInsert(&ht, 1, 100);
    HashInsert(&ht, 2, 200);
    HashInsert(&ht, 1001, 300);
    HashInsert(&ht, 1002, 400);
    Display(&ht);
    printf("销毁哈希表\n");
    HashDestroy(&ht);
    Display(&ht);
}

void testHashEmpty(){
    TEST_HEADER;
    HashTable ht;
    HashInit(&ht, HashFuncDefault);
    printf("expect 1 actual %d\n",HashEmpty(&ht));
}

void testHashSize(){
    TEST_HEADER;
    HashTable ht;
    HashInit(&ht, HashFuncDefault);
    /*HashInsert(&ht, 1, 100);
    HashInsert(&ht, 2, 200);
    HashInsert(&ht, 1001, 300);
    HashInsert(&ht, 1002, 400);
    printf("expect 4 actual %d\n", HashSize(&ht));*/
    printf("expect 0 actual %d\n", HashSize(&ht)); 
}
int main(){
    //testHashInit();
    //testHashInsert();
    //testHashFind();
    //testHashRemove();
    //testHashDestroy();
    //testHashEmpty();
    testHashSize();
    system("pause");
    return 0;
}
#endif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值