🔢 ChainMap_S - 链表法哈希映射(单一数据类型)

采用链表法解决哈希冲突的键值对映射表,存储单一类型数据

📖 概述

ChainMap_S (Chain Map Single Data) 是一种采用链表法(Separate Chaining)解决哈希冲突的 Map 数据结构。它将哈希值相同的元素存储在同一个链表中,适合数据量较大且分布不均匀的场景。

📌 特点

  • 采用链表法处理哈希冲突
  • 只能存储单一类型数据(key 和 value 类型可不同)
  • 需要提供 key 和 value 的操作集
  • 支持动态扩容

⚙️ 数据类型定义

// ChainMap_S 中的 Entry 类型
typedef struct Entry_S_inChainMap {
    Data_S key;      // 键
    Data_S value;   // 值
    bool isEmpty;    // 是否为空
} Entry_S_inChainMap;

// ChainMap_S 链表节点
typedef struct Node_S_inChainMap {
    struct Node_S_inChainMap* next;
    struct Node_S_inChainMap* prev;
    Entry_S_inChainMap entry;
} Node_S_inChainMap;

// ChainMap_S 链表
typedef struct List_S_inChainMap {
    Node_S_inChainMap* head;
    Node_S_inChainMap* tail;
    int size;
} List_S_inChainMap;

// ChainMap_S
typedef struct ChainMap_S {
    List_S_inChainMap* arr;      // 哈希桶数组
    InfoOfData* keyInfo;          // key 操作集
    InfoOfData* valInfo;          // value 操作集
    int mod;                      // 取模基数
    int len;                      // 哈希桶数量
    int size;                     // 元素数量
} ChainMap_S;

🚀 快速开始

#include "base.h"
#include "Map/ChainMap/Single_Data/chainmap_sdata.h"
#include "Oper/String_Info/string_info.h"
#include "Oper/Int_Info/int_info.h"

int main() {
    // 1. 初始化 Map
    ChainMap_S map;
    initSChainMap(&map, &Info_String, &Info_Int);

    // 2. 插入键值对
    insertSKeyAndSValInSChainMap(&map, 
        Data_S_OWN("age", NULL), 
        Data_S_OWN(25, NULL));

    insertSKeyAndSValInSChainMap(&map,
        Data_S_OWN("score", NULL),
        Data_S_OWN(100, NULL));

    // 3. 查找
    Data_S val = getCopySValBySKeyInSChianMap(&map, Data_S_OWN("age", NULL));
    if (!val.isEmpty) {
        printf("age: %d\n", *(int*)val.data);
    }

    // 4. 打印
    printSChainMap(&map);

    // 5. 释放
    freeSChainMap(&map);
    return 0;
}

📋 函数列表

🔧 初始化与销毁

void initSChainMap(ChainMap_S* pMap, InfoOfData* keyInfo, InfoOfData* valInfo)

初始化 ChainMap_S

参数:
  • pMap - ChainMap_S 的指针
  • keyInfo - key 的 InfoOfData 类型指针
  • valInfo - val 的 InfoOfData 类型指针
void freeSValInSChainMap(ChainMap_S* pMap, Data_S* valData)

释放掉复制来的在 ChainMap_S 中的 SVal

参数:
  • pMap - ChainMap_S 的指针
  • valData - SVal 类型指针 (Data_S 类型)
void freeSEntryInSChainMap(ChainMap_S* pMap, Entry_S_inChainMap* entry)

释放掉复制来的在 ChainMap_S 中的 SEntry (Entry_S_inChainMap 类型)

参数:
  • pMap - ChainMap_S 的指针
  • entry - SEntry 类型 (Entry_S_inChainMap 类型)
void freeSChainMap(ChainMap_S* pMap)

释放掉 ChainMap_S

参数:
  • pMap - ChainMap_S 的指针

➕ 插入与查询

InfoOfReturn insertSKeyAndSValInSChainMap(ChainMap_S* pMap, Data_S key, Data_S val)

插入 key 和 val 到 ChainMap_S 类型中去

参数:
  • pMap - ChainMap_S 的指针
  • key - 传入的 key (Data_S 类型数据)
  • val - 传入的 val (Data_S 类型数据)
返回: 返回 InfoOfReturn 中的枚举类型
Data_S getCopySValBySKeyInSChianMap(ChainMap_S* pMap, Data_S key)

通过 SKey 得到复制来的 SVal (Data_S 类型)

参数:
  • pMap - ChainMap_S 的指针
  • key - 传入的 key (Data_S 类型数据)
返回: 返回 Data_S 类型数据,若没有返回空 Data_S 类型数据,通过 Data.isEmpty 进行查看
注意: 返回的数据使用后需要调用 freeSValInSChainMap 释放
Data_S getPtrSValBySKeyInSChainMap(ChainMap_S* pMap, Data_S key)

通过 SKey 得到 SVal (Data_S 类型),可直接修改内部的 void* data 和 void* content 内容

参数:
  • pMap - ChainMap_S 的指针
  • key - 传入的 key (Data_S 类型数据)
返回: 返回 Data_S 类型数据,若没有返回空 Data_S 类型数据,通过 Data.isEmpty 进行查看
警告: 返回的指针直接指向 Map 内部数据,请勿 free
Entry_S_inChainMap getCopySEntryBySKeyInSChainMap(ChainMap_S* pMap, Data_S key)

通过 SKey 得到复制来的 SEntry (Entry_S_inChainMap 类型)

参数:
  • pMap - ChainMap_S 的指针
  • key - 传入的 key (Data_S 类型数据)
返回: 返回 Entry_S_inChainMap 类型数据,若没有返回空 Entry_S_inChainMap 类型数据,通过 entry.isEmpty 进行查看

🔍 判存与删除

bool hasSKeyInSChainMap(ChainMap_S* pMap, Data_S key)

判断 Skey 是否在 ChainMap_S 中

参数:
  • pMap - ChainMap_S 的指针
  • key - 传入的 key (Data_S 类型数据)
返回: 如果存在返回 true,否则 false
InfoOfReturn delSEntryBySKeyInSChainMap(ChainMap_S* pMap, Data_S key)

通过 SKey 删除在 ChainMap_S 中的元素

参数:
  • pMap - ChainMap_S 的指针
  • key - 传入的 key (Data_S 类型数据)
返回: 返回 InfoOfReturn 中的枚举类型

🖨️ 打印

void printSChainMap(ChainMap_S* pMap)

打印 ChainMap_S 中的所有数据

参数:
  • pMap - ChainMap_S 的指针
void printSKeyInSChainMap(ChainMap_S* pMap, Data_S keyData)

打印在 ChainMap_S 中的 SKey (Data_S 类型)

参数:
  • pMap - ChainMap_S 的指针
  • keyData - SKey (Data_S 类型)
void printSValInSChainMap(ChainMap_S* pMap, Data_S valData)

打印在 ChainMap_S 中的 SVal (Data_S 类型)

参数:
  • pMap - ChainMap_S 的指针
  • valData - SVal (Data_S 类型)
void printSEntryInSChainMap(ChainMap_S* pMap, Entry_S_inChainMap entry)

打印在 ChainMap_S 中的 SEntry (Entry_S_inChainMap 类型)

参数:
  • pMap - ChainMap_S 的指针
  • entry - SEntry (Entry_S_inChainMap 类型)

💡 完整示例

#include <stdio.h>
#include "base.h"
#include "Map/ChainMap/Single_Data/chainmap_sdata.h"
#include "Oper/String_Info/string_info.h"
#include "Oper/Int_Info/int_info.h"

int main() {
    // 初始化 Map
    ChainMap_S map;
    initSChainMap(&map, &Info_String, &Info_Int);

    // 插入数据
    printf("=== 插入数据 ===\n");
    insertSKeyAndSValInSChainMap(&map, 
        Data_S_OWN("apple", NULL), 
        Data_S_OWN(10, NULL));
    insertSKeyAndSValInSChainMap(&map, 
        Data_S_OWN("banana", NULL), 
        Data_S_OWN(5, NULL));
    insertSKeyAndSValInSChainMap(&map, 
        Data_S_OWN("orange", NULL), 
        Data_S_OWN(8, NULL));

    printSChainMap(&map);

    // 查询
    printf("\n=== 查询数据 ===\n");
    Data_S val = getCopySValBySKeyInSChianMap(&map, Data_S_OWN("apple", NULL));
    if (!val.isEmpty) {
        printf("apple 的数量: %d\n", *(int*)val.data);
        freeSValInSChainMap(&map, &val);
    }

    // 判断存在
    printf("\n是否存在 grape: %s\n", 
        hasSKeyInSChainMap(&map, Data_S_OWN("grape", NULL)) ? "是" : "否");

    // 删除
    printf("\n=== 删除数据 ===\n");
    delSEntryBySKeyInSChainMap(&map, Data_S_OWN("banana", NULL));
    printSChainMap(&map);

    // 释放
    freeSChainMap(&map);
    return 0;
}

⚠️ 注意事项