跳表定义:
跳表(Skip List)是一种用于有序元素集合的数据结构,它通过层次化的链表结构在查找、插入和删除操作上具有较高的平均时间复杂度。
跳表特点:
- 简单性和易实现性:相对于平衡树等复杂的数据结构,跳表的实现比较简单。它由多个层次的链表组成,每个层次的链表是下一个层次链表的子集,从而形成一种层次化的结构。
- 平均时间复杂度:在跳表中,插入、删除和搜索的平均时间复杂度都为 O(log n),其中 n 是元素个数。这是通过每一级链表跳跃来实现的,类似于二分查找。
- 无需平衡操作:与平衡树不同,跳表的平衡是通过随机化生成层次和节点来实现的,因此不需要像平衡树那样频繁地进行旋转或平衡操作。
- 空间效率:虽然跳表相对于普通链表需要更多的空间来存储层次结构,但它的空间复杂度仍然是线性的,因为每层的节点数量是平均减少的。
- 可拓展性:跳表可以轻松地在现有的基础上进行扩展。当数据量增加时,可以动态地增加层次,从而保持跳表的性能。
- 局部性原理:跳表利用了局部性原理,即在内存访问中,往往会访问附近的数据。通过层次结构,跳表在查找时可以更快地跳过不必要的部分,从而减少了访问的数据量。
- 并发性:由于跳表的结构相对简单,它在并发环境下可以更容易地实现锁粒度更小的操作,从而在一些情况下获得更好的并发性能。
代码实现:
- 定义跳表节点类,每插入一个元素,都会为该元素创建一个SkipNode与之对应
class SkipNode {
public:
//跳表节点保存的值
int value;
//跳表节点每一层的指针
std::vector<SkipNode*> forward;
SkipNode(int val, int level) : value(val), forward(level + 1, nullptr) {}
};
2. 定义跳表类
class SkipList {
private:
//跳表的最大层数
int MAX_LEVEL;
//当前跳表的最大层数
int level;
//跳表的头节点
SkipNode* head;
//新插入一个节点时,随机产生一个与之对应的层数
int randomLevel() {
int lvl = 1;
while (rand() % 2 == 0 && lvl < MAX_LEVEL) {
lvl++;
}
return lvl;
}
public:
//初始化,先创建对应的头结点
SkipList(int maxLevel) : MAX_LEVEL(maxLevel), level(0) {
head = new SkipNode(-1, MAX_LEVEL);
}
//在跳表中插入一个元素
void insert(int value) {
int newLevel = randomLevel();
if (newLevel > level) {
level = newLevel;
}
SkipNode* newNode = new SkipNode(value, newLevel);
SkipNode* current = head;
for (int i = level; i >= 0; i--) {
while (current->forward[i] != nullptr && current->forward[i]->value < value){
current = current->forward[i];
}
if (i <= newLevel) {
newNode->forward[i] = current->forward[i];
current->forward[i] = newNode;
}
}
}
//在跳表中移除一个元素
void remove(int value) {
SkipNode* current = head;
for (int i = level; i >= 0; i--) {
while (current->forward[i] != nullptr && current->forward[i]->value < value){
current = current->forward[i];
}
if (current->forward[i] != nullptr && current->forward[i]->value == value) {
SkipNode* temp = current->forward[i];
current->forward[i] = temp->forward[i];
delete temp;
}
}
}
//在跳表中查找一个元素
bool search(int value) {
SkipNode* current = head;
for (int i = level; i >= 0; i--) {
while (current->forward[i] != nullptr && current->forward[i]->value < value){
current = current->forward[i];
}
if (current->forward[i] != nullptr && current->forward[i]->value == value) {
return true;
}
}
return false;
}
};
通过以上代码,可以简单实现保存元素为整型的跳表,涵盖插入、删除和搜索操作。