力扣1206--跳表

1206. 设计跳表 - 力扣(LeetCode)

挑战一下hard,果然难搞

参考 跳表的原理与实现 图解_跳表实现-CSDN博客

代码如下:

cpp 复制代码
struct Node{
    Node(Node* _right, Node* _down, int _val) :
        right(_right), down(_down), val(_val){}
    Node* right;
    Node* down;
    int val;
};//Node节点的类型,一个右指针,一个向下的指针
class Skiplist {
private:
    Node* head;
    const static int max_Level = 32;//最大层数
    vector<Node*> pathList;//插入节点的时候,遍历查找小于target的最后一个Node,存在pathList中
public:
    Skiplist() {
        head = new Node(NULL, NULL, -1);//创建一个头结点进来
        pathList.reserve(max_Level);//使用reserve提前分配空间,每次都自动扩展32个
    }
    
    bool search(int target) {
        Node* p = head;
        while(p)
        {

            while(p->right && p->right->val < target)
                p = p->right;
            if(!p->right || p->right->val > target)
                p = p->down;
            else
                return true;
        }
        return false;
    }
    
    void add(int num) {
        Node* p = head;
        pathList.clear();
        while(p)
        {
            //从左往右查找,直到不小于num为止
            while(p->right != NULL && p->right->val < num)
                p = p->right;
            pathList.push_back(p);
            p = p->down;
            /*
            //如果到达边界,往下一层找
            //这地方放在尾部主要是为了后边插入的时候,pop_back出来,
            //刚好是从最底层插入,然后再往上更新
            if(p->right != NULL && p->right->val > num)
            {
                //如果右节点的值域大于num,那么把它放入list尾部
                pathList.push_back(p);
                //更新p
                p = p->down;
            }
            //if(p->right == nullptr)这里是个错误,上边if代码执行之后,会执行这个if
            //上述代码会改变p的值,所以这里不判断p值,直接访问p->right会导致指针越界
            //如果是其他情况,把当前的p放入list尾部
            else
            {
                pathList.push_back(p);
                p = p->down;
            }*/
        }
        //第一次把插入的flag置为true,从最底层开始,肯定是要插入的。
        bool insert_Up = true;
        Node* downNode = nullptr;//用于记录更新此次插入后的节点,如果上层需要插节点,用此更新
        while(insert_Up && pathList.size() > 0)
        {
            Node* tmpNode = pathList.back();//拿到最后一个节点
            pathList.pop_back();//弹出
            //把新节点插入当前层
            //建立新节点,同时更新right和down
            Node* insert_Node = new Node(tmpNode->right, downNode, num);
            //把新节点插入层中
            tmpNode->right = insert_Node;
            insert_Up = (rand() & 1 ) == 0;//每次有50%的概率需要提取到上一层
        }
        //如果需要在最上一层加层
        if(insert_Up)
        {
            //创建一个新Node,right为head,down为上次的downNode
            Node* tmpNode = new Node(nullptr, nullptr, -1);
            tmpNode->right = head;
            tmpNode->down = downNode;
            //更新head
            head = tmpNode;
        }

    }
    
    bool erase(int num) {
        Node* p = head;
        bool seen = false;
        while(p)
        {
            while(p->right && p->right->val < num)
                p = p->right;
            if(!p->right || p->right->val > num)
                p = p->down;
            else
            {
                seen = true;
                p->right = p->right->right;
                p = p->down;//没有这一行也可以,有的话可以加快查询
            }
        }
        return seen;
    }
};
相关推荐
shehuiyuelaiyuehao1 小时前
算法31,前缀和,可被k整除的子数组
数据结构·python·算法
测试19982 小时前
如何用appium搭建Android自动化测试框架?
自动化测试·软件测试·python·测试工具·职场和发展·appium·测试用例
203号居民3 小时前
LeetCode hot 100 — 141. 环形链表2
算法·leetcode·链表
玖玥拾3 小时前
LeetCode 202 快乐数
算法·leetcode
LuminousCPP3 小时前
数据结构-二叉树(六):BFS层序遍历与完全二叉树判断|复用链式队列 + (N_0=N_2+1) 性质证明
c语言·数据结构·笔记·算法·二叉树·宽度优先
ZhouDevin4 小时前
算法论文/数据集3——CLD(TMLR2025)压缩训练集,仅保留对验证集有益的样本
人工智能·深度学习·算法·计算机视觉
Tim_105 小时前
【LeetCode】29、两数相除
算法·leetcode·职场和发展
船厂电气自动化ai大模型5 小时前
AI大模型与数学/第63课:矩阵定义、矩阵加法、标量乘法(逐级精讲)
数据结构·人工智能·深度学习·线性代数·算法
余额瞒着我当琳6 小时前
算法修炼 chapter 2 双指针进阶、盛最多水的容器、有效三角形的个数、两数之和、三数之和、四数之和
算法
你压到我腿毛了6666 小时前
C语言冒泡算法(Bubble sort)
c语言·数据结构·算法