数据结构与算法--跳表

跳表定义:

        跳表(Skip List)是一种用于有序元素集合的数据结构,它通过层次化的链表结构在查找、插入和删除操作上具有较高的平均时间复杂度。

跳表特点:

  • 简单性和易实现性:相对于平衡树等复杂的数据结构,跳表的实现比较简单。它由多个层次的链表组成,每个层次的链表是下一个层次链表的子集,从而形成一种层次化的结构。
  • 平均时间复杂度:在跳表中,插入、删除和搜索的平均时间复杂度都为 O(log n),其中 n 是元素个数。这是通过每一级链表跳跃来实现的,类似于二分查找。
  • 无需平衡操作:与平衡树不同,跳表的平衡是通过随机化生成层次和节点来实现的,因此不需要像平衡树那样频繁地进行旋转或平衡操作。
  • 空间效率:虽然跳表相对于普通链表需要更多的空间来存储层次结构,但它的空间复杂度仍然是线性的,因为每层的节点数量是平均减少的。
  • 可拓展性:跳表可以轻松地在现有的基础上进行扩展。当数据量增加时,可以动态地增加层次,从而保持跳表的性能。
  • 局部性原理:跳表利用了局部性原理,即在内存访问中,往往会访问附近的数据。通过层次结构,跳表在查找时可以更快地跳过不必要的部分,从而减少了访问的数据量。
  • 并发性:由于跳表的结构相对简单,它在并发环境下可以更容易地实现锁粒度更小的操作,从而在一些情况下获得更好的并发性能。

代码实现:

  1. 定义跳表节点类,每插入一个元素,都会为该元素创建一个SkipNode与之对应
class SkipNode {
public:
    //跳表节点保存的值
    int value;
    //跳表节点每一层的指针
    std::vector<SkipNode*> forward;

    SkipNode(int val, int level) : value(val), forward(level + 1, nullptr) {}
};

     2. 定义跳表类

class SkipList {
private:
    //跳表的最大层数
    int MAX_LEVEL;
    //当前跳表的最大层数
    int level;
    //跳表的头节点
    SkipNode* head;
    //新插入一个节点时,随机产生一个与之对应的层数
    int randomLevel() {
        int lvl = 1;
        while (rand() % 2 == 0 && lvl < MAX_LEVEL) {
            lvl++;
        }
        return lvl;
    }

public:
    //初始化,先创建对应的头结点
    SkipList(int maxLevel) : MAX_LEVEL(maxLevel), level(0) {
        head = new SkipNode(-1, MAX_LEVEL);
    }
    //在跳表中插入一个元素
    void insert(int value) {
        int newLevel = randomLevel();
        if (newLevel > level) {
            level = newLevel;
        }

        SkipNode* newNode = new SkipNode(value, newLevel);
        SkipNode* current = head;

        for (int i = level; i >= 0; i--) {
            while (current->forward[i] != nullptr && current->forward[i]->value < value){
                current = current->forward[i];
            }
            if (i <= newLevel) {
                newNode->forward[i] = current->forward[i];
                current->forward[i] = newNode;
            }
        }
    }
    //在跳表中移除一个元素
    void remove(int value) {
        SkipNode* current = head;

        for (int i = level; i >= 0; i--) {
            while (current->forward[i] != nullptr && current->forward[i]->value < value){
                current = current->forward[i];
            }
            if (current->forward[i] != nullptr && current->forward[i]->value == value) {
                SkipNode* temp = current->forward[i];
                current->forward[i] = temp->forward[i];
                delete temp;
            }
        }
    }
    //在跳表中查找一个元素
    bool search(int value) {
        SkipNode* current = head;

        for (int i = level; i >= 0; i--) {
            while (current->forward[i] != nullptr && current->forward[i]->value < value){
                current = current->forward[i];
            }
            if (current->forward[i] != nullptr && current->forward[i]->value == value) {
                return true;
            }
        }

        return false;
    }

};

        通过以上代码,可以简单实现保存元素为整型的跳表,涵盖插入、删除和搜索操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值