前言
从实用性角度来说,链表对Javascript 来说没有任何价值,为什么呢?
我们先了解链表的特性,这个特性我们放在c++前提下来说,因为 这个特性是 根据 内存特性 来阐述的,Javascript 不存在内存操作,所有数据类型,本质性继承Object 对象,而Object对象,其实可以说是一个哈希存储(资料传送门) ,所以链表对于 JavaScript毫无价值。 当然下文会提供一些例子,来证明这个结论
结构
链表以头节点开始(head),以next 属性链接下一个节点。
链表以索引方向分为:
- 单向链表,从头到尾 单方向索引。
- 双向链表,可以从头部想尾部索引,也能重尾部向头部索引
- 循环列表,头指针指向尾节点, 尾指针指向头结点
下图 为单向链表的 结构
特性
对于链表的特性只有2个,这两个特性 只能体现在高级语言当中。
- 链表动态的大小(长度动态分配)
- 能高性能插入,删除元素
链表动态的大小
数组是初始化的时候就分配好固定大小,在内存当中,这块分配好的空间表现是 连续固定的,但是链表不一样,链表的节点是分散的,通过程序链接的。
能高性能插入,删除元素
链表的高性能的插入/删除元素,也是因为对应内存特性。由于数组的 固定连续的内存空间,数组的索引速度很快,但是插入/删除性能不好,因为每当做插入/删除操作都会让其他元素移动内存地址,而链表就是控制节点的 指针就是 进行插入/删除。
关于JavaScript 的链表
前言提过 链表这个结构对JavaScript毫无意义,为什么呢。
链表的特性在JavaScript中完全体现不出,JavaScript的数组,本身就不是传统的数组,JS的数组其实就是JS Object 对象的拓展,而JS Object 在 C++ 中其实是用Hash Map的实现的。关于JS Obect详细资料传送门
当然抱着学习与探索的精神,我们还是用JavaScript 实现了 链表。
实现源码
// 节点对象
function Node(element) {
this.element = element;
this.next = null;
}
// 列表对象
function List() {
this.head = new Node("head");
this.find = find;
this.insert = insert;
this.remove = remove;
this.display = display;
this.findPrevious = findPrevious;
}
// 搜索元素方法
function find(item) {
let currNode = this.head;
while(currNode.element !== item) {
currNode = currNode.next;
}
return currNode;
}
// 插入元素方法
function insert(newElement,item) {
let newNode = new Node(newElement);
let current = this.find(item);
if(current === null)
return console.log("can't find the item");
newNode.next = current.next;
current.next = newNode;
}
// 移除元素方法
function remove(item) {
let prevNode = this.findPrevious(item);
if(prevNode.next !== null)
prevNode.next = prevNode.next.next;
}
// 查找item 的前节点
function findPrevious(item) {
let currNode = this.head;
while(currNode.next !== null && currNode.next.element !== item) {
currNode = currNode.next;
}
return currNode;
}
// 显示列表数据
function display() {
let current = this.head;
while(current.next !== null) {
console.log(current.next.element);
current = current.next;
}
}
测试性能
上文提及链表插入性能优秀,我们运行下面代码
let l = new List();
let arr = [];
console.time();
for(let i =0 ; i< 100000; i++){
arr.push(i)
}
console.timeEnd();
console.time();
for(let i =1 ; i< 100000; i++){
l.insert(i, 'head')
}
console.timeEnd();
结果是: