单向链表
class Node {
constructor(element) {
this.element = element;
this.next = null;
}
}
class LinkedList {
constructor() {
this.size = 0;
this.head = null;
}
/**
* @method 尾部追加数据
* @param {any} element 追加数据
*/
append(element) {
let node = new Node(element);
if (this.head === null) {
this.head = node;
} else {
let current = this.getNode(this.size - 1);
current.next = node;
}
this.size++;
}
/**
* @method 指定位置追加数据
* @param {Number} position 位置
* @param {any} element 追加数据
*/
appendAt(position, element) {
if (position < 0 || position > this.size) {
throw new Error("position out range");
}
let node = new Node(element);
if (position === 0) {
node.next = this.head;
this.head = node;
} else {
let pre = this.getNode(position - 1);
node.next = pre.next;
pre.next = node;
}
this.size++;
}
/**
* @method 删除指定位置数据
* @param {Number} position 位置
*/
removeAt(position) {
if (position < 0 || position >= this.size) {
throw new Error("position out range");
}
let current = this.head;
if (position === 0) {
this.head = current.next;
} else {
let pre = this.getNode(position - 1);
current = pre.next;
pre.next = current.next;
}
this.size--;
}
/**
* @method 修改指定位置数据
* @param {Number} position 位置
* @param {any} element 追加数据
*/
update(position, element) {
if (position < 0 || position >= this.size) {
throw new Error("position out range");
}
let pre = this.getNode(position);
pre.element = element;
}
/**
* @method 查找指定位置数据
* @param {Number} position 位置
* @return {any} 返回数据
*/
getData(position) {
if (position < 0 || position >= this.size) {
throw new Error("position out range");
}
let pre = this.getNode(position);
return pre.element;
}
/**
* @method 查找指定数据索引
* @param {any} element
* @return {Number} 索引
*/
indexOf(element) {
let current = this.head;
// let i = 0;
// while (current) {
// if (current.element === element) return i;
// current = current.next;
// i++;
// }
for (let i = 0; i < this.size; i++) {
if (current.element === element) {
return i;
}
current = current.next;
}
return -1;
}
/**
* @method 返回链表长度
* @return {Number} 链表长度
*/
get length() {
return this.size;
}
getNode(index) {
if (index < 0 || index >= this.size) {
throw new Error("out range");
}
let current = this.head;
// let i = 0;
// while (i++ < index) {
// current = current.next;
// }
for (let i = 0; i < index; i++) {
current = current.next;
}
return current;
}
}
let ll = new LinkedList();
ll.append(1);
ll.append(2);
// ll.append(3);
// ll.append(4);
ll.appendAt(2, 3);
ll.appendAt(3, 4);
// ll.appendAt(3, 2);
// ll.removeAt(0);
// ll.removeAt(1);
console.log(ll.getData(3));
// console.log(ll.indexOf(1));
// console.log(ll.indexOf(2));
// console.log(ll.indexOf(3));
// console.log(ll.indexOf(4));
// console.log(ll.indexOf(5));
console.dir(ll, {
depth: 100,
});
console.log(ll.length);
// setTimeout(() => {
// ll.update(3, 9);
// console.dir(ll, {
// depth: 100,
// });
// }, 1000);
双向链表
class DoublyNode {
constructor(element) {
this.element = element;
this.prev = null;
this.next = null;
}
}
class DoublyLinkedList {
constructor() {
this.size = 0;
this.head = null;
this.tail = null;
}
/**
* @method 尾部追加数据
* @param {any} element 追加数据
*/
append(element) {
let node = new DoublyNode(element);
if (this.head === null) {
this.head = node;
this.tail = node;
} else {
this.tail.next = node;
node.prev = this.tail;
this.tail = node;
}
this.size++;
}
/**
* @method 指定位置追加数据
* @param {*} position 位置
* @param {*} element 追加数据
*/
appendAt(position, element) {
if (position < 0 || position > this.size) {
throw new Error("position out range");
}
let node = new DoublyNode(element);
if (position === 0) {
if (this.head === null) {
this.head = node;
this.tail = node;
} else {
node.next = this.head;
this.head.perv = node;
this.head = node;
}
} else if (position === this.size) {
this.tail.next = node;
node.prev = this.tail;
this.tail = node;
} else {
let pre = this.getNode(position - 1);
pre.next = node;
node.prev = pre;
node.next = pre.next;
pre.prev = node;
}
this.size++;
}
/**
* @method 删除指定位置数据
* @param {*} position 位置
*/
removeAt(position) {
if (position < 0 || position >= this.size) {
throw new Error("position out range");
}
let current = this.head;
if (position === 0) {
if (this.size === 1) {
this.head = null;
this.tail = null;
} else {
this.head = current.next;
this.head.prev = null;
}
} else if (position === this.size - 1) {
this.tail.prev.next = null;
this.tail = this.tail.prev;
} else {
let pre = this.getNode(position - 1);
current = pre.next;
pre.next = current.next;
}
this.size--;
}
/**
* @method 修改指定位置数据
* @param {Number} position 位置
* @param {any} element 追加数据
* TODO: 性能优化点 this.size / 2 > position 从头向后遍历, 反之则反
*/
update(position, element) {
if (position < 0 || position >= this.size) {
throw new Error("position out range");
}
let pre = this.getNode(position);
pre.element = element;
}
/**
* @method 查找指定位置数据
* @param {Number} position 位置
* @return {any} 返回数据
* TODO: 性能优化点 this.size / 2 > position 从头向后遍历, 反之则反
*/
getData(position) {
if (position < 0 || position >= this.size) {
throw new Error("position out range");
}
let pre = this.getNode(position);
return pre.element;
}
/**
* @method 查找指定数据索引
* @param {Number} element
* @return {Number} 索引
*/
indexOf(element) {
let current = this.head;
for (let i = 0; i < this.size; i++) {
if (current.element === element) {
return i;
}
current = current.next;
}
return -1;
}
/**
* @method 返回链表长度
* @return {Number} 链表长度
*/
get length() {
return this.size;
}
getNode(index) {
if (index < 0 || index >= this.size) {
throw new Error("out range");
}
let current = this.head;
for (let i = 0; i < index; i++) {
current = current.next;
}
return current;
}
}
let ll = new DoublyLinkedList();
ll.append(1);
ll.append(2);
ll.append(3);
ll.append(4);
// ll.appendAt(2, 3);
// ll.appendAt(3, 4);
// ll.appendAt(3, 2);
// ll.removeAt(0);
// ll.removeAt(1);
// console.log(ll.getData(3));
// console.log(ll.indexOf(1));
// console.log(ll.indexOf(2));
// console.log(ll.indexOf(3));
// console.log(ll.indexOf(4));
// console.log(ll.indexOf(5));
console.dir(ll, {
depth: 100,
});
console.log(ll.length);
setTimeout(() => {
ll.update(3, 9);
console.dir(ll, {
depth: 100,
});
}, 1000);
单向循环链表
双向循环链表
环形链表