当前位置:首页 > JavaScript

JS实现跳表

2026-02-28 19:17:59JavaScript

跳表(Skip List)简介

跳表是一种基于概率的平衡数据结构,通过多层链表实现高效查找、插入和删除操作,时间复杂度为 $O(\log n)$。其核心思想是通过“跳跃”式访问节点减少遍历次数。

跳表节点结构

跳表节点包含值(value)和指向后续节点的指针数组(forward)。每一层对应一个指针,用于在不同层级间跳跃。

JS实现跳表

class SkipListNode {
  constructor(value, level) {
    this.value = value;
    this.forward = new Array(level).fill(null); // 初始化各层指针为null
  }
}

跳表类实现

跳表类需初始化头节点、最大层级和概率因子(通常为0.5)。

JS实现跳表

class SkipList {
  constructor() {
    this.maxLevel = 16; // 最大层数
    this.head = new SkipListNode(null, this.maxLevel); // 头节点
    this.level = 1; // 当前有效层数
    this.p = 0.5; // 概率因子
  }

  // 随机生成节点层数
  randomLevel() {
    let level = 1;
    while (Math.random() < this.p && level < this.maxLevel) {
      level++;
    }
    return level;
  }
}

查找操作

从最高层开始查找,逐步向下直至找到目标或确认不存在。

search(value) {
  let current = this.head;
  for (let i = this.level - 1; i >= 0; i--) {
    while (current.forward[i] && current.forward[i].value < value) {
      current = current.forward[i];
    }
  }
  current = current.forward[0];
  return current && current.value === value ? current : null;
}

插入操作

  1. 确定插入位置并记录每层的前驱节点。
  2. 随机生成新节点层数,更新前驱节点的指针。
insert(value) {
  const update = new Array(this.maxLevel).fill(null);
  let current = this.head;

  for (let i = this.level - 1; i >= 0; i--) {
    while (current.forward[i] && current.forward[i].value < value) {
      current = current.forward[i];
    }
    update[i] = current;
  }

  const level = this.randomLevel();
  if (level > this.level) {
    for (let i = this.level; i < level; i++) {
      update[i] = this.head;
    }
    this.level = level;
  }

  const newNode = new SkipListNode(value, level);
  for (let i = 0; i < level; i++) {
    newNode.forward[i] = update[i].forward[i];
    update[i].forward[i] = newNode;
  }
}

删除操作

类似插入,需先定位节点并更新前驱指针。

delete(value) {
  const update = new Array(this.maxLevel).fill(null);
  let current = this.head;

  for (let i = this.level - 1; i >= 0; i--) {
    while (current.forward[i] && current.forward[i].value < value) {
      current = current.forward[i];
    }
    update[i] = current;
  }

  current = current.forward[0];
  if (!current || current.value !== value) return false;

  for (let i = 0; i < this.level; i++) {
    if (update[i].forward[i] !== current) break;
    update[i].forward[i] = current.forward[i];
  }

  while (this.level > 1 && !this.head.forward[this.level - 1]) {
    this.level--;
  }
  return true;
}

复杂度分析

  • 空间复杂度: $O(n \log n)$(最坏情况),实际接近 $O(n)$。
  • 时间复杂度: 查找、插入、删除均为 $O(\log n)$。

应用场景

  • Redis的有序集合(ZSET)底层实现。
  • 替代平衡树(如AVL、红黑树)的简化方案。

标签: JS
分享给朋友:

相关文章

JS实现跳表

JS实现跳表

跳表的基本概念 跳表(Skip List)是一种基于概率的数据结构,允许快速查询、插入和删除操作,时间复杂度平均为O(log n)。它通过多层链表实现,每一层都是下一层的子集,高层链表跳过多个元素,从…

JS如何调用react组件

JS如何调用react组件

调用React组件的常见方法 在JavaScript中调用React组件通常涉及以下几种场景和方式: 直接渲染组件 通过ReactDOM.render()方法将组件渲染到DOM节点: impo…

JS如何实现左右滑动

JS如何实现左右滑动

实现左右滑动的方法 使用 touchstart、touchmove 和 touchend 事件监听触摸操作,计算滑动距离和方向。 let startX, moveX; element.addEv…

JS实现日期滚动选择

JS实现日期滚动选择

实现日期滚动选择的基本思路 使用HTML、CSS和JavaScript创建一个日期滚动选择器,允许用户通过滚动选择年、月、日。核心是通过监听滚动事件,动态更新显示的值。 HTML结构 创建一个包含…

用JS实现冰墩墩

用JS实现冰墩墩

以下是用JavaScript绘制冰墩墩的几种实现方法,结合Canvas绘图和SVG路径数据: 使用Canvas绘制基础轮廓 const canvas = document.createElement…

JS节流和防抖的实现

JS节流和防抖的实现

节流(Throttle)的实现 节流是指在一定时间间隔内,函数最多执行一次。常用于限制高频事件的触发频率,如滚动事件、窗口调整等。 function throttle(func, delay) {…