根据数据规模确定索引层数,根据概率确定插入数据索引层数。
每插入一个元素,有概率生成$x$级索引,$0\le x\le p$,若当前跳表插入元素个数为$n$,$p$是满足$2^p\ge n$最小的数。生成$x$级索引的概率是$\frac{1}{2^x},(x>0)$,不生成索引$(x=0)$概率为$\frac{1}{2^p}$。
#include <bits/stdc++.h>
using namespace std;
random_device seed;
ranlux48 engine(seed());
int random(int l, int r) {
uniform_int_distribution<> distrib(l, r);
return distrib(engine);
}
template<class t,class u> ostream& operator<<(ostream& os,const pair<t,u>& p) {
return os<<'['<<p.first<<", "<<p.second<<']';
}
template<class t> ostream& operator<<(ostream& os,const vector<t>& v) {
os<<'['; int s = 1;
for(auto e:v) { if (s) s = 0; else os << ", "; os << e; }
return os<<']';
}
template<class t,class u> ostream& operator<<(ostream& os,const map<t,u>& mp){
os<<'{'; int s = 1;
for(auto [x,y]:mp) { if (s) s = 0; else os << ", "; os<<x<<": "<<y; }
return os<<'}';
}
#define NINF 0xf3f3f3f3
class Skiplist {
public:
struct Node {
int val;
Node* down;
Node* right;
Node(int val, Node* down=NULL, Node* right=NULL):val(val),down(down),right(right) {}
};
int val_cnt = 0;
int p = 0; // samllest p, that 2^p >= val_cnt
vector<Node*> head; // size = p+1
Skiplist() {
head.emplace_back(new Node(NINF));
}
bool search(int target) {
int lev = head.size()-1;
// 高层索引头为空,移除
while (lev && head[lev]->right == NULL) {
delete head[lev];
head.pop_back();
lev--;
}
Node* cur = head[lev];
while (cur) {
// 右侧节点小于target 右移动
while (cur->right && cur->right->val < target) cur = cur->right;
// 右侧为target,找到答案
if (cur->right && cur->right->val == target) return true;
//否则进入下一层索引
cur = cur->down;
}
return false;
}
void add(int num) {
val_cnt++;
while ((1<<p) < val_cnt) p++;
// 获取建立索引层数,概率算法
int idx = rand_idx();
// 当前索引头不够
int lev = head.size()-1;
while (lev < idx) {
head.push_back(new Node(NINF, head.back()));
lev++;
}
Node* cur = head[lev], *up = NULL;
while (cur) {
// 右侧节点小于num 右移动
while (cur->right && cur->right->val < num) cur = cur->right;
// idx及以下建立索引
if (lev<=idx) {
cur->right = new Node(num, NULL, cur->right);
if (up != NULL) up->down = cur->right;
up = cur->right;
}
//进入下一层索引
cur = cur->down;
lev--;
}
}
bool erase(int num) {
int lev = head.size()-1;
// 高层索引头为空,移除
while (lev && head[lev]->right == NULL) {
delete head[lev];
head.pop_back();
lev--;
}
bool rt = false;
Node* cur = head[lev];
while (cur) {
// 右侧节点小于num 右移动
while (cur->right && cur->right->val < num) cur = cur->right;
// 右侧为num,删除之
if (cur->right && cur->right->val == num) {
rt = true;
Node* e = cur->right;
cur->right = e->right;
delete e;
}
//否则进入下一层索引
cur = cur->down;
}
val_cnt--;
while (p && (1<<p-1) >= val_cnt) p--;
return rt;
}
void awesome_print() {
int lev = head.size()-1;
cout << "val_cnt: " << val_cnt << "\\tlev: " << lev << "\\tp: " << p << endl;
map<Node*,int> mp;
set<Node*> st;
for (int i=lev; i>=0; i--) {
Node* cur = head[i];
while (cur) {
if (!st.count(cur)) {
Node* t = cur;
st.insert(t);
int c = 0;
while (t->down) st.insert(t = t->down), c++;
mp[t] = c;
}
cur = cur->right;
}
}
function<void(int)> dfs = [&](int l) {
if (l > lev) return;
dfs(l+1);
Node *t = head[0];
while (t) {
cout << "\\t";
if (l<=mp[t]) {
if (t->val == NINF) {
cout << "HEAD";
} else {
cout << t->val;
}
}
t = t->right;
}
cout << endl;
};
dfs(0);
}
private:
int rand_idx() {
int sz = 1<<p;
// int v = rand()%sz;
int v = random(0, sz-1);
int rt = 0;
while (v) {
rt++;
v >>= 1;
}
/*
sz = 8
0 : 0
1 : 1
2 : 2 3
4 : 4 5 6 7
*/
return rt;
}
};
void sol() {
Skiplist sl;
vector<int> a;
for (int i=0; i<20; i++) {
a.push_back(random(0, 100));
}
cout << "add seq " << a << endl;
for (int i:a) {
sl.add(i);
cout << "add " << i << endl;
sl.awesome_print();
}
random_shuffle(a.begin(), a.end());
cout << "del seq " << a << endl;
for (int i:a) {
sl.erase(i);
cout << "erase " << i << endl;
sl.awesome_print();
}
}
int main() {
sol();
return 0;
}