C语言数据结构哈希表详解

C语言数据结构哈希表详解

什么是哈希表?

哈希表(Hash Table)是一种采用散列函数(hash函数)将数据映射到一个固定长度的数组中,并且以 O(1) 的时间复杂度进行数据插入、查找、删除操作的数据结构。哈希表主要由以下三个组成部分构成:
- 数组:用于存储映射到对应下标上的数据。
- 散列函数:将数据映射到数组下标上的规则。
- 冲突处理方式:当不同的数据映射到同一下标时,需要采取的处理措施,如开放地址法、链地址法等。

实现哈希表的关键点

哈希表的实现过程中,有以下几个关键点需要掌握:

哈希函数的设计

哈希函数的设计决定了哈希表的效率和数据存储的均衡性,通常需要符合以下要求:
- 易于计算:计算哈希值的时间复杂度要尽量低。
- 均匀分布:将数据散列到数组中的下标需要尽量均匀,减少冲突的发生。
- 低冲突率:哈希算法计算出相同哈希值的输入应尽量少。

哈希表的扩容和缩容

当哈希表存储的数据量达到一定阈值时,需要对哈希表进行扩容,以保证哈希表的效率和空间利用率。同时,当哈希表中存储的数据量变小时,还需要对哈希表进行缩容以减少空间的浪费。

冲突的解决方式

当不同的数据映射到同一下标时,可以采取以下几种冲突解决方式:
- 开放地址法:尝试向其他的空闲位置插入元素,类似于寻找新的住址。
- 链地址法:将多个具有同一哈希值的元素存储在同一个链表中。

哈希表的实现示例

以下是一个使用链地址法实现哈希表的示例,详见代码:

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

// 哈希表节点结构体
typedef struct HashNode {
    char* key;
    char* value;
    struct HashNode* next;
} HashNode;

// 哈希表结构体
typedef struct HashTable {
    HashNode** nodes;
    int size;
} HashTable;

// 创建哈希表
HashTable* createHashTable(int size) {
    HashTable* hashTable = (HashTable*)malloc(sizeof(HashTable));
    hashTable->nodes = (HashNode**)calloc(size, sizeof(HashNode*));
    hashTable->size = size;
    return hashTable;
}

// 计算哈希值
int hash(char* key, int size) {
    unsigned int hashValue = 0;
    for (int i = 0; i < strlen(key); i++) {
        hashValue = hashValue * 31 + key[i];
    }
    return hashValue % size;
}

// 插入键值对
void put(HashTable* hashTable, char* key, char* value) {
    int index = hash(key, hashTable->size);
    HashNode* node = hashTable->nodes[index];
    while (node != NULL) {
        if (strcmp(node->key, key) == 0) {
            // 如果键已经存在,更新其对应的值
            strcpy(node->value, value);
            return;
        }
        node = node->next;
    }
    // 如果键不存在,创建新的节点并插入链表头部
    HashNode* newNode = (HashNode*)malloc(sizeof(HashNode));
    newNode->key = (char*)malloc(strlen(key) + 1);
    strcpy(newNode->key, key);
    newNode->value = (char*)malloc(strlen(value) + 1);
    strcpy(newNode->value, value);
    newNode->next = hashTable->nodes[index];
    hashTable->nodes[index] = newNode;
}

// 获取键对应的值
char* get(HashTable* hashTable, char* key) {
    int index = hash(key, hashTable->size);
    HashNode* node = hashTable->nodes[index];
    while (node != NULL) {
        if (strcmp(node->key, key) == 0) {
            return node->value;
        }
        node = node->next;
    }
    return NULL;
}

// 删除键值对
void removeByKey(HashTable* hashTable, char* key) {
    int index = hash(key, hashTable->size);
    HashNode* node = hashTable->nodes[index];
    HashNode* preNode = NULL;
    while (node != NULL) {
        if (strcmp(node->key, key) == 0) {
            if (preNode == NULL) {
                // 如果删除的节点是链表的第一个节点,需要将链表头部指向第二个节点
                hashTable->nodes[index] = node->next;
            } else {
                // 如果删除的节点不是链表的第一个节点,需要将前一个节点指向下一个节点
                preNode->next = node->next;
            }
            free(node->key);
            free(node->value);
            free(node);
            return;
        }
        preNode = node;
        node = node->next;
    }
}

// 删除哈希表
void deleteHashTable(HashTable* hashTable) {
    for (int i = 0; i < hashTable->size; i++) {
        HashNode* node = hashTable->nodes[i];
        while (node != NULL) {
            HashNode* nextNode = node->next;
            free(node->key);
            free(node->value);
            free(node);
            node = nextNode;
        }
    }
    free(hashTable->nodes);
    free(hashTable);
}

// 示例:使用哈希表存储学生信息
int main() {
    HashTable* studentTable = createHashTable(100);
    put(studentTable, "Tom", "20");
    put(studentTable, "Jerry", "19");
    put(studentTable, "Alice", "21");
    put(studentTable, "Bob", "18");

    printf("Bob's age is %s\n", get(studentTable, "Bob"));

    removeByKey(studentTable, "Alice");

    printf("Alice's age is %s\n", get(studentTable, "Alice"));

    deleteHashTable(studentTable);
    return 0;
}

在上述代码中,我们使用了链地址法解决了哈希冲突,并实现了插入、查找、删除等操作。此外,我们还根据实际需求,将该哈希表用于存储学生信息,以便更好地说明哈希表的应用场景。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言数据结构哈希表详解 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月16日

相关文章

  • Java数据结构之有向图设计与实现详解

    Java数据结构之有向图设计与实现详解 什么是有向图 有向图是一种图形结构,其中每一个节点都有一个方向,即它指向或被其他节点指向。有向图可以用来表示许多实际问题,如路线、依赖关系、状态转移等。 有向图的基本概念 在有向图中,每一个节点都有一个唯一的标识符,被称为节点ID。如果从节点A到节点B存在一条有向边,则称B是A的后继节点,A是B的前驱节点。节点的度数是…

    数据结构 2023年5月17日
    00
  • C语言进阶数据的存储机制完整版

    C语言进阶数据的存储机制完整版攻略 1. 前言 C语言是一门高度可控的语言,其中其数据的存储机制是必须掌握的基础知识点。本文介绍了C语言数据存储的机制,包括变量在内存中的分配、指针的应用及结构体的组织等内容,旨在帮助读者掌握C语言中的数据存储机制。 2. 变量在内存中的分配 变量在内存中的分配既涉及到内存的分配可操作性,也涉及到相应的存储结构。 2.1. 变…

    数据结构 2023年5月17日
    00
  • C++LeetCode数据结构基础详解

    C++LeetCode数据结构基础详解攻略 什么是LeetCode? LeetCode是一个专门为程序员提供的算法题平台。平台上汇集了各种算法、数据结构和编程题,用户可以在平台上挑战各种难度的算法用来提高自己的编程能力和算法素养。 如何学习LeetCode? 学习LeetCode的关键是掌握数据结构和算法。下面介绍如何结合具体的C++代码来学习LeetCod…

    数据结构 2023年5月17日
    00
  • C语言多维数组数据结构的实现详解

    C语言多维数组数据结构的实现详解 多维数组的定义 多维数组是由若干行和若干列构成的数据类型,它由多个一维数组组成。在C语言中,多维数组的定义和一维数组十分相似,只是在数组定义中增加了方括号以表示维数。 下面是一个二维数组的定义: int arr[3][4]; 上述代码定义了一个3行4列的二维数组,标识符为arr,它包含12个元素。其中arr[0][0]到ar…

    数据结构 2023年5月17日
    00
  • Huffman实现

    Huffman编码树 秒懂:【算法】Huffman编码_哔哩哔哩_bilibili 约定:字符x的编码长度 就是其对应叶节点的深度; 在一个字符集中,每个字符出现的次数有多有少,那么若都采用固定长度编码的话,那么编码长度会非常大,并且搜索时间复杂度都非常高;若采用非固定编码,出现次数多的字符编码长度小一些,并且放在树深度小的地方,提高搜索时间效率;这样带权平…

    算法与数据结构 2023年4月17日
    00
  • 简单讲解哈希表

    哈希表(Hash Table),也被称为散列表,是一种高效的数据结构,它可以在O(1)的时间复杂度下完成插入、删除、查找等基本操作。哈希表是通过将关键字映射到一个固定大小的表中来实现的,这个映射函数被称为哈希函数。 什么是哈希函数 哈希函数是将任意长度的输入值(也称为“键”或“关键字”)映射为固定大小的输出值(也称为“哈希值”或“散列”)。哈希函数必须将不同…

    数据结构 2023年5月17日
    00
  • C语言 数据结构中栈的实现代码

    下面是关于C语言中栈的实现代码的详细攻略: 栈的概念 栈是一种只能在一端进行插入或删除操作的线性数据结构,它具有后进先出(Last In First Out, LIFO)的特点。通俗的说,就像大家在平时搭积木那样,搭积木的时候总是从最下面开始往上搭,拿积木的时候总是从最上面的积木开始拿起,栈就是这么一个先进后出的数据结构。 栈的实现方法 栈的实现方法比较多,…

    数据结构 2023年5月17日
    00
  • Java数据结构之图(动力节点Java学院整理)

    Java数据结构之图是动力节点Java学院整理的一篇关于图的攻略教程,该教程包含以下主要内容: 一、图的定义 图是由若干个顶点以及它们之间的相互关系所构成的数学模型。它包含了许多实际生活中的应用,如社交网络、地图、电子邮件网络等。 二、图的存储方式 图的存储方式有两种:邻接矩阵和邻接表。 邻接矩阵 邻接矩阵以二维数组的形式存储图。对于有n个顶点的图,其邻接矩…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部