题目:1206. 设计跳表
题解:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
Redis内部数据结构详解(6)——skiplist - 铁蕾的个人博客
跳表:复杂链式结构:跳表_INGNIGHT的博客-CSDN博客
class Skiplist {
int MAX_LEVEL;
public:
Skiplist() {
MAX_LEVEL = 16;
_max_level = 1;
}
bool search(int target) {
std::vector<Node*> prevs = find(target);
return prevs[0]->forward[0] && prevs[0]->forward[0]->val == target ? true : false;
}
void add(int num) {
int level = get_level();
_max_level = std::max(_max_level, level);
//cout << _max_level << endl;
std::vector<Node*> prevs = find(num);
Node * node = new (std::nothrow) Node;
node->val = num;
for (int i = level-1; i >= 0; --i) {
node->forward[i] = prevs[i]->forward[i];
prevs[i]->forward[i] = node;
}
}
bool erase(int num) {
std::vector<Node*> prevs = find(num);
if (!prevs[0]->forward[0] || prevs[0]->forward[0]->val != num) {
return false;
}
for (int i = _max_level-1; i >= 0; --i) {
if (prevs[i]->forward[i] && prevs[i]->forward[i]->val == num) {
prevs[i]->forward[i] = prevs[i]->forward[i]->forward[i];
}
}
//delete prevs[0]->forward[0];
while (_max_level > 1 && !head.forward[_max_level-1]) {
--_max_level;
}
return true;
}
struct Node {
Node() {
val = -1;
forward.resize(16, nullptr);
}
std::vector<Node*> forward;
int val;
};
int get_level() {
int level = 1;
while (random() / RAND_MAX < 0.5 && level < MAX_LEVEL) {
++level;
}
// 最大的高度也就是0~15
return level;
}
std::vector<Node*> find(int target) {
Node* cur = &head;
std::vector<Node*> result(_max_level, nullptr);
for (int i = _max_level-1; i >= 0; --i) {
while (cur->forward[i] && cur->forward[i]->val < target) {
cur = cur->forward[i];
}
result[i] = cur;
}
return result;
}
Node head;
int _max_level;
};
/**
* Your Skiplist object will be instantiated and called as such:
* Skiplist* obj = new Skiplist();
* bool param_1 = obj->search(target);
* obj->add(num);
* bool param_3 = obj->erase(num);
*/
static const int SKIPLIST_P_VAL = RAND_MAX / 2, MAX_LEVEL = 16;
class Skiplist {
public:
struct Node {
int val;
vector<Node *> level;
Node(int val, int size = MAX_LEVEL) : val(val), level(size) {}
};
Node head;
int maxlevel = 1;
Skiplist() : head(INT_MIN, MAX_LEVEL) {}
// ~Skiplist() { delte all nodes. }
// essentially the same as _search
bool search(int target) {
Node * prev = _search(target)[0];
return prev->level[0] && prev->level[0]->val == target;
}
vector<Node *> _search(int key) {
Node * cur = &head;
vector<Node *> prevs(MAX_LEVEL);
// through every level, from top to bottom
for (int i = maxlevel - 1; i >= 0; i--) {
// through elements in the current level with smaller value
while (cur->level[i] && cur->level[i]->val < key)
cur = cur->level[i];
prevs[i] = cur;
}
return prevs;
}
void add(int num) {
auto prevs = _search(num);
int level = random_level();
// update maxlevel and prevs
if (level > maxlevel) {
for (int i = maxlevel; i < level; i++)
prevs[i] = &head;
maxlevel = level;
}
Node * cur = new Node(num, level);
// from prev->next to prev->cur->next
for (int i = level - 1; i >= 0; i--) {
cur->level[i] = prevs[i]->level[i];
prevs[i]->level[i] = cur;
}
// if there is backward pointer, need to set both cur and cur.next 's back pointer
// Note that the back poinet of the first valid node is nullptr instead of head
}
bool erase(int num) {
auto prevs = _search(num);
if (!prevs[0]->level[0] || prevs[0]->level[0]->val != num)
return false;
Node * del = prevs[0]->level[0];
// from prev->cur->next to prev->next
for (int i = 0; i < maxlevel; i++)
if (prevs[i]->level[i] == del)
prevs[i]->level[i] = del->level[i];
delete del;
// update maxlevel.
while (maxlevel > 1 && !head.level[maxlevel - 1])
maxlevel--;
// if there is backward poinet, need to set cur.next.back to cur.back
return true;
}
static int random_level() {
int level = 1;
while (rand() < SKIPLIST_P_VAL && level < MAX_LEVEL) level++;
return level;
}
};
constexpr int MAX_LEVEL = 32;
constexpr double P_FACTOR = 0.25;
struct SkiplistNode {
int val;
vector<SkiplistNode *> forward;
SkiplistNode(int _val, int _maxLevel = MAX_LEVEL) : val(_val), forward(_maxLevel, nullptr) {
}
};
class Skiplist {
private:
SkiplistNode * head;
int level;
mt19937 gen{random_device{}()};
uniform_real_distribution<double> dis;
public:
Skiplist(): head(new SkiplistNode(-1)), level(0), dis(0, 1) {
}
bool search(int target) {
std::vector<SkiplistNode*> update = find(target);
return update[0]->forward[0] && update[0]->forward[0]->val == target ? true : false;
}
void add(int num) {
/*vector<SkiplistNode *> update(MAX_LEVEL, head);
SkiplistNode *curr = this->head;
for (int i = level - 1; i >= 0; i--) {
// 找到第 i 层小于且最接近 num 的元素
while (curr->forward[i] && curr->forward[i]->val < num) {
curr = curr->forward[i];
}
update[i] = curr;
}*/
int lv = randomLevel();
level = max(level, lv);
vector<SkiplistNode *> update = find(num);
SkiplistNode *newNode = new SkiplistNode(num, lv);
for (int i = lv-1; i >= 0; --i) {
/* 对第 i 层的状态进行更新,将当前元素的 forward 指向新的节点 */
newNode->forward[i] = update[i]->forward[i];
update[i]->forward[i] = newNode;
}
}
bool erase(int num) {
vector<SkiplistNode *> update = find(num);
SkiplistNode* curr = update[0]->forward[0];
if (!curr || curr->val != num) {
return false;
}
for (int i = level-1; i >= 0; --i) {
if (update[i]->forward[i] == curr) {
/* 对第 i 层的状态进行更新,将 forward 指向被删除节点的下一跳 */
update[i]->forward[i] = curr->forward[i];
}
}
delete curr;
/* 更新当前的 level */
while (level > 1 && head->forward[level - 1] == nullptr) {
level--;
}
return true;
}
int randomLevel() {
int lv = 1;
/* 随机生成 lv */
while (dis(gen) < P_FACTOR && lv < MAX_LEVEL) {
lv++;
}
return lv;
}
std::vector<SkiplistNode*> find(int target) {
SkiplistNode* cur = head;
std::vector<SkiplistNode*> result(level, nullptr);
for (int i = level-1; i >= 0; --i) {
while (cur->forward[i] && cur->forward[i]->val < target) {
cur = cur->forward[i];
}
result[i] = cur;
}
return result;
}
};
陈小玉代码:
#include<cstdio>
#include<cstdlib>//rand()
#include<ctime>//time()
using namespace std;
const int INF=0x7fffffff;
const float P=0.5f;
const int MAX_LEVEL=16;
using namespace std;
typedef struct Node{
int val;
struct Node *forward[MAX_LEVEL];
}*Nodeptr;
Nodeptr head,updata[MAX_LEVEL];
int level;
void Init(){
level=0;
head=new Node;
for(int i=0;i<MAX_LEVEL;i++)
head->forward[i]=NULL;
head->val=-INF;
}
int RandomLevel(){//随机产生插入元素高度
int lay=0;
//printf("%d\n",rand());
//printf("%d\n",RAND_MAX);
while((float)rand()/RAND_MAX<P&&lay<MAX_LEVEL-1)//rand()产生的随机数范围是0~RAND_MAX
lay++;
return lay;
}
Nodeptr Find(int val){//查找最接近val的元素
Nodeptr p=head;
for(int i=level;i>=0;i--){
while(p->forward[i]&&p->forward[i]->val<val)
p=p->forward[i];
updata[i]=p;//记录搜索过程中各级走过的最大节点位置
}
return p;
}
void Insert(int val){
Nodeptr p,s;
int lay=RandomLevel();
printf("lay=%d\n",lay);
if(lay>level) //要插入的层 > 现有层数
level=lay;
p=Find(val); //查询
s=new Node;//创建一个新节点
s->val=val;
for(int i=0;i<MAX_LEVEL;i++)
s->forward[i]=NULL;
for(int i=0;i<=lay;i++){//插入操作
s->forward[i]=updata[i]->forward[i];
updata[i]->forward[i]=s;
}
}
void Delete(int val){
Nodeptr p=Find(val);
if(p->forward[0]&&p->forward[0]->val==val){
printf("%d\n",p->forward[0]->val);
for(int i=level;i>=0;i--){//删除操作
if(updata[i]->forward[i]&&updata[i]->forward[i]->val==val)
updata[i]->forward[i]=updata[i]->forward[i]->forward[i];
}
while(level>0&&!head->forward[level])//删除空链
level--;
}
}
void print(int i){//遍历
Nodeptr p=head->forward[i];
if(!p) return;
while(p){
printf("%d ",p->val);
p=p->forward[i];
}
printf("\n");
}
void printall(){//遍历所有层
for(int i=level;i>=0;i--)
printf("level %d: ",i),print(i);
}
void show(){
printf("Please select:\n");
printf("-----------------------------\n");
printf(" 1: 插入\n");
printf(" 2: 删除\n");
printf(" 3: 查找\n");
printf(" 4: 遍历\n");
printf(" 5: 遍历所有层\n");
printf(" 0: 退出\n");
printf("-----------------------------\n");
}
int main(){
//time函数返回从1970年1月1日0时开始到现在逝去的秒数
//可以利用srand((unsigned int)(time(NULL))的方法,产生不同的随机数种子,因为每一次运行程序的时间是不同的
srand((unsigned int)time(0));
Init();
int n,x;
show();
while(~scanf("%d",&n),n){
switch(n){
case 1:
scanf("%d",&x);
Insert(x);break;
case 2:
scanf("%d",&x);
Delete(x);break;
case 3:
scanf("%d",&x);
Nodeptr p;
p=Find(x);
if(p->forward[0]&&p->forward[0]->val==x)
printf("find success!\n");
else
printf("find fail!\n");
break;
case 4:
print(0);break;
case 5:
printall();break;
}
show();
}
return 0;
}