跳表(Skip List)是一种基于有序链表的数据结构,它通过在原始链表上建立多层索引链表来加速查找操作。每一层的链表都是原始链表的一个子集,同时层与层之间的元素是逐渐稀疏的。跳表的平均时间复杂度为 O(log n),并且不需要像平衡树那样复杂的平衡操作,因此在实践中是一种高效的数据结构。
要用跳表实现一个类似于 C++ 中的 std::map
的数据结构,可以考虑以下步骤:
- 定义跳表节点结构:每个节点包含一个键值对,以及指向下一个节点的指针数组。
- 定义跳表类:实现插入、删除、查找等基本操作。
- 实现类似于
std::map
的功能:例如插入键值对、根据键查找值、删除键值对等。
以下是一个简单的 C++ 实现示例:
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <vector>
#include <map>
const int MAX_LEVEL = 16;
template<typename K, typename V>
struct SkipListNode {
K key;
V value;
std::vector<SkipListNode<K, V>*> forwards;
SkipListNode(K k, V v, int level) : key(k), value(v), forwards(level, nullptr) {}
};
template<typename K, typename V>
class SkipListMap {
private:
SkipListNode<K, V>* head;
int level;
int size;
public:
SkipListMap() : level(1), size(0) {
head = new SkipListNode<K, V>(K(), V(), MAX_LEVEL);
}
~SkipListMap() {
SkipListNode<K, V>* node = head->forwards[0];
while (node != nullptr) {
SkipListNode<K, V>* tmp = node->forwards[0];
delete node;
node = tmp;
}
delete head;
}
void insert(const K& key, const V& value) {
std::vector<SkipListNode<K, V>*> update(MAX_LEVEL, nullptr);
SkipListNode<K, V>* node = head;
for (int i = level - 1; i >= 0; --i) {
while (node->forwards[i] != nullptr && node->forwards[i]->key < key) {
node = node->forwards[i];
}
update[i] = node;
}
node = node->forwards[0];
if (node != nullptr && node->key == key) {
node->value = value;
} else {
int newLevel = randomLevel();
if (newLevel > level) {
for (int i = level; i < newLevel; ++i) {
update[i] = head;
}
level = newLevel;
}
node = new SkipListNode<K, V>(key, value, newLevel);
for (int i = 0; i < newLevel; ++i) {
node->forwards[i] = update[i]->forwards[i];
update[i]->forwards[i] = node;
}
++size;
}
}
V* search(const K& key) const {
SkipListNode<K, V>* node = head;
for (int i = level - 1; i >= 0; --i) {
while (node->forwards[i] != nullptr && node->forwards[i]->key < key) {
node = node->forwards[i];
}
}
node = node->forwards[0];
if (node != nullptr && node->key == key) {
return &(node->value);
} else {
return nullptr;
}
}
void erase(const K& key) {
std::vector<SkipListNode<K, V>*> update(MAX_LEVEL, nullptr);
SkipListNode<K, V>* node = head;
for (int i = level - 1; i >= 0; --i) {
while (node->forwards[i] != nullptr && node->forwards[i]->key < key) {
node = node->forwards[i];
}
update[i] = node;
}
node = node->forwards[0];
if (node != nullptr && node->key == key) {
for (int i = 0; i < level; ++i) {
if (update[i]->forwards[i] == node) {
update[i]->forwards[i] = node->forwards[i];
}
}
delete node;
while (level > 1 && head->forwards[level - 1] == nullptr) {
--level;
}
--size;
}
}
int randomLevel() {
int level = 1;
while (rand() % 2 == 0 && level < MAX_LEVEL) {
++level;
}
return level;
}
int getSize() const {
return size;
}
};
int main() {
srand(time(nullptr));
// 使用跳表实现的类似于 std::map 的数据结构
SkipListMap<int, std::string> skipListMap;
// 插入键值对
skipListMap.insert(1, "One");
skipListMap.insert(2, "Two");
skipListMap.insert(3, "Three");
// 查找键值对
std::cout << "Value of key 2: " << *(skipListMap.search(2)) << std::endl;
// 删除键值对
skipListMap.erase(2);
// 再次查找键值对
std::cout << "Value of key 2 after deletion: " << (skipListMap.search(2) ? *(skipListMap.search(2)) : "Not found") << std::endl;
return 0;
}
这个示例演示了如何用跳表实现一个类似于 std::map
的数据结构。它包括跳表节点结构 SkipListNode
和跳表类 SkipListMap
,以及 main
函数中的示例用法。