列表 - 数据结构训练营

为了演示内存和数据结构之间的交互,我们将先实现一个列表。 列表是有序值的序列,其中可能包含重复的值。 JavaScript 的 Array 对象是用于构造数组的全局对象,数组是类似于列表的高阶对象。但 JavaScript 里并没有列表的实现,在这里将开始表的简单数组实现。 实现列表数据结构可以提供以下一些运算: 一个生成空列表的构造函数; 确定列表元素的运算; 向列表末端插入元素的运算; 删除列表末端元素的运算; 向列表前端加入元素的运算; 删除列表前端元素的运算; 下面我们将依次介绍其实现。 一个生成空列表的构造函数 我们从一个空的内存块开始,用一个普通的 JavaScript 数组来表示它,同时存储列表的长度。 请注意,我们单独存储了长度,因为在现实生活中,“内存”不能直接读取其长度。 constructor() { this.memory = []; this.length = 0; } 确定列表元素的运算 我们需要一种从列表中检索数据的方法。 使用数组实现,可以非常快速地访问内存,因为分配了一块连续的内存来存储数组,利用元素的索引(index)可以计算出该元素对应的存储地址。 列表访问是常数 O(1) - “太棒了!!” 请在右边的代码中实现该操作。 get(address) { } 因为列表有顺序,所以可以在开头、中间或结尾插入元素。 对于我们的实现,将专注于使用以下四种方法在列表的开头或结尾添加\删除元素: - push - 将元素添加到末尾 - pop - 删除末尾的元素 - unshift - 将元素添加到开始 - shift - 删除第一个元素 向列表末端插入元素的运算 先来看 push,需要实现将元素添加到列表末尾的方法。 很简单,直接在列表末尾后面的一个地址中添加一个元素就可以了。因为存储了长度,所以很容易定位。别忘了给长度加一。 将一个元素 push 列表的末尾是常数 O(1) - “太棒了!!” push(value) { } 删除列表末端元素的运算 接下来,需要从列表末尾删除元素的方法 pop。 与 push 类似,需要做的就是删除列表末尾地址处的值。 然后减少长度。 不要直接使用数组的 pop 方法,可以使用 delete 方法。delete 操作符用于删除对象的某个属性,而数组元素可以看做是数组对象的属性,如: delete this.memory[lastAddress]; 将会删除 memory 的第 lastAddress+1 个元素。 从列表末尾弹出一个项目是常数 O(1) - “太棒了!!” pop() { return value; } push 和 pop 都在列表的末尾进行操作,总的来说是非常简单的操作,因为它们不需要关心列表的其余部分。让我们看看当我们在列表的开头使用 unshift 和 shift 操作时会发生什么。 向列表前端加入元素的运算 要在列表的开头添加一个新元素,需要将所有值向后移一个位置来为要插入的元素腾出空间。 从列表的开头移删除一个元素的复杂度是线性的 O(N) - “还行”。 shift() { return value; }
使用正确的数据结构可以大大简化原本复杂的逻辑。如果很注重性能或想节约内存,那么就需要选择正确的数据结构。来和我一起用 JavaScript 语言来实现一些常用数据结构吧。


运行