数组不是组织数据的最佳数据结构,js中的数组与其它语言中的数组不同,他被实现成了对象,与其它语言相比,js中的数组效率很低。
如果发现数组效率很低时,我们可以使用链表来代替任何可以使用一维数组的情况,但是如果需要随机访问,数组仍然是最佳选择。
链表
- 链表是由一组节点组成的集合,每个节点都使用一个对象都引用指向他的后继,指向另一个节点的引用叫做链。
- 链表元素考相互之间的关系进行引用。
- 遍历链表,就是跟着链接,从链表的首元素一直走到尾元素(不包含链表的头节点,头节点一般用来作为链表的接入点)
链表的头节点需要特殊标记,链表的尾元素指向一个
null
节点链表的插入、删除元素功能强大。
单向链表构造函数
// Node 类主要用来表示节点
function Node(element) {
this.element = element;
this.next = null;
}
// LinkedList 类提供了插入节点、删除节点、显示列表元素的方法,以及一些其它辅助方法
function LList() {
this.head = new Node("head");
this.find = find;
this.insert = insert;
this.remove = remove;
this.display = display;
this.findPrevious = findPrevious;
}
function find(item) {
var currNode = this.head;
while(currNode.element !== item) {
currNode = currNode.next;
}
return currNode;
}
function insert(newElement, item) {
var newNode = new Node(newElement);
var current = this.find(item);
newNode.next = current.next;
current.next = newNode;
}
function display() {
var currNode = this.head;
while (!currNode.nex == null) {
print (currNode.next.element);
currNode = currNode.next;
}
}
function findPrevious(item) {
var currNode = this.head;
while (!(currNode.next == null) && (currNode.next.element != item)) {
currNode = currNode.next;
}
return currNode;
}
function remove(item) {
var prevNode = this.findPrevious(item);
if (!(prevNode.next == null)) {
prevNode.next = prevNode.next.next;
}
}
双向链表
使用双向链表,双向链表的构造函数与单向链表大体相同,主要需要修改一下:
function Node(element) {
this.element = element;
this.next = null;
this.previous = null;
}
function LList() {
this.head = new Node("head");
this.find = find;
this.insert = insert;
this.remove = remove;
this.display = display;
this.findLast = findLast;
this.dispReverse = dispReverse;
}
function find(item) {
var currNode = this.head;
while(currNode.element !== item) {
currNode = currNode.next;
}
return currNode;
}
function insert(newElement, item) {
var newNode = new Node(newElement);
var current = this.find(item);
newNode.next = current.next;
newNode.previous = current;
current.next = newNode;
}
function display() {
var currNode = this.head;
while (!currNode.nex == null) {
print (currNode.next.element);
currNode = currNode.next;
}
}
function remove(item) {
var currNode = this.find(item);
if (!(currNode.next == null)) {
currNode.previous.next = currNode.next;
currNode.next.previous = currNode.previous;
currNode.next = null;
currNode.previous = null;
}
}
function findLast() {
var currNode = this.head;
while (!(currNode.next == null)) {
currNode = currNode.next;
}
return currNode;
}
function dispReverse() {
var currNode = this.head;
currNode = this.findLast();
while (!(currNode.previous == null)) {
print(currNode.element);
currNode = currNode.previous;
}
}
循环链表
循环链表与单向链表的区别就是,创建循环链表时,让头节点的next属性指向它本身,从循环链表的尾节点向后移动,就等于从后向前遍历链表
function LList() {
this.head = new Node("head");
this.head.next = this.head;
this.find = find;
this.insert = insert;
this.remove = remove;
this.display = display;
this.findLast = findLast;
this.dispReverse = dispReverse;
}
function display() {
var currNode = this.head;
while (!(currNode.next == null) &&
!(currNode.next.element == "head")) {
print(currNode.next.element);
currNode = currNode.next;
}
}
// 其它循环的更改方法与display()函数相同