单向链表的特点
单向链表的缺点
双向链表
双向链表的缺点
双向链表的特点
双向链表基本属性的封装
在单向链表中head存储的是第一个节点的引用,在双向链表中tail存储的是最后一个节点的引用
// 双向链表的封装
function DoubleLinkedList(){
// 属性
this.head = null
// 在双向链表里面this.tail一定是指向最后一个节点
this.tail = null
this.length = 0
// 内部的类进行节点的创建(3个属性)
function Node(data){
this.data = data
this.prev = null
this.next = null
}
// 封装常见的操作
}
双向链表的常见操作
(1)实现append方法
DoubleLinkedList.prototype.append=function(data){
// 根据传入的数据创建节点
var newNode = new Node(data)
// 如果当前链表没有元素
if(this.length == 0){
this.head = newNode
this.tail = newNode
}else{
newNode.prev = this.tail
this.tail.next = newNode
this.tail = newNode
}
this.length += 1
}
(2)实现toString ,forwardString ,backwardString 方法
// 将链表转为字符串的形式
DoubleLinkedList.prototype.toString = function(){
return this.backwardString()
}
// forwardString:向前遍历
DoubleLinkedList.prototype.forwardString = function(){
var current = this.tail
var resultString = ''
// 依次向前遍历获取每一个节点
while(current){
resultString += current.data + ' '
current = current.prev
}
return resultString
}
// backwardString:向后串联为字符串
DoubleLinkedList.prototype.backwardString = function(){
var current = this.head
var resultString = ''
// 依次向后遍历获取每一个节点
while(current){
resultString += current.data + ' '
current = current.next
}
return resultString
}
(3)实现insert方法
(当position是0的情况的图示)
DoubleLinkedList.prototype.insert=function(position,data){
// 当存入position的时候,先进行越界判断
var newNode = new Node(data)
if(position<0 || position>this.length) return false
// 当前两边是否有元素
if(this.length === 0){
// 将head的指针指向newNode
this.head = newNode
this.tail = newNode
}else{
// 判断position是否是0
if(position === 0){
// this.head指向的是原本的那个元素
this.head.prev = newNode
newNode.next = this.head
this.head = newNode
}else if(position == this.length){
// this.tail指向最后一个节点
newNode.prev = this.tail
this.tail.next = newNode
this.tail = newNode
}else{
var current = this.head,
index = 0
previous = null;
while(index++<position){
previous = current
current = current.next
}
newNode.next = current
previous.next = newNode
current.prev = newNode
newNode.prev = previous
}
}
length += 1
return true
}
(4)实现get方法
DoubleLinkedList.prototype.get=(position)=>{
// 越界判断
if(position<0 || position>= this.length) return null
var current = this.head
var index = 0
while(index++ < position){
current = current.next
}
return current.data
}
但是通过这样实现的get方法,当链表的元素过多的时候, 其实是效率不高的,因为这个方法是从前依次王后进行寻找,如果找的是链表末尾的元素,在单向链表中必须是从前往后寻找,但是在双向链表中,可以通过从后往前的方式,在寻找末尾元素的时候会更加快捷,方便。
DoubleLinkedList.prototype.get=(position)=>{
// 越界判断
if(position<0 || position>= this.length) return null
var current = this.head
// 当当前寻找的位置处于前半段的时候
var len = this.length
var index = 0
if(len / 2 > position ){
while(index++ < position){
current = current.next
}
return current.data
}else{
// 当前寻找的元素处于后半段
current = this.tail
index = this.length -1
while(index-- > position) {
current = current.prev
}
console.log('我是后半段')
return current.data
}
}
(4)实现indexOf方法
DoubleLinkedList.prototype.indexOf=(data)=>{
var current = this.head
var index =0
// 查找与data相同的节点
while(current){
if(current.data === data){
return index
}
current = current.next
index += 1
}
return -1
}
(5)实现update方法(也可以像get方法一样,进行一个优化)
DoubleLinkedList.prototype.update=(position,newDate)=>{
// 越界判断
if(position<0 || position>=this.length) return false
var current = this.head
var index = 0
while(index++ < position){
current = current.next
}
// 找到的时候修改值
current.data = newDate
return true
}
(6)实现removeAt方法(当一个节点,没有其他节点的引用指向它的话,那么这个节点就会被回收)
DoubleLinkedList.prototype.removeAt=(position)=>{
// 越界判断
if(position<0 || position >= this.length) return null
// 判断是否只有一个节点
var current = this.head
if(this.length == 1){
this.head = null
this.tail = null
}else{
// 删除第一个节点
if(position==0){
this.head.next.prev = null
this.head = this.head.next
}else if(position == this.length -1){
current = this.tail
this.tail.prev.next = null
this.tail = this.tail.prev
}else{
var index = 0
while(index++ < position){
current = current.next
}
// 找到以后需要改变2个指针
current.prev.next =current.next
current.next.prev = current.prev
}
}
// 最后修改length属性
this.length -=1
return current.data
}
(7)实现remove方法
DoubleLinkedList.prototype.remove=(data)=>{
// 获取索引
var index = this.indexOf(data)
return this.removeAt(index)
}
(8)其余方法的实现(isEmpty,size)
DoubleLinkedList.prototype.isEmpty=(data)=>{
return this.length == 0
}
DoubleLinkedList.prototype.size=(data)=>{
return this.length
}
(9)双向链表获取第一个节点元素
DoubleLinkedList.prototype.getFirst=(data)=>{
return this.head.data
}
(10)双向链表获取最后一个节点元素
DoubleLinkedList.prototype.getLast=(data)=>{
// 获取索引
return this.tail.data
}