嘿,程序员们!👋 今天我们要揭秘C++中最牛的数据结构之一——红黑树!相信很多小伙伴对map和set的内部实现一直很好奇,今天我们就一起"解剖"它们!💪
想象红黑树就像是一个有严格纪律的家族:
// 颜色枚举,红黑树的"身份证"
enum Color {
RED, // 红色成员
BLACK // 黑色成员
};
// 节点:红黑树的基本单元
template <typename T>
struct RBTreeNode {
T data; // 数据
Color color; // 颜色标记
RBTreeNode* parent; // 父节点指针
RBTreeNode* left; // 左孩子
RBTreeNode* right; // 右孩子
// 新成员默认是红色的
RBTreeNode(const T& value) :
data(value),
color(RED),
parent(nullptr),
left(nullptr),
right(nullptr) {}
};
// 左旋:想象成一个节点向左侧"倒下"
void rotateLeft(RBTreeNode* x) {
RBTreeNode* y = x->right; // 找到要"顶替"的节点
x->right = y->left; // 调整关系
// 一系列复杂的指针重连接...
if (y->left != nullptr)
y->left->parent = x;
// 更新根节点或父节点的子节点
if (x->parent == nullptr)
root = y;
else if (x == x->parent->left)
x->parent->left = y;
else
x->parent->right = y;
y->left = x;
x->parent = y;
}
map就像是一个高级的"翻译官":
template <typename Key, typename Value>
class MyMap {
private:
RBTree<std::pair<Key, Value>> tree;
public:
// 插入操作
void insert(const std::pair<Key, Value>& kvPair) {
tree.insertUnique(kvPair);
}
// 牛逼的下标访问
Value& operator[](const Key& key) {
// 如果没有就自动创建
return tree.findOrInsert(key);
}
};
emplace
替代insert
unordered_map/unordered_set
容器 | 插入 | 查找 | 删除 |
---|---|---|---|
map | O(log n) | O(log n) | O(log n) |
set | O(log n) | O(log n) | O(log n) |
操作 | 平均时间复杂度 |
---|---|
插入 | O(log n) |
查找 | O(log n) |
删除 | O(log n) |
在C++的世界里,map
和set
绝对是最常用且最强大的容器之一。它们不仅仅是简单的数据结构,更是算法和数据管理的利器。本文将带你全方位解析这两个容器的方方面面。
迭代器可以理解为容器和算法之间的桥梁。它就像一个"智能指针",能够遍历容器中的元素,同时屏蔽不同容器的内部细节。
C++中迭代器主要分为五类:
template <typename T>
class MyIterator {
private:
T* ptr; // 底层指针
public:
// 构造函数
MyIterator(T* p) : ptr(p) {}
// 解引用操作符
T& operator*() {
return *ptr;
}
// 前置++操作符
MyIterator& operator++() {
++ptr;
return *this;
}
// 比较操作符
bool operator!=(const MyIterator& other) {
return ptr != other.ptr;
}
};
map
是一个关联容器,它存储键值对(key-value),并且:
// 词频统计
std::map<std::string, int> wordCount;
// 添加元素
wordCount["hello"] = 10;
wordCount["world"] = 20;
// 遍历
for (const auto& pair : wordCount) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
template <typename Key, typename Value>
class MyMap {
private:
// 内部红黑树
RBTree<std::pair<const Key, Value>> tree;
public:
// 插入操作
void insert(const std::pair<Key, Value>& kvPair) {
tree.insertUnique(kvPair);
}
// 下标访问操作符
Value& operator[](const Key& key) {
// 如果键不存在,自动创建
return tree.findOrInsert(key);
}
// 迭代器支持
auto begin() { return tree.begin(); }
auto end() { return tree.end(); }
};
set
是只存储键的关联容器:
// 去重
std::set<int> uniqueNumbers;
uniqueNumbers.insert(1);
uniqueNumbers.insert(2);
uniqueNumbers.insert(1); // 不会重复插入
// 查找
auto it = uniqueNumbers.find(2);
if (it != uniqueNumbers.end()) {
std::cout << "找到元素" << std::endl;
}
std::map<std::string, int> wordFrequency;
void countWords(const std::string& text) {
std::istringstream iss(text);
std::string word;
while (iss >> word) {
wordFrequency[word]++;
}
}
template <typename Key, typename Value>
class LRUCache {
private:
std::map<Key, Value> cache;
std::list<Key> lruList;
size_t capacity;
public:
void put(const Key& key, const Value& value) {
if (cache.size() >= capacity) {
// 移除最近最少使用的元素
cache.erase(lruList.front());
lruList.pop_front();
}
cache[key] = value;
lruList.push_back(key);
}
};
红黑树就是这么牛!🐂
map和set不仅仅是容器,更是C++中的艺术品。深入理解它们,将极大提升你的编程能力!希望通过这篇文章,你能窥探C++容器的神秘面纱!