c++,数据结构,unordermap哈希表基本操作

两数之和,题目来自leetcode

cpp 复制代码
//两数之和,首先将其列出一一对应,然后对其进行遍历相加,相加值等于,则返回,否则不返回
#include<vector>
#include<unordered_map>

using namespace std;

//法1.暴力求解
class Sloution {
public:
	vector<int> twoSum(vector<int>&nums, int target) {

		for (int i = 0; i < nums.size(); i++) {
			for (int j = i + 1; j < nums.size(); j++)
			{
				if (nums[i] + nums[j] == target)
				{
					return{ i,j };
				}
			}
		}

		return{};
	}
};

//法2,哈希表求解
class Sloution_1 {
public:
	vector<int> TwoSum(vector<int>&nums_, int targets){
		//初始化哈希表
		unordered_map<int, int> hashmap;

		//进行一次遍历
		for (int i = 0; i < nums_.size(); i++)
		{
			//计算需要的数值
			int complement = targets - nums_[i];

			//检查hashmap中是否存在需要的值,首次遍历其中为空,必定不存在,其中自动存在迭代器,不需要自己再写,查找时
			if (hashmap.find(complement) != hashmap.end())
			{
				return{ hashmap[complement],i };//找到了,进行返回
			}
			hashmap[nums_[i]] = i;//将查找过的数值存储到其中,为下次做准备
		}
		return{};
	}
};

下面介绍unordermap的基础操作

1. 基本操作

创建和初始化

复制代码
#include <unordered_map>
#include <string>
using namespace std;
​
// 创建空哈希表
unordered_map<int, string> map1;
​
// 初始化列表
unordered_map<int, string> map2 = {
    {1, "Alice"},
    {2, "Bob"},
    {3, "Charlie"}
};
​
// 复制构造
unordered_map<int, string> map3(map2);

插入操作

复制代码
unordered_map<int, string> map;
​
// 1. 使用[]操作符(如果键存在则覆盖)
map[1] = "Apple";
map[2] = "Banana";
​
// 2. insert() 方法
map.insert({3, "Cherry"});
map.insert(make_pair(4, "Date"));
​
// 3. emplace() 高效插入
map.emplace(5, "Elderberry");
​
// 检查插入是否成功
auto result = map.insert({1, "Apricot"});  // 键1已存在,插入失败
if (!result.second) {
    cout << "插入失败,键已存在" << endl;
}

2. 查找操作

复制代码
unordered_map<int, string> map = {{1, "Apple"}, {2, "Banana"}};
​
// 1. find() 方法(推荐)
auto it = map.find(2);
if (it != map.end()) {
    cout << "找到: " << it->first << " -> " << it->second << endl;
} else {
    cout << "未找到" << endl;
}
​
// 2. count() 方法
if (map.count(1) > 0) {
    cout << "键存在" << endl;
}
​
// 3. at() 方法(安全访问)
try {
    string value = map.at(1);  // 如果键不存在会抛出异常
} catch (const out_of_range& e) {
    cout << "键不存在" << endl;
}
​
// 4. []操作符(不安全,会创建新键)
string value = map[3];  // 如果键3不存在,会创建一个空值

3. 删除操作

复制代码
unordered_map<int, string> map = {
    {1, "A"}, {2, "B"}, {3, "C"}, {4, "D"}
};
​
// 1. erase() 通过键
map.erase(2);  // 删除键为2的元素
​
// 2. erase() 通过迭代器
auto it = map.find(3);
if (it != map.end()) {
    map.erase(it);
}
​
// 3. erase() 删除范围
auto begin = map.find(1);
auto end = map.find(4);
map.erase(begin, end);  // 删除[1,4)范围的元素
​
// 4. clear() 清空所有元素
map.clear();

4. 遍历操作

复制代码
unordered_map<int, string> map = {{1, "A"}, {2, "B"}, {3, "C"}};
​
// 1. 使用迭代器
cout << "迭代器遍历:" << endl;
for (auto it = map.begin(); it != map.end(); ++it) {
    cout << it->first << " -> " << it->second << endl;
}
​
// 2. 范围for循环(推荐)
cout << "范围for循环:" << endl;
for (const auto& pair : map) {
    cout << pair.first << " -> " << pair.second << endl;
}
​
// 3. 结构化绑定(C++17)
cout << "结构化绑定:" << endl;
for (const auto& [key, value] : map) {
    cout << key << " -> " << value << endl;
}

5. 容量查询

复制代码
unordered_map<int, string> map = {{1, "A"}, {2, "B"}};
​
cout << "大小: " << map.size() << endl;
cout << "是否为空: " << map.empty() << endl;
cout << "桶数量: " << map.bucket_count() << endl;
cout << "负载因子: " << map.load_factor() << endl;
cout << "最大负载因子: " << map.max_load_factor() << endl;

6. 桶操作

复制代码
unordered_map<int, string> map = {{1, "A"}, {2, "B"}, {3, "C"}};
​
// 查看特定键所在的桶
int key = 2;
size_t bucket = map.bucket(key);
cout << "键" << key << "在桶" << bucket << endl;
​
// 查看桶的大小
cout << "桶" << bucket << "的大小: " << map.bucket_size(bucket) << endl;
​
// 遍历特定桶中的元素
for (auto it = map.begin(bucket); it != map.end(bucket); ++it) {
    cout << "桶中的元素: " << it->first << " -> " << it->second << endl;
}

7. 哈希策略控制

复制代码
unordered_map<int, string> map;
​
// 设置最大负载因子
map.max_load_factor(0.7f);
​
// 预分配桶数量(减少重新哈希)
map.reserve(100);
​
// 重新哈希
map.rehash(50);

8. 两数之和的完整示例

复制代码
#include <iostream>
#include <unordered_map>
#include <vector>
using namespace std;
​
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> hashmap;
        
        for (int i = 0; i < nums.size(); i++) {
            int complement = target - nums[i];
            
            // 使用find查找补数
            auto it = hashmap.find(complement);
            if (it != hashmap.end()) {
                return {it->second, i};
            }
            
            // 插入当前元素
            hashmap[nums[i]] = i;
            
            // 调试信息:打印当前哈希表状态
            cout << "插入后哈希表大小: " << hashmap.size() << endl;
            cout << "当前负载因子: " << hashmap.load_factor() << endl;
        }
        
        return {};
    }
};
​
// 测试函数
int main() {
    Solution sol;
    vector<int> nums = {2, 7, 11, 15};
    int target = 9;
    
    vector<int> result = sol.twoSum(nums, target);
    
    if (!result.empty()) {
        cout << "结果: [" << result[0] << ", " << result[1] << "]" << endl;
    } else {
        cout << "未找到解" << endl;
    }
    
    return 0;
}

9. 性能特点

操作 平均复杂度 最坏复杂度 说明
插入 O(1) O(n) 插入单个元素
查找 O(1) O(n) 根据键查找
删除 O(1) O(n) 根据键删除
遍历 O(n) O(n) 遍历所有元素

10. 常用技巧

统计频率

复制代码
vector<int> nums = {1, 2, 2, 3, 3, 3};
unordered_map<int, int> freq;
​
for (int num : nums) {
    freq[num]++;  // 自动初始化为0然后递增
}
​
// 输出: 1:1, 2:2, 3:3

检查重复

复制代码
vector<int> nums = {1, 2, 3, 2, 4};
unordered_map<int, bool> seen;
​
for (int num : nums) {
    if (seen[num]) {
        cout << "重复元素: " << num << endl;
    }
    seen[num] = true;
}

这些是 unordered_map 最常用的操作,掌握它们可以高效地解决很多算法问题。

相关推荐
Incredibuild2 小时前
CI/CD Pipeline:完整指南
c++·ci/cd·devsecops
深思慎考2 小时前
LinuxC++项目开发日志——基于正倒排索引的boost搜索引擎(4——通过jsoncpp库建立搜索模块)
linux·c++·搜索引擎
青草地溪水旁3 小时前
设计模式(C++)详解——职责链模式 (Chain of Responsibility)(2)
c++·设计模式·责任链模式
青草地溪水旁3 小时前
设计模式(C++)详解——职责链模式 (Chain of Responsibility)(1)
c++·设计模式·责任链模式
不沾一点因果4 小时前
基于C++的分布式RPC框架(一)
c++
usabcd24 小时前
如何重新编译HyperLPR原生库以消除16k对齐警告
android·c++·cmake·ndk·mnn·16k对齐·hyperlpr
椎名澄嵐6 小时前
★ Linux ★ 信号
linux·运维·服务器·开发语言·c++
普通网友7 小时前
C++构建缓存加速
开发语言·c++·算法
带鱼吃猫7 小时前
高并发内存池(三):手把手从零搭建ThreadCache线程缓存
数据结构·c++·链表·visual studio