一.链表的特点
- 当需要存储多个元素时,除了使用数组外,另外一个选择就是链表
- 链表中的元素在内存中所获取的内存空间不必是连续的
- 链表的每个元素由一个存储元素本身的节点和一个指向下一个元素的引用(有些语言称之为指针或者连接)组成
二.链表的优缺点
相对于数组,链表有一些优点:
- 内存空间不是必须连续的,可以充分利用计算机的内存,实现灵活的内存动态管理
- 链表不必在创建时就确定大小,并且大小可以无限延伸下去
- 链表在插入和删除数据时,时间复杂度可以达到O(1),相对数组效率高很多。而数组在修改和查找元素方面效率较高
相对于数组,链表有一些缺点:
- 链表访问任何一个位置的元素时,都需要从头开始访问(无法跳过第一个元素访问任何一个元素)
- 无法通过下标直接访问元素,需要从头一个一个访问,直到找到对应的元素
三.单向链表的相关操作
- 追加方法:在链表的末尾添加节点
- toString方法
- insert方法:在给定的positon处添加节点
- get方法:获取指定position的data数据
- indexOf(element):返回元素在链表中的索引,如果没有该元素则返回-1
- update方法:更改指定位置的data数据
- removeAt方法:删除指定位置的节点
- remove方法:删除指定数据的节点
function LinkedList(){
//内部类:节点类
function Node(data){
this.data = data
this.next = null
}
//属性
this.head = null
this.length = 0
//1.追加方法
LinkedList.prototype.append = function(data){
// 1.1 创建新的节点
var newNode = new Node(data)
// 1.2判断是否添加的是第一个节点
if(this.length == 0){ // 2.1 是第一个节点
this.head = newNode
} else { // 2.2 不是第一个节点
// 找到最后一个节点
var current = this.head
while(current.next){
current = current.next
}
// 最后节点的next指向新节点
current.next = newNode
}
// 1.3 长度+1
this.length += 1
}
// 2.toString方法
LinkedList.prototype.toString = function(){
// 2.1 定义变量
var current = this.head
var listString = ' '
// 2.2 循环获取一个个节点
while(current){
listString += current.data + ' '
current = current.next
}
return listString
}
}
// 3.insert方法
LinkedList.prototype.insert = function(position , data){
// 3.1 对position进行越界判断
if(position < 0 || position > this.length) return false // 此处为>,当position=length时,相当于在尾部追加
// 3.2 根据data创建newNode
var newNode = new Node(data)
// 3.3 判断插入的位置是否是第一个
if(position == 0){
newNode.next = this.head
this.head = newNode
} else {
var index = 0
var current = this.head
var previous = null
while(index++ < position){
previous = current
current = current.next
}
newNode.next = current
previous.next = newNode
}
// 3.4 length+1
this.length += 1
return true
}
// 4.get方法
LinkedList.prototype.get = function(position){
// 4.1 越界判断
if(position < 0 || position >= this.length) return null //此处为>=,因为当position=length时,节点已经不存在了
// 4.2 获取对应的data
var index = 0
var current = this.head
while(index++ < position){
current = current.next
}
return current.data
}
// 5. indexOf方法
LinkedList.prototype.indexOf = function(data){
// 5.1 定义变量
var current = this.head
var index = 0
// 5.2 开始查找
while(current){
if(current.data == data){
return index
}
current = current.next
index += 1
}
// 5.3 找到最后没有找到,返回-1
return -1
// 6.update方法
LinkedList.prototype.update = function(position, newData){
// 6.1 越界判断
if(position < 0 || position >= this.length) return false
// 6.2 查找正确的节点
var current = this.head
var index = 0
while(index++ < position){
current = current.next
}
// 6.3 将position位置的node的data修改成newData
current.data = newData
return true
}
// 7.removeAt方法
LinkedList.prototype.removeAt = function(position){
// 7.1 越界判断
if(position < 0 || position >= this.length) return null
// 7.2 判断是否删除的是第一个节点
var current = this.head
if(position == 0){
this.head = this.head.next
} else {
var index = 0
var previous = null
while(index++ < position){
previous = current
current = current.next
}
// 前一个节点的next指向current的next即可
previous.next = current.next
}
// 7.3 length-1
this.length -= 1
return current.data
}
// 8. remove方法
LinkedList.prototype.remove = function(data){
// 8.1 获取data在链表中的位置
var position = this.indexOf(data)
// 8.2 根据位置信息,删除节点
return this.removeAt(position)
}
}