力扣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;
    }
};
相关推荐
努力学习编程的伍大侠11 分钟前
基础排序算法
数据结构·c++·算法
ThisIsClark15 分钟前
【后端面试总结】MySQL主从复制逻辑的技术介绍
mysql·面试·职场和发展
XiaoLeisj39 分钟前
【递归,搜索与回溯算法 & 综合练习】深入理解暴搜决策树:递归,搜索与回溯算法综合小专题(二)
数据结构·算法·leetcode·决策树·深度优先·剪枝
Jasmine_llq1 小时前
《 火星人 》
算法·青少年编程·c#
闻缺陷则喜何志丹1 小时前
【C++动态规划 图论】3243. 新增道路查询后的最短距离 I|1567
c++·算法·动态规划·力扣·图论·最短路·路径
Lenyiin1 小时前
01.02、判定是否互为字符重排
算法·leetcode
鸽鸽程序猿2 小时前
【算法】【优选算法】宽搜(BFS)中队列的使用
算法·宽度优先·队列
Jackey_Song_Odd2 小时前
C语言 单向链表反转问题
c语言·数据结构·算法·链表
Watermelo6172 小时前
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
开发语言·前端·javascript·算法·数据挖掘·数据分析·ecmascript