为了演示内存和数据结构之间的交互,我们将先实现一个列表。
列表是有序值的序列,其中可能包含重复的值。
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;
}
运行