C语言实现的一个哈希表

此哈希表中键和值的类型都是整数

1、哈希表实现的头文件hash.h:

头文件中定义了哈希表中哈希节点和哈希表结构体类型,以及此种哈希表的操作函数:

#ifndef __HASH_INC__
#define __HASH_INC__

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

#define     HASH_SIZE   1093
/*
    定义一个哈希表节点的结构体
    成员变量:键,值,以及此节点的下一个节点的指针
 */
typedef struct _hashnode {
    int key;
    int value;
    struct _hashnode * nextNode;
}HashNode;

/*
    定义一个哈希表结构体
    成员变量: 哈希表中节点总数,哈希节点指针数组
 */
typedef struct _hashtable{
    int totalNodes;
    HashNode ** pphashNodes;
}HashTable;


int createHashTable(HashTable ** pphashTable);
HashNode *  getNodeHashTable(HashTable * pHashTable, int key);
int insertHashTable(HashTable * pHashTable, int key, int value);
int getValueHashTable(HashTable * pHashTable, int key, int * pValue);
int deleteKeyHashTable(HashTable * pHashTable, int key);
int deleteAllHashTable(HashTable ** ppHashTable);


#endif

2、此处哈希表实现的源文件hash.c:

每个函数的作用和使用方法在函数定义中详细说明:

#include "hash.h"
/*
    创建一个哈希表,由* pphashTable返回,返回0表示创建成功,-1表示创建失败
*/
int createHashTable(HashTable ** pphashTable)
{
    // 创建一个哈希表结构体
    (* pphashTable) = (HashTable *)malloc(sizeof(HashTable));

    if(NULL == (*pphashTable)){
        return -1;
    }

    // 当前节点总数为0
    // 分配一个大小为HASH_SIZE的节点指针数组,并初始化这些指针指向NULL
    (*pphashTable)->totalNodes = 0;
    (*pphashTable)->pphashNodes = (HashNode **)malloc(sizeof(HashNode *) * HASH_SIZE);

    if (NULL == (*pphashTable)->pphashNodes){
        return -1;
    }

    memset((*pphashTable)->pphashNodes, 0x00, sizeof(HASH_SIZE) * sizeof(HashNode *));

    return 0;
}

// 用键,值向哈希表中插入
// 如果以key为键的节点已经存在,则改变对应的值。
// 计算节点指针索引
// 分配哈希节点,将传入的key和value写入对应的成员变量
// 如果由key计算出的节点指针索引的指针指向空,则将以上哈希节点的地址存入这个指针
// 如果指针索引的指针不为空,则从当前指向节点中nextNode寻找下一个节点,直接这个节点的nextNode指向空,
// 将新分配节点地址存入当前节点的nextNode。
int insertHashTable(HashTable * pHashTable, int key, int value)
{
    int ikey = key % HASH_SIZE;
    HashNode * tmpNode = NULL;

    tmpNode = getNodeHashTable(pHashTable, key);
    // tmpNode = (HashNode *)malloc(sizeof(HashNode));

    if (tmpNode != NULL){
        tmpNode->value = value;
        return -1;
    }

    HashNode * newNode = (HashNode *)malloc(sizeof(HashNode));

    if (NULL == newNode){
        return -1;
    }

    newNode->key = key;
    newNode->value = value;
    newNode->nextNode = NULL;

    if (pHashTable->pphashNodes[ikey] == NULL){
        pHashTable->pphashNodes[ikey] = newNode;
    }
    else{
        tmpNode = pHashTable->pphashNodes[ikey];
        while (tmpNode->nextNode != NULL){
            tmpNode = tmpNode->nextNode;
        }

        tmpNode->nextNode = newNode;
    }
    pHashTable->totalNodes++;
    return 0;
}


/* 在哈希表中寻找以key为键的值,如果找到则用*pValue取回,并且函数返回0,否则函数返回-1 */
int getValueHashTable(HashTable * pHashTable, int key, int * pValue){
    int ikey = key % HASH_SIZE;
    HashNode * tmpNode;

    if (pHashTable  == NULL || pHashTable->totalNodes == 0 || pHashTable->pphashNodes[ikey] == NULL){
        return -1;
    }

    tmpNode = pHashTable->pphashNodes[ikey];

    while (tmpNode != NULL && tmpNode->key != key){
        tmpNode = tmpNode->nextNode;
    }

    if (tmpNode == NULL){
        return -1;
    }
    else{
        * pValue = tmpNode->value;
        return 0;
    }
}

/*
    在哈希表中寻找以key为键的哈希节点,如果找到,则返回这个节点,否则,返回NULL
*/
HashNode *  getNodeHashTable(HashTable * pHashTable, int key)
{
    int ikey = key % HASH_SIZE;
    HashNode * tmpNode = NULL;

     if (pHashTable  == NULL || pHashTable->totalNodes == 0 || pHashTable->pphashNodes[ikey] == NULL){
        return NULL;
    }

    tmpNode = pHashTable->pphashNodes[ikey];

    while (tmpNode != NULL && tmpNode->key != key){
        tmpNode = tmpNode->nextNode;
    }

    return tmpNode;
}

/* 在哈希表中,删除以key为键的哈希节点,如果删除成功返回0,否则返回-1 */
int deleteKeyHashTable(HashTable * pHashTable, int key)
{
    int ikey = key % HASH_SIZE;
    HashNode * tmpNode, * prevNode;

    if (pHashTable == NULL || pHashTable->totalNodes == 0 || pHashTable->pphashNodes[ikey] == NULL){
        return -1;
    }

    tmpNode = pHashTable->pphashNodes[ikey];

    while (tmpNode && tmpNode->key != key){
        prevNode = tmpNode;
        tmpNode = tmpNode->nextNode;
    }

    if (tmpNode == NULL){
        return -1;
    }
    else{
        if (tmpNode == pHashTable->pphashNodes[ikey]){
            pHashTable->pphashNodes[ikey] = tmpNode->nextNode;
        }
        else{
            prevNode->nextNode = tmpNode->nextNode;
        }
        free(tmpNode);
        pHashTable->totalNodes--;
        return 0;
    }
}

/* 释放哈希表中所有哈希节点以及哈希表 */
int deleteAllHashTable(HashTable ** ppHashTable)
{
    int i;
    HashNode * tmpNode, * nextNode;

    if ((* ppHashTable) == NULL || (*ppHashTable)->totalNodes == 0)
    {
        return -1;
    }

    for (i = 0; i < HASH_SIZE; i++){
        if ((*ppHashTable)->pphashNodes[i] == NULL){
            continue;
        }
        else{
            tmpNode  = (*ppHashTable)->pphashNodes[i];
            while (tmpNode->nextNode != NULL){
                nextNode = tmpNode->nextNode;
                free(tmpNode);
                (*ppHashTable)->totalNodes--;
                tmpNode = nextNode;
            }
            free(tmpNode);
            (*ppHashTable)->totalNodes--;

            (*ppHashTable)->pphashNodes[i] = NULL;
            if ((*ppHashTable)->totalNodes == 0){
                break;
            }
        }
    }

    free(* ppHashTable);
    (*ppHashTable) = NULL;
    return 0;
}

3、测试程序test.c如下:

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

void test(int key1, int value1, int key2, int value2)
{
    HashTable * pHashTable;

    /* create hash table */
    if (createHashTable(&pHashTable) != 0){
        printf("create failed\n");
        return;
    }

    /* insert key and value into hash table */
    insertHashTable(pHashTable, key1, value1);
    insertHashTable(pHashTable, key2, value2);


    printf("current total nodes:%d\n", pHashTable->totalNodes);

    /* get hashnode with key*/
    HashNode * tmpNode = getNodeHashTable(pHashTable, key1);
    printf("Get Hashnode with key:\n");
    if (tmpNode != NULL){
        printf("key:%d--->value:%d\n", key1, tmpNode->value);
    }
    else{
        printf("key:%d-->no value in hash table\n",key1);
    }

    tmpNode = getNodeHashTable(pHashTable, key2);
    if (tmpNode != NULL){
        printf("key:%d--->value:%d\n", key2, tmpNode->value);
    }
    else{
        printf("key:%d-->no value in hash table\n",key2);
    }

    /* get value with key*/
    printf("Get value with key:\n");
    int value = 0;
    getValueHashTable(pHashTable, key1, &value);
    printf("key:%d--->value:%d\n", key1, value);

    getValueHashTable(pHashTable, key2, &value);
    printf("key:%d--->value:%d\n", key2, value);

    /* delete hashnode with key */
    deleteKeyHashTable(pHashTable, key1);
    printf("current totoal nodes:%d\n", pHashTable->totalNodes);
    tmpNode = getNodeHashTable(pHashTable, key1);
    if (tmpNode != NULL){
        printf("key:%d--->value:%d\n", key1, tmpNode->value);
    }
    else{
        printf("key:%d-->no value in hash table\n",key1);
    }

    tmpNode = getNodeHashTable(pHashTable, key2);
    if (tmpNode != NULL){
        printf("key:%d--->value:%d\n", key2, tmpNode->value);
    }
    else{
        printf("key:%d-->no value in hash table\n",key2);
    }

    /* delete all hashnodes and hashtable */
    deleteAllHashTable(&pHashTable);
}

int main()
{

        test(1,11,2,22);
        return 0;
}

4、用于编译的Makefile文件:

OBJS=$(patsubst %.c,%.o, $(wildcard ./*c))
TARGET=main

$(TARGET):$(OBJS)
        $(CXX) $^ -o $(TARGET)

%.o:%.c
        $(CXX) -c $^ -o $@

clean:
        rm -rf *.o $(TARGET)


.PHONY:clean

5、执行make进行编译:

orangepi@orangepi5:~/C_program/hash_dir$ make
g++ -c hash.c -o hash.o
g++ -c test.c -o test.o
g++ hash.o test.o -o main
orangepi@orangepi5:~/C_program/hash_dir$ ls
hash.c  hash.c.bak  hash.h  hash.o  main  Makefile  test.c  test.o

6、测试生成的可执行程序main:

orangepi@orangepi5:~/C_program/hash_dir$ ./main
current total nodes:2
Get Hashnode with key:
key:1--->value:11
key:2--->value:22
Get value with key:
key:1--->value:11
key:2--->value:22
current totoal nodes:1
key:1-->no value in hash table
key:2--->value:22

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值