链表是一种动态的数据结构,不同于数组的是,链表分配内存空间的灵活性,它不会像数组一样被分配一块连续的内存。当你想在数组的任意位置,插入一个新值的时候,必须对数组中的各个元素进行相应的位置移动才能达到目标,开销显然是很大的。然而链表的灵活性在于它的每个元素节点分为两部分,一部分是存储元素本身,另一部分是指向下一个节点元素的引用,也可以称为指针,当你要插入数据时,把上一个节点的向下指针指向新数据节点,新数据节点的向下指针指向原有数据。但是链表不像数组那样可以直接通过索引立刻定位,只能通过遍历。 链表分配内存的动态性体现在内存的不连续性和无索引性,你可以随时随地增加或删除,如下图所示:
在这里,我们定义了链表的五个操作:增加append,删除removeAt,插入insert,输出节点toString,以及索引indexOf。
function LinkedList() {
var Node = function (val) { //新元素构造
this.val = val;
this.next = null;
};
var length = 0;
var head = null;
this.append = function (val) {
var node = new Node(val); //构造新的元素节点
var current;
if (head === null) { //头节点为空时 当前结点作为头节点
head = node;
} else {
current = head;
while (current.next) { //遍历,直到节点的next为null时停止循环,当前节点为尾节点
current = current.next;
}
current.next = node; //将尾节点指向新的元素,新元素作为尾节点
}
length++; //更新链表长度
};
this.removeAt = function (position) {
if (position > -1 && position < length) {
var current = head;
var index = 0;
var previous;
if (position == 0) {
head = current.next;
} else {
while (index++ < position) {
previous = current;
current = current.next;
}
previous.next = current.next;
}
length--;
return current.val;
} else {
return null;
}
};
this.insert = function (position, val) {
if (position > -1 && position <= length) { //校验边界
var node = new Node(val);
current = head;
var index = 0;
var previous;
if (position == 0) { //作为头节点,将新节点的next指向原有的头节点。
node.next = current;
head = node; //新节点赋值给头节点
} else {
while (index++ < position) {
previous = current;
current = current.next;
} //遍历结束得到当前position所在的current节点,和上一个节点
previous.next = node; //上一个节点的next指向新节点 新节点指向当前结点,可以参照上图来看
node.next = current;
}
length++;
return true;
} else {
return false;
}
};
this.toString = function () {
var string = head.val;
var current = head.next;
while (current) {
string += ',' + current.val;
current = current.next;
}
return string;
};
this.indexOf = function (val) {
var current = head;
var index = -1;
while (current) {
if (val === current.val) { //从头节点开始遍历
return index;
}
index++;
current = current.next;
}
return -1;
};
this.getLength = function () {
return length;
}
this.getHead = function () {
return head;
}
}
// 创建链表
var li = new LinkedList();
li.append(1);
li.append(2);
li.append(4);
li.append(4);
li.append(5);
li.insert(2,3);
li.insert(2,3);
console.log(li.toString()) // 1,2,3,3,4,4,5
console.log(li.getHead()) // 1->2->3->3->4->4->5
参考:
END