1.定义
单向链表是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始。链表是使用指针进行构造的列表,并且是由一个个结点组装起来的,因此又称为结点列表。其中每个结点都有指针成员变量指向列表中的下一个结点,head指针指向第一个结点称为表头,而终止于最后一个指向nuLL的指针。
2.链表优势
- 要存储多个元素,另外一个选择是链表
- 不同于数组,链表中的元素在内存中不必是连续的空间
- 链表的每个元素由一个存储元素本身的节点和一个指向下一个元素的引用(有些语言称为指针或连接)组成
相对于数组,链表的一些优点
- 内存空间不是必须连续的,可以充分利用计算机的内存,实现灵活的内存动态管理
- 链表不必在创建时就确定大小,并且大小可以无限延伸下去
- 链表在插入和删除数据时,时间复杂度可以达到O(1),相对于数组效率高很多
相对于数组,链表的一些缺点
- 链表访问任何一个位置的元素时,都需要从头开始访问(无法跳过第一个元素访问任何一个元素)
- 无法通过下标直接访问元素,需要从头一个个访问,直到找到对应元素
3.链表的一些常见操作(增、删、改、查)
append(element):向列表尾部添加一个新的项
insert(position,element):向列表的特定位置插入一个新的项
get(position):获取对应位置元素
indexOf(element):返回元素在列表中的索引,如果列表中没有该元素则返回-1
update(position):修改某个位置的元素
remove(element):从列表中移除一项
removeAt(position):从列表的特定位置移除一项
isEmpty():判断链表是否为空,为空则返回true,否则返回false
size():返回链表包含的元素个数
toString():由于列表项使用了Node类,就需要重写继承自JavaScript对象默认的toString方法,让其只输出元素的值
3.1 append()方法
//1.增加方法
LinkedList.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
}
//最后节点的next指向新的节点
current.next = newNode
}
this.length += 1
}
3.2 toString()方法
//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.3 insert()方法
//3.insert方法
LinkedList.prototype.insert = function(position,data){
//对position进行越界判断
if(position < 0 || position > this.length) return false
//创建newNode
var newNode = new Node(data)
//判断插入位置是否是第一个
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
}
this.length += 1
return true
}
3.4 get()方法
//get方法
LinkedList.prototype.get = function(position){
//越界判断
if(position < 0 || position >= this.length) return false
//获取对应data
var current = this.head
var index = 0
while(index++ < position){
current = current.next
}
return current.data
}
3.5 indexOf()方法
//indexOf方法
LinkedList.prototype.indexOf = function(data){
//定义变量
var current = this.head
var index = 0
//开始查找
while(current){
if(current.data == data){
return index
}else{
current = current.next
index +=1
}
}
//找到最后没有找到,返回-1
return -1
}
3.6 updata()方法
//updata方法
LinkedList.prototype.updata = function(position,newData){
//越界判断
if(position < 0 || position >= this.length) return false
//查找正确的节点
var current = this.head
var index = 0
while(index++ < position){
current = current.next
}
//将position位置的node的data修改成newData
current.data = newData
return true
}
3.7 removeAt()方法
//removeAt方法
LinkedList.prototype.removeAt = function(position){
//越界判断
if(position < 0 || position >= this.length) return false
//判断是否删除的是第一个节点
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
}
this.length -= 1
return current.data
}
3.8 remove()方法
//remove方法
LinkedList.prototype.remove = function(data){
//获取data在列表中的位置
var position = this.indexOf(data)
//根据位置信息删除节点
return this.removeAt(position)
}
3.9 isEmpty()方法
//isEmpty方法
LinkedList.prototype.isEmpty = function(){
return this.length == 0
}
3.10 size()方法
//size方法
LinkedList.prototype.size = function(){
return this.length
}
}
4.链表结构的封装
//封装链表类
function LinkedList(){
//内部类:节点类
function Node(data){
this.data = data
this.next = null
}
//属性
this.head = null
this.length = 0
}
5. 完整代码
//封装链表类
function LinkedList(){
//内部类:节点类
function Node(data){
this.data = data
this.next = null
}
//属性
this.head = null
this.length = 0
//1.增加方法
LinkedList.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
}
//最后节点的next指向新的节点
current.next = newNode
}
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){
//对position进行越界判断
if(position < 0 || position > this.length) return false
//创建newNode
var newNode = new Node(data)
//判断插入位置是否是第一个
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
}
this.length += 1
return true
}
//get方法
LinkedList.prototype.get = function(position){
//越界判断
if(position < 0 || position >= this.length) return false
//获取对应data
var current = this.head
var index = 0
while(index++ < position){
current = current.next
}
return current.data
}
//indexOf方法
LinkedList.prototype.indexOf = function(data){
//定义变量
var current = this.head
var index = 0
//开始查找
while(current){
if(current.data == data){
return index
}else{
current = current.next
index +=1
}
}
//找到最后没有找到,返回-1
return -1
}
//updata方法
LinkedList.prototype.updata = function(position,newData){
//越界判断
if(position < 0 || position >= this.length) return false
//查找正确的节点
var current = this.head
var index = 0
while(index++ < position){
current = current.next
}
//将position位置的node的data修改成newData
current.data = newData
return true
}
//removeAt方法
LinkedList.prototype.removeAt = function(position){
//越界判断
if(position < 0 || position >= this.length) return false
//判断是否删除的是第一个节点
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
}
this.length -= 1
return current.data
}
//remove方法
LinkedList.prototype.remove = function(data){
//获取data在列表中的位置
var position = this.indexOf(data)
//根据位置信息删除节点
return this.removeAt(position)
}
//isEmpty方法
LinkedList.prototype.isEmpty = function(){
return this.length == 0
}
//size方法
LinkedList.prototype.size = function(){
return this.length
}
}
测试
//测试
var list = new LinkedList()
list.append('asd')
list.append('qwe')
list.append('zzx')
//alert(list)
list.insert(0,'qqq')
list.insert(3,'mmm')
list.insert(5,'ppp')
//alert(list)
//alert(list.get(0))
//alert(list.get(3))
// alert(list.indexOf('ppp'))
// alert(list.indexOf('asd'))
// alert(list.indexOf('ccc'))
list.updata(0,'ooo')
list.updata(3,'uuu')
//alert(list)
list.removeAt(0)
//alert(list)
list.remove('ppp')
//alert(list)
list.remove('mmm')
//alert(list)
alert(list.isEmpty())
alert(list.size())