程序设计的核心,而C++作为高性能编程语言,其对底层内存和信息操作的直接性,使其成为实现核心数据结构的首选语言。本文将聚焦哈希表、红黑树(平衡二叉搜索树的经典实现)和双指针算法三大高频核心内容,从原理剖析、C++落地构建到应用场景全维度讲解,支援开发者真正掌握这些关键技术的落地能力。就是数据结构与算法
一、哈希表:高效查找的核心实现
哈希表(Hash Table)是基于哈希函数将键(Key)映射到值(Value)的线性数据结构,其平均时间复杂度为O(1)的查找、插入和删除特性,使其成为工程中最常用的高效查找容器。C++标准库中的unordered_map/unordered_set正是哈希表的实现,本节将从零实现一个简易哈希表,理解其底层原理。
1. 核心原理
哈希表的核心是“哈希函数+冲突处理”:
- 哈希函数:将任意长度的键转换为固定范围的索引(如数组下标),要求尽可能均匀分布,减少冲突。常用方法有取模法、乘法哈希法等。
- 冲突解决:由于哈希函数映射的索引范围有限,不同键可能映射到同一索引(哈希冲突),主流解决方式为链地址法(Separate Chaining)——每个数组元素对应一个链表,冲突的元素存入链表中。
2. C++达成哈希表(链地址法)
(1)设计思路
- 底层用动态数组存储链表头节点,数组大小(桶数)初始化为16,负载因子(元素数/桶数)超过0.75时扩容;
- 哈希函数:对字符串键采用BKDR哈希算法,对整数键直接取模;
- 支持插入、查找、删除、扩容核心操作;
- 模板化设计,支持任意键值类型(需重载哈希函数)。
(2)完整实现代码
#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <utility> // pair
#include <cstdint> // uint64_t
// 哈希函数模板(默认整数哈希)
template <typename K>
struct HashFunc {
size_t operator()(const K& key) const {
return static_cast<size_t>(key);
}
};
// 字符串哈希特化(BKDR算法)
template <>
struct HashFunc<std::string> {
size_t operator()(const std::string& key) const {
size_t hash = 0;
for (char c : key) {
hash = hash * 131 + c; // 131是经典质数,减少冲突
}
return hash;
}
};
// 哈希表模板类
template <typename K, typename V, typename Hash = HashFunc<K>>
class HashTable {
private:
// 桶的类型:链表存储键值对
using Bucket = std::list<std::pair<K, V>>;
// 桶数组
std::vector<Bucket> buckets;
// 元素总数
size_t size_;
// 负载因子阈值
const float load_factor_threshold = 0.75f;
// 哈希函数对象
Hash hash_func;
// 计算键对应的桶索引
size_t get_bucket_index(const K& key) const {
return hash_func(key) % buckets.size();
}
// 扩容:桶数翻倍,重新哈希所有元素
void resize() {
size_t new_bucket_count = buckets.size() * 2;
std::vector<Bucket> new_buckets(new_bucket_count);
// 遍历所有旧桶,重新分配元素到新桶
for (auto& bucket : buckets) {
for (auto& pair : bucket) {
size_t new_idx = hash_func(pair.first) % new_bucket_count;
new_buckets[new_idx].push_back(std::move(pair));
}
bucket.clear();
}
// 替换旧桶数组
buckets.swap(new_buckets);
}
public:
// 构造函数:初始化桶数为16
HashTable() : buckets(16), size_(0) {
}
// 插入键值对(若键已存在,更新值)
void insert(const K& key, const V& value) {
// 检查负载因子,超过阈值则扩容
if (static_cast<float>(size_) / buckets.size() >= load_factor_threshold) {
resize();
}
size_t idx = get_bucket_index(key);
Bucket& bucket = buckets[idx];
// 查找键是否存在,存在则更新值
for (auto& pair : bucket) {
if (pair.first == key) {
pair.second = value;
return;
}
}
// 键不存在,插入新元素
bucket.push_back(std::make_pair(key, value));
size_++;
}
// 查找键对应的值,返回是否找到
bool find(const K& key, V& value) const {
size_t idx = get_bucket_index(key);
const Bucket& bucket = buckets[idx];
for (const auto& pair : bucket) {
if (pair.first
浙公网安备 33010602011771号