这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战算法
链表相对于数组的优势在于:数组
O(1)
,相对数组效率高许多。链表相对于数组的缺点在于:浏览器
链表的每一个元素由一个存储元素自己的节点和一个指向下一个元素的引用组成。也就是说每个节点本身有一个data,而且有一个指向下一个节点的指针next,next的指向默认为null。markdown
function LinkList() {
function Node(data) {
this.data = data;
this.next = null;
}
this.head = null;
this.length = 0; // 记录链表节点的个数
}
复制代码
append(element)
:向列表尾部添加一个新的元素insert(position, element)
:向列表的某个位置插入一个新的元素get(position)
:获取对应位置的元素indexOf(element)
:返回元素在列表中的索引。若是没有该元素则返回-1update(position, data)
:修改某个位置的元素的data值removeAt(position)
:从列表的某个位置移除一个元素remove(data)
:从列表中移除一个元素isEmpty()
:若是链表中没有元素,返回true。不然返回falsesize()
:返回链表中包含的元素个数,和数组的length属性相似toString()
:链表中元素是Node类,须要重写toString
方法,方便输出打印元素的值。若是添加的是第一个节点的话,须要多作一个步骤——把head指针指向第一个节点。若是添加的不是第一个节点的话,就要把最后一个节点的指针指向新建立的节点。app
查找方法:从this.head
开始查找,若是当前指针指向的下一个current.next
不为空,将下一个节点的指针current.next
赋值给当前指针current
;直到current.next
为空,那么这个指针所在的节点就是链表中的最后一个节点,将这个指向空的指针指向新建立的节点便可。post
LinkList.prototype.append = function (data) {
var newNode = new Node(data);
if (this.length == 0) {
this.head = newNode;
} else {
var current = this.head;
while (current.next) {
current = current.next;
}
current.next = newNode;
}
this.length += 1;
}
复制代码
在某个位置中插入一个元素。我在这里的设置,传入的position不能小于0,所以小于0时return false
,并且插入的位置也不可以大于此时链表的长度,在这种状况下也return false
。接下来,插入元素存在两种状况:this
第一种:将元素插到第一个节点,即position
的值为0,此时要修改建立节点的指针指向,应该指向原来this.head
指向的元素,再让this.head
指向这个新建立的元素,便可完成插入。spa
第二种,将元素插到中间或者末尾,即0 < position < this.length
,先找到要插入的位置的上一个节点。而后跟第一种方法的思路是差很少的,将建立的节点指针指向当前节点指向的元素newNode.next = current.next
,而后让当前节点指针指向新建立的元素current.next = newNode
prototype
LinkList.prototype.insert = function (position, data) {
var newNode = new Node(data);
if (position < 0 || position > this.length) return false;
if (position === 0) {
newNode.next = this.head;
this.head = newNode;
} else {
var current = this.head;
for (var i = 0; i < position - 1; i++) {
current = current.next;
}
newNode.next = current.next;
current.next = newNode;
}
this.length += 1;
}
复制代码
获取某个位置的元素,查找到这个位置,让current
指向当前位置,返回当前位置的data值便可。指针
LinkList.prototype.get = function (position) {
if (position < 0 || position >= this.length) return null;
var current = this.head;
for (var i = 0; i < position; i++) {
current = current.next;
}
return current.data;
}
复制代码
修改某个位置的元素值。这个跟get方法实际上是差很少的,只不过get只是拿到这个位置的data值,可是update是要咱们将这个data值改为传进来的data。这个就不用代码呈现了。
indexOf(element)
方法在链表中查找某一个元素的值(data
),当找到这个元素的时候就这个元素的索引号(即位于哪一个位置)。若是没有找到这个数据的话就会返回-1。遍历链表,将每个元素的data和要查找的element进行比较,若是相同就返回它的索引值。
LinkList.prototype.indexOf = function (element) {
var current = this.head;
var index = 0;
while (current) {
if (current.data == element) {
return index;
}
current = current.next;
index += 1;
}
return -1;
}
复制代码
removeAt(position)
方法从某个位置移除一个元素。有两种状况:
1)删除position = 0
的元素;虽然此时删除的元素仍是指向第二个元素,可是此时虽然它有指向别人,可是没有人指向它,浏览器会自动把这些没用的对象回收。
2)删除position > 0
的元素;查找元素,直到要删除元素位置的上一个位置,即current
,current.next
本来指向的就是这个要删除的元素,对它的指向从新赋值为current.next.next
,即指向删除元素的下一个元素位置。最后再返回删除元素的data值。
LinkList.prototype.removeAt = function (position) {
var current = this.head;
if (position < 0 || position >= this.length) return false;
if (position == 0) {
this.head = this.head.next
} else {
for (var i = 0; i < position - 1; i++) {
current = current.next;
}
current.next = current.next.next;
}
this.length -= 1;
return current.data;
}
复制代码
remove(data)
方法移除data等于传入的data的元素。1)用indexOf
获取data在链表中的位置;2)根据位置信息删除节点,返回删除的数据。
LinkList.prototype.remove = function (data) {
var position = this.indexOf(data);
return this.removeAt(position);
}
复制代码
toString()
方法这个方法只是方便咱们查看链表中的数据。实现方法:遍历链表,将链表中的每个节点的值都取出来放到一个字符串中,再做为返回值返回,
LinkList.prototype.toString = function () {
var current = this.head;
var listString = '';
while (current) {
listString += current.data + ' ';
current = current.next;
}
return listString;
}
复制代码
\