一、认识链表
链表和数组一样,可以用于存储一些列数据,但两者的实现机制完全不同.
数组的创建通常需要申请一段连续的内存空间
,并且大小是固定的,所以当当前数组不能满足需求时,需要扩容.而且在数组开头和中间插入数据的成本很高,需要大量的元素位移惟一.
链表的特点和优势:
- 链表的元素在内存中不必是连续的内存空间
- 链表的每个元素由一个存储元素本身的节点和一个指向下一个元素的引用(指针)组成
- 链表在创建是不必确定大小,大小是可以
无限延伸
下去的 - 链表在
插入和删除
数据时,时间复杂度
可以达到O(1).相对数组效率高很多
链表的缺点:
- 链表访问任何一个位置的元素时,都需要
从头开始访问
.(无法跳过第一个元素访问任何一个元素) - 无法通过下标直接访问元素,需要从头一个个访问,知道找到对应的元素
二、链表结构的封装
function LinkList(){
// 属性
this.head = null
this.length = 0
// 封装一个内部类
function Node(data){
this.data = data
this.next = null
}
// 向尾部添加一个新的项
LinkList.prototype.append = function(data){
let newNode = new Node(data)
if(!this.head){
this.head = newNode
this.length += 1
}else{
let curNode = this.head
while(curNode.next){
curNode = curNode.next
}
curNode.next = newNode
this.length += 1
return true
}
}
// 向链表特定位置插入一个元素
LinkList.prototype.insert = function(data, position){
let pos = position > 0 ? position:(this.length + position)
if(pos > this.length || pos < 0) return false
let newNode = new Node(data)
if(pos = 0){
newNode.next = this.head
this.head = newNode
}else{
let index = 0
let curNode = this.head
let preNode = null
while(pos > index){
preNode = curNode
curNode = curNode.next
index++
}
preNode.next = newNode
newNode.next = curNode
}
this.length += 1
return true
}
// 修改某个位置的元素
LinkList.prototype.update = function(data, position){
let pos = position > 0 ? position:(this.length + position)
if(pos > this.length || pos < 0) return false
let index = 0
let curNode = this.head
while(pos > index){
curNode = curNode.next
index++
}
curNode.data = data
return true
}
// 获取对应位置元素
LinkList.prototype.get = function(position){
let pos = position > 0 ? position:(this.length + position)
if(pos > this.length || pos < 0) return null
let index = 0
let curNode = this.head
while(pos > index){
curNode = curNode.next
index++
}
return curNode.data
}
// 返回元素在链表中的索引,如果链表中没有该元素则返回 -1
LinkList.prototype.indexOf = function(data){
let index = 0
let curNode = this.head
while(curNode){
if(curNode.data === data){
return index
}
curNode = curNode.next
index++
}
return -1
}
// 移除特定位置的项
LinkList.prototype.removeAt = function(position){
let pos = position > 0 ? position:(this.length + position)
if(pos > this.length || pos < 0) return null
let curNode = this.head
if(pos === 0){
this.head = this.head.next
}else{
let index = 0
let preNode = null
while(pos > index){
preNode = curNode
curNode = curNode.next
index++
}
preNode.next = curNode.next
}
this.length--
return curNode.data
}
// 从链表中移除一项
LinkList.prototype.remove = function(data){
let pos = this.indexOf(data)
if(pos === -1) return null
return this.removeAt(pos)
}
// 判断链表是否为空
LinkList.prototype.isEmpty = function(){
return this.length === 0
}
// size
LinkList.prototype.size = function(){
return this.length
}
//
LinkList.prototype.toString = function(){
let curNode = this.head
let listString = ''
while(curNode){
listString += curNode.data + ' '
curNode = curNode.next
}
return listString
}
}