理解:跳跃表是一种索引(1/2概率)随机功能的链表,因此存在两个后继。
struct node {
node(int val = INT_MIN) :value(val), up(nullptr), down(nullptr), left(nullptr), right(nullptr) {} // 结构体构造
int value;
struct node* down; // 下
struct node* right; // 右
};
由于单向链表寻找前个节点只能从链表head再次遍历,我们采用双向链表。
struct node {
node(int val = INT_MIN) :value(val), up(nullptr), down(nullptr), left(nullptr), right(nullptr) {}
int value;
// 设置4个方向上的指针
struct node* up; // 上
struct node* down; // 下
struct node* left; // 左
struct node* right; // 右
};
头文件
#pragma once
#ifndef SKIPLIST_INT_H_
#define SKIPLIST_INT_H_
#include <cstdlib> /* srand, rand */
#include <ctime> /* time */
#include <climits> /* INT_MIN */
/* 简单跳跃表,它允许简单的插入和删除元素,并提供O(logn)的查询时间复杂度。 */
/*
SkipList_Int的性质
(1) 由很多层结构组成,level是通过一定的概率随机产生的,基本是50%的产生几率。
(2) 每一层都是一个有序的链表,默认是升序,每一层的链表头作为跳点。
(3) 最底层(Level 1)的链表包含所有元素。
(4) 如果一个元素出现在Level i 的链表中,则它在Level i 之下的链表也都会出现。
(5) 每个节点包含四个指针,但有可能为nullptr。
(6) 每一层链表横向为单向连接,纵向为双向连接。
*/
// Simple SkipList_Int 表头始终是列表最小的节点
class SkipList_Int {
private:
/* 节点元素 */
struct node {
node(int val = INT_MIN) :value(val), up(nullptr), down(nullptr), left(nullptr), right(nullptr) {}
int value;
// 设置4个方向上的指针
struct node* up; // 上
struct node* down; // 下
struct node* left; // 左
struct node* right; // 右
};
private:
node* head; // 头节点,查询起始点
int lvl_num; // 当前链表层数
/* 随机判断 */
bool randomVal();
public:
SkipList_Int() : lvl_num(1) {
head = new node();
}
/* 插入新元素 */
void insert(int val);
/* 查询元素 */
bool search(int val);
/* 删除元素 */
void remove(int val);
};
#endif // !SKIPLIST_INT_H_
源代码
#include "skip_list.h"
static unsigned int seed = NULL; // 随机种子
bool SkipList_Int::randomVal() {
if (seed == NULL) {
seed = (unsigned)time(NULL);
}
::srand(seed);
int ret = ::rand() % 2;
seed = ::rand();
if (ret == 0) {
return true;
}
else {
return false;
}
}
void SkipList_Int::insert(int val) {
/* 首先查找L1层 */
node* cursor = head;
node* new_node = nullptr;
while (cursor->down != nullptr) {
cursor = cursor->down;
}
node* cur_head = cursor; // 当前层链表头
while (cursor->right != nullptr) {
if (val < cursor->right->value && new_node == nullptr) {
new_node = new node(val);
new_node->right = cursor->right;
cursor->right = new_node;
}
cursor = cursor->right; // 向右移动游标
}
if (new_node == nullptr) {
new_node = new node(val);
cursor->right = new_node;
}
/* L1层插入完成 */
/* 上层操作 */
int cur_lvl = 1; // 当前所在层
while (randomVal()) {
cur_lvl++;
if (lvl_num < cur_lvl) { // 增加一层
lvl_num++;
node* new_head = new node();
new_head->down = head;
head->up = new_head;
head = new_head;
}
cur_head = cur_head->up; // 当前链表头上移一层
cursor = cur_head; // 继续获取游标
node* skip_node = nullptr; // 非L1层的节点
while (cursor->right != nullptr) {
if (val < cursor->right->value && skip_node == nullptr) {
skip_node = new node(val);
skip_node->right = cursor->right;
}
cursor = cursor->right;
}
if (skip_node == nullptr) {
skip_node = new node(val);
cursor->right = skip_node;
}
while (new_node->up != nullptr) {
new_node = new_node->up;
}
/* 连接上下两个节点 */
skip_node->down = new_node;
new_node->up = skip_node;
}
}
bool SkipList_Int::search(int val) {
node* cursor = nullptr;
if (head == nullptr) {
return false;
}
/* 初始化游标指针 */
cursor = head;
while (cursor->down != nullptr) { // 第一层循环游标向下
while (cursor->right != nullptr) { // 第二层循环游标向右
if (val <= cursor->right->value) { // 定位元素:于当前链表发现可定位坐标则跳出循环...
break;
}
cursor = cursor->right;
}
cursor = cursor->down;
}
while (cursor->right != nullptr) { // L1层循环开始具体查询
if (val > cursor->right->value) {
cursor = cursor->right; // 如果查找的值大于右侧值则游标可以继续向右
}
else if (val == cursor->right->value) { // 如果等于则表明已经找到节点
return true;
}
else if (val < cursor->right->value) { // 如果小于则表明不存在该节点
return false;
}
}
return false; // 完成遍历返回false;
}
void SkipList_Int::remove(int val) {
node* cursor = head; // 获得游标
node* pre_head = nullptr; // 上一行的头指针,删除行时使用
while (true) {
node* cur_head = cursor; // 当前行头指针
if (pre_head != nullptr) {
cur_head->up = nullptr;
pre_head->down = nullptr; // 解除上下级的指针
delete pre_head;
pre_head = nullptr; // 指针归0
lvl_num--; // 层数-1
head = cur_head; // 重新指定起始指针
}
while (cursor != nullptr && cursor->right != nullptr) { // 在当前行中查询val
if (val == cursor->right->value) {
node* delptr = cursor->right;
cursor->right = cursor->right->right;
delete delptr; // 析构找到的节点
}
cursor = cursor->right;
}
if (cur_head->right == nullptr) { // 判断当前行是否还存在其它元素,如果不存在则删除该行并将整个跳跃表降维
pre_head = cur_head;
}
if (cur_head->down == nullptr) {
break;
}
else {
cursor = cur_head->down;
}
}
}
int main() {
SkipList_Int test1;
for (int i = 0; i < 10; i++) {
test1.insert(i);
}
bool search_label = test1.search(12);
search_label = test1.search(21);
test1.remove(1);
}