MFC中CMap类的用法和原理

发布于:2025-03-31 ⋅ 阅读:(21) ⋅ 点赞:(0)

1、CMap 的原理

CMap 是一个基于哈希表的映射类,它将唯一键映射到对应的值。其内部实现依赖于哈希算法,通过哈希函数将键转换为哈希值,然后将哈希值映射到哈希表中的某个位置。如果多个键的哈希值相同(即哈希冲突),CMap 会使用链表来解决冲突。

1.1关键点

1.1.1 哈希函数:
CMap 使用模板函数 HashKey() 来计算键的哈希值。默认情况下,HashKey() 假设键是一个指针,并将其转换为 DWORD。对于字符串类型(如 LPCSTR 和 LPCWSTR),CMap 提供了专门的哈希函数实现。
如果使用自定义类型作为键,需要提供自己的哈希函数。
1.1.2 哈希表大小:
哈希表的大小会影响性能。如果哈希表太小,可能会导致大量冲突;如果太大,则会浪费内存。可以通过调用 InitHashTable 方法来初始化哈希表并指定其大小。
1.1.3 存储结构:
CMap 内部使用一个哈希表来存储键值对。每个哈希表条目可能是一个链表,用于存储具有相同哈希值的键值对。

2.CMap 的用法

2.1. 定义和初始化

CMap 是一个模板类,需要指定键类型、键的参数类型、值类型和值的参数类型。例如:
下面展示一些 内联代码片

CMap<int, int, CString, CString> myMap; // 键为 int,值为 CString

在使用 CMap 之前,建议调用 InitHashTable 方法初始化哈希表:

myMap.InitHashTable(101); // 哈希表大小为 101

2.2 插入键值对

使用 SetAt 方法插入键值对:

myMap.SetAt(1, _T("Value1"));
myMap.SetAt(2, _T("Value2"));

也可以使用 operator[] 插入或修改键值对:

myMap[3] = _T("Value3");

3. 查找键值对

使用 Lookup 方法查找键对应的值:

CString value;
if (myMap.Lookup(1, value))
{
    // 找到键为 1 的值
    TRACE(_T("Value: %s\n"), value);
}

4. 遍历映射

可以使用 GetStartPosition 和 GetNextAssoc 方法遍历映射中的所有键值对:

POSITION pos = myMap.GetStartPosition();
int key;
CString value;
while (pos != NULL)
{
    myMap.GetNextAssoc(pos, key, value);
    TRACE(_T("Key: %d, Value: %s\n"), key, value);
}

5. 删除键值对

使用 RemoveKey 方法删除指定键的键值对:

myMap.RemoveKey(1); // 删除键为 1 的键值对

也可以使用 RemoveAll 方法清空整个映射:

myMap.RemoveAll();

6. 获取映射的大小

使用 GetSize 或 GetCount 方法获取映射中的元素数量:

int size = myMap.GetSize();
TRACE(_T("Map size: %d\n"), size);

3.注意事项

3.1 键的唯一性:
CMap 要求键是唯一的。如果尝试插入一个已经存在的键,SetAt 方法会覆盖原有的值。
3.2 自定义键类型:
如果使用自定义类型作为键,需要提供哈希函数和比较函数。默认情况下,CMap 使用 HashKey 函数计算哈希值,并使用 operator== 比较键。
3.3 性能优化:
选择合适的哈希表大小可以提高性能。哈希表大小通常是质数,可以减少冲突。
3.4 序列化:
如果需要将 CMap 对象序列化到文件,可以使用 Serialize 方法。CMap 会自动序列化其所有元素。
示例代码:

#include <afx.h>
#include <afxtempl.h>
#include <iostream>

int main()
{
    CMap<int, int, CString, CString> myMap;
    myMap.InitHashTable(101);

    // 插入键值对
    myMap.SetAt(1, _T("Value1"));
    myMap.SetAt(2, _T("Value2"));
    myMap[3] = _T("Value3");

    // 查找键值对
    CString value;
    if (myMap.Lookup(2, value))
    {
        std::wcout << L"Key 2: " << value.GetString() << std::endl;
    }

    // 遍历映射
    POSITION pos = myMap.GetStartPosition();
    int key;
    while (pos != NULL)
    {
        myMap.GetNextAssoc(pos, key, value);
        std::wcout << L"Key: " << key << L", Value: " << value.GetString() << std::endl;
    }

    // 删除键值对
    myMap.RemoveKey(1);
    myMap.RemoveAll();

    return 0;
}

以上就是MFC中CMap类的简单用法。


网站公告

今日签到

点亮在社区的每一天
去签到