一、链表
线性结构,但不同与数组,链表中的元素在内存中不是连续放置的,每一个元素是由一个元素本身的节点和指向下一个元素的引用组成,相对于传统的数组,链表的好处在于,添加或删除元素的时候不需要移动其他元素,所以链表在频繁插入或者删除的场景下效率较高
二、js实现
1.每个节点存储两个值,分别是当前节点的值val
和指向下一个节点的指针next
function Node(val) {
this.val = val;
this.next = null;
}
2.设计一个构造函数ArrayLisrt,有两个属性,分别是链表的长度length
和指向链表第一个节点的指针head
function ArrayList() {
this.length = 0;
this.head = null;
}
3.设计链表主要实现以下四个方法:
getNodeByIndex: 根据下标查找对应的节点
append: 在链表的尾部增加一个新的节点
insert: 在某个位置插入一个节点
removeAt: 删除某个位置的节点
function ArrayList() {
this.length = 0;
this.head = null;
}
function Node(val) {
this.val = val;
this.next = null;
}
ArrayList.prototype.getNodeByIndex = function (idx) {
if (typeof idx !== "number") throw new Error("id is not valid");
if (idx < 0 || idx >= this.length) return null;
let cur = this.head;
while (idx--) {
cur = cur.next;
}
return cur;
};
ArrayList.prototype.append = function (val) {
let node = new Node(val);
if (this.length === 0) {
this.head = node;
} else {
this.getNodeByIndex(this.length - 1).next = node;
}
this.length++;
};
ArrayList.prototype.insert = function (pos, val) {
if (pos < 0 || pos >= this.length) return false;
let node = new Node(val);
if (pos === 0) {
node.next = this.head;
this.head = node;
} else {
let prev = this.getNodeByIndex(pos - 1);
node.next = prev.next;
prev.next = node;
}
this.length++;
return true;
};
ArrayList.prototype.removeAt = function (pos) {
if (pos < 0 || pos >= this.length) return false;
if (pos === 0) {
this.head = this.head.next;
} else {
let prev = this.getNodeByIndex(pos - 1);
prev.next = prev.next.next;
}
this.length--;
return true;
};