数据结构——环形数组

环形数组

start 指向第一个有效元素的索引,end 指向最后一个有效元素的下一个位置索引。

注意: start是闭区间,先左移后赋值,先赋值(null)后右移;end是开区间,先赋值再右移,先左移再赋值(null)。

左移减一加size再取模,右移加一再取模。

JS代码实现:

复制代码
class CycleArray {
constructor(size = 1) {
    this.size = size;
    this.arr = new Array(size);
    // start 指向第一个有效元素的索引,闭区间
    this.start = 0;
    // 切记 end 是一个开区间,
    // 即 end 指向最后一个有效元素的下一个位置索引
    this.end = 0;
    this.count = 0;
}

resize(newSize) {
    // 创建新的数组
    var newArr = new Array(newSize);
    // 将旧数组的元素复制到新数组中
    for (var i = 0; i < this.count; i++) {
        newArr[i] = this.arr[(this.start + i) % this.size];
    }
    this.arr = newArr;
    // 重置 start 和 end 指针
    this.start = 0;
    this.end = this.count;
    this.size = newSize;
}

// 在数组头部添加元素,时间复杂度 O(1)
addFirst(val) {
    // 当数组满时,扩容为原来的两倍
    if (this.isFull()) {
        this.resize(this.size * 2);
    }
    // 因为 start 是闭区间,所以先左移,再赋值
    this.start = (this.start - 1 + this.size) % this.size;
    this.arr[this.start] = val;
    this.count++;
}

// 删除数组头部元素,时间复杂度 O(1)
removeFirst() {
    if (this.isEmpty()) {
        throw new Error("Array is empty");
    }
    // 因为 start 是闭区间,所以先赋值,再右移
    this.arr[this.start] = null;
    this.start = (this.start + 1) % this.size;
    this.count--;
    // 如果数组元素数量减少到原大小的四分之一,则减小数组大小为一半
    if (this.count > 0 && this.count == this.size / 4) {
        this.resize(this.size / 2);
    }
}

// 在数组尾部添加元素,时间复杂度 O(1)
addLast(val) {
    if (this.isFull()) {
        this.resize(this.size * 2);
    }
    // 因为 end 是开区间,所以是先赋值,再右移
    this.arr[this.end] = val;
    this.end = (this.end + 1) % this.size;
    this.count++;
}

// 删除数组尾部元素,时间复杂度 O(1)
removeLast() {
    if (this.isEmpty()) {
        throw new Error("Array is empty");
    }
    // 因为 end 是开区间,所以先左移,再赋值
    this.end = (this.end - 1 + this.size) % this.size;
    this.arr[this.end] = null;
    this.count--;
    // 缩容
    if (this.count > 0 && this.count == this.size / 4) {
        this.resize(this.size / 2);
    }
}

// 获取数组头部元素,时间复杂度 O(1)
getFirst() {
    if (this.isEmpty()) {
        throw new Error("Array is empty");
    }
    return this.arr[this.start];
}

// 获取数组尾部元素,时间复杂度 O(1)
getLast() {
    if (this.isEmpty()) {
        throw new Error("Array is empty");
    }
    // end 是开区间,指向的是下一个元素的位置,所以要减 1
    return this.arr[(this.end - 1 + this.size) % this.size];
}

isFull() {
    return this.count === this.size;
}

size() {
    return this.count;
}

isEmpty() {
    return this.count === 0;
}
}
相关推荐
前端梭哈攻城狮11 分钟前
uniapp图片上传添加水印/压缩/剪裁
前端·javascript·vue.js
天涯学馆11 分钟前
前后端分离的 API 设计:技术深度剖析
前端·javascript·面试
爱编程的喵13 分钟前
深入理解JavaScript原型机制:从Java到JS的面向对象编程之路
java·前端·javascript
独立开阀者_FwtCoder13 分钟前
Cursor 1.0 重磅发来袭(毛骨悚然,开始学习你如何编码)
前端·javascript·github
五点六六六18 分钟前
一些关于TreeShaking的AST的理解
前端·javascript·前端工程化
aichitang202439 分钟前
矩阵详解:从基础概念到实际应用
线性代数·算法·矩阵
海盐泡泡龟1 小时前
“组件、路由懒加载”,在 Vue3 和 React 中分别如何实现? (copy)
前端·javascript·react.js
coding随想1 小时前
深入浅出WebGL:在浏览器中解锁3D世界的魔法钥匙
javascript
OpenCSG1 小时前
电子行业AI赋能软件开发经典案例——某金融软件公司
人工智能·算法·金融·开源
踢足球的,程序猿2 小时前
从 Vue 2.0 进阶到 Vue 3.0 的核心技术解析指南
前端·javascript·vue.js·前端框架·html