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类的简单用法。