当前位置:首页 > JavaScript

JS实现跳表

2026-02-28 19:17:59JavaScript

跳表(Skip List)简介

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

跳表节点结构

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

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

跳表类实现

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

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;
  }
}

删除操作

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

JS实现跳表

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如何访问react内部的数据

JS如何访问react内部的数据

访问 React 组件内部数据的方法 在 React 中,组件内部的数据通常通过 state 或 props 管理。以下是几种常见的访问方式: 通过 state 访问数据 React 组件的内部状态…

JS如何实现左右滑动

JS如何实现左右滑动

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

JS能实现跨平台吗

JS能实现跨平台吗

JavaScript 的跨平台能力 JavaScript 是一种高度灵活的脚本语言,通过不同运行时环境和工具链可以实现跨平台开发。以下是其跨平台能力的核心实现方式: 浏览器环境 JavaScript…

JS实现GPS

JS实现GPS

GPS定位的基本原理 GPS定位主要通过浏览器提供的Geolocation API实现。该API允许网页获取用户设备的地理位置信息,前提是用户授权同意。位置信息通常来源于设备的GPS模块、Wi-Fi或…

动态实现JS

动态实现JS

动态实现 JavaScript 的方法 动态加载脚本 通过创建 script 元素并插入到 DOM 中实现动态加载。例如: const script = document.createEleme…

JS实现哀悼

JS实现哀悼

实现网页哀悼效果的方法 在网页上实现哀悼效果通常指将页面整体调整为黑白或灰色调,以示哀悼。以下是几种常见的实现方式: CSS滤镜实现 通过CSS的filter属性可以快速将整个页面转为灰度。将以下代…