第二天 哈希

Posted on 2025-11-20 13:50  熊兔  阅读(2)  评论(0)    收藏  举报

哈希表中键不可以重复但是值可以重复

 哈希表的初始化
#include <iostream>
#include <unordered_map>  // 包含哈希表头文件
#include <string>

using namespace std;

int main() {
    // 1. 声明和初始化哈希表
    // 创建一个键为string类型,值为int类型的哈希表
    unordered_map<string, int> ageMap;
    
    // 2. 插入键值对的三种方法
    
    // 方法1:使用insert函数和pair
    ageMap.insert(pair<string, int>("Alice", 25));
    
    // 方法2:使用insert函数和make_pair
    ageMap.insert(make_pair("Bob", 30));
    
    // 方法3:使用下标操作符(如果键不存在会自动创建)
    ageMap["Charlie"] = 28;
    
    // 3. 访问元素
    
    // 使用下标操作符访问(如果键不存在会创建新元素)
    cout << "Alice的年龄: " << ageMap["Alice"] << endl;
    
    // 使用at函数访问(如果键不存在会抛出异常,更安全)
    cout << "Bob的年龄: " << ageMap.at("Bob") << endl;
    
    // 4. 检查键是否存在
    // 使用find函数,如果找到返回迭代器,否则返回end()
    if (ageMap.find("David") != ageMap.end()) {
        cout << "David存在于哈希表中" << endl;
    } else {
        cout << "David不存在于哈希表中" << endl;
    }
    
    // 5. 遍历哈希表
    
    cout << "\n遍历哈希表方法1:" << endl;
    // 方法1:使用迭代器
    for (auto it = ageMap.begin(); it != ageMap.end(); ++it) {
        // it->first 是键,it->second 是值
        cout << "姓名: " << it->first << ", 年龄: " << it->second << endl;
    }
    
    cout << "\n遍历哈希表方法2:" << endl;
    // 方法2:使用范围for循环(C++11)
    for (const auto& pair : ageMap) {
        cout << "姓名: " << pair.first << ", 年龄: " << pair.second << endl;
    }
    
    // 6. 修改元素
    
    // 如果键存在,修改对应的值
    ageMap["Alice"] = 26;  // 更新Alice的年龄
    cout << "\n更新后Alice的年龄: " << ageMap["Alice"] << endl;
    
    // 7. 删除元素
    
    // 方法1:通过键删除
    ageMap.erase("Bob");
    cout << "删除Bob后哈希表大小: " << ageMap.size() << endl;
    
    // 方法2:通过迭代器删除
    auto it = ageMap.find("Charlie");
    if (it != ageMap.end()) {
        ageMap.erase(it);
    }
    
    // 8. 其他常用操作
    
    // 获取哈希表大小(元素个数)
    cout << "当前哈希表大小: " << ageMap.size() << endl;
    
    // 检查哈希表是否为空
    cout << "哈希表是否为空: " << (ageMap.empty() ? "是" : "否") << endl;
    
    // 清空哈希表
    ageMap.clear();
    cout << "清空后哈希表大小: " << ageMap.size() << endl;
    


    return 0;
}
 判断容量
void capacityFunctions() {
    unordered_map<int, string> map = {{1, "one"}, {2, "two"}};
    
    // empty() - 检查容器是否为空
    bool isEmpty = map.empty();  // 返回false
    
    // size() - 返回元素数量
    size_t elementCount = map.size();  // 返回2
    
    // max_size() - 返回可容纳的最大元素数
    size_t maxElements = map.max_size();
    
    cout << "是否为空: " << isEmpty << endl;
    cout << "元素数量: " << elementCount << endl;
    cout << "最大容量: " << maxElements << endl;
}
 访问成员函数和异常访问方式
void accessFunctions() {
    unordered_map<string, int> ageMap = {{"Alice", 25}, {"Bob", 30}};
    
    // operator[] - 访问或插入元素
    ageMap["Charlie"] = 28;           // 插入新元素
    int aliceAge = ageMap["Alice"];   // 访问现有元素
    
    // at() - 安全访问,会检查边界
    try {
        int bobAge = ageMap.at("Bob");     // 正常访问
        int davidAge = ageMap.at("David"); // 抛出std::out_of_range异常
    } catch (const out_of_range& e) {
        cout << "键不存在: " << e.what() << endl;
    }
}


//try异常访问
try {
    int bobAge = ageMap.at("Bob");     // 正常访问,不会抛出异常
    int davidAge = ageMap.at("David"); // 键不存在,抛出std::out_of_range异常
} catch (const out_of_range& e) {
    cout << "键不存在: " << e.what() << endl;
}
//当try块中抛出异常时,程序跳转到匹配的catch块
//const out_of_range& e:捕获out_of_range类型的异常
//e是异常对象的引用
查找成员函数
void lookupFunctions() {
    unordered_map<string, int> map = {{"apple", 5}, {"banana", 3}};
    
    // find() - 查找元素,返回迭代器
    auto it = map.find("apple");
    if (it != map.end()) {
        cout << "找到apple: " << it->second << endl;
    }
    
    // count() - 返回匹配键的数量(0或1)
    size_t count = map.count("banana");  // 返回1
    count = map.count("cherry");         // 返回0
    
    // equal_range() - 返回匹配键的范围(对unordered_map用处有限)
    auto range = map.equal_range("apple");// 查找键为"apple"的所有元素
    for (auto i = range.first; i != range.second; ++i) { //i++和++i对输出没用影响
        cout << i->first << ": " << i->second << endl; //i->first:访问键(key),i->second:访问值(value)
    }
    
    // contains() - C++20引入,检查是否包含键
    #if __cplusplus >= 202002L
    bool hasApple = map.contains("apple");  // 返回true
    #endif
}
桶成员函数
void bucketFunctions() {
    unordered_map<int, string> map = {{1, "one"}, {2, "two"}, {3, "three"}};
    
    // bucket_count() - 返回桶的数量
    size_t bucketCount = map.bucket_count();
    cout << "桶数量: " << bucketCount << endl;
    
    // max_bucket_count() - 最大桶数量
    size_t maxBuckets = map.max_bucket_count();
    
    // bucket_size(n) - 返回第n个桶中的元素数量
    for (size_t i = 0; i < bucketCount; ++i) {
        cout << "桶 " << i << " 有 " << map.bucket_size(i) << " 个元素" << endl;
    }
    
    // bucket(key) - 返回键所在的桶索引
    size_t bucketIndex = map.bucket(2);
    cout << "键2在桶: " << bucketIndex << endl;
}
哈希策略成员函数
void hashPolicyFunctions() {
    unordered_map<int, string> map;
    
    // load_factor() - 当前负载因子
    float currentLoad = map.load_factor();
    
    // max_load_factor() - 获取或设置最大负载因子
    float maxLoad = map.max_load_factor();  // 获取
    map.max_load_factor(0.75f);             // 设置
    
    // rehash(n) - 设置桶的数量为至少n
    map.rehash(20);
    
    // reserve(n) - 预留空间用于至少n个元素
    map.reserve(100);
    
    cout << "当前负载因子: " << currentLoad << endl;
    cout << "最大负载因子: " << maxLoad << endl;
}
观察器成员函数
void observerFunctions() {
    unordered_map<string, int> map;
    
    // hash_function() - 返回哈希函数对象
    auto hashFunc = map.hash_function();
    size_t hashValue = hashFunc("test");
    
    // key_eq() - 返回键比较函数对象
    auto keyEqual = map.key_eq();
    bool keysEqual = keyEqual("a", "a");
    
    // get_allocator() - 返回分配器
    auto allocator = map.get_allocator();
    
    cout << "字符串'test'的哈希值: " << hashValue << endl;
    cout << "键比较结果: " << keysEqual << endl;
}
迭代器成员函数
// 定义一个名为 iteratorFunctions 的函数,返回类型为 void(不返回值)
void iteratorFunctions() {
    
    // 创建一个 unordered_map(哈希表),键为 int 类型,值为 string 类型
    // 并用初始化列表初始化三个键值对:1->"one", 2->"two", 3->"three"
    unordered_map<int, string> map = {{1, "one"}, {2, "two"}, {3, "three"}};
    
    // 输出提示信息,表示接下来是正序遍历
    cout << "正序遍历:" << endl;
    
    // 开始 for 循环,使用迭代器遍历哈希表
    // map.begin() 返回指向第一个元素的迭代器
    // map.end() 返回指向最后一个元素之后位置的迭代器
    // ++it 每次循环将迭代器向前移动一个位置
    for (auto it = map.begin(); it != map.end(); ++it) {
        
        // 通过迭代器访问当前元素的键和值
        // it->first 获取键(key),it->second 获取值(value)
        cout << it->first << ": " << it->second << endl;
    }
    
    // 输出提示信息,表示接下来使用 const 迭代器遍历
    cout << "const迭代器遍历:" << endl;
    
    // 开始 for 循环,使用 const 迭代器遍历
    // map.cbegin() 返回指向第一个元素的 const 迭代器(不能修改元素)
    // map.cend() 返回指向最后一个元素之后位置的 const 迭代器
    for (auto it = map.cbegin(); it != map.cend(); ++it) {
        
        // 通过 const 迭代器访问元素(只能读取,不能修改)
        cout << it->first << ": " << it->second << endl;
    }
    
    // 开始遍历哈希表的每个桶(bucket)
    // map.bucket_count() 返回哈希表中桶的总数量
    // size_t i = 0 初始化循环计数器,从第0个桶开始
    // i < map.bucket_count() 循环条件,遍历所有桶
    // ++i 每次循环计数器加1
    for (size_t i = 0; i < map.bucket_count(); ++i) {
        
        // 输出当前桶的编号
        cout << "桶" << i << "中的元素: ";
        
        // 开始内层循环,遍历当前桶中的所有元素
        // map.begin(i) 返回指向第i个桶中第一个元素的迭代器
        // map.end(i) 返回指向第i个桶中最后一个元素之后位置的迭代器
        for (auto local_it = map.begin(i); local_it != map.end(i); ++local_it) {
            
            // 输出当前元素的键
            cout << local_it->first << " ";
        }
        
        // 换行,结束当前桶的输出
        cout << endl;
    }
}
// 函数结束

 

博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3