javascript数据结构与算法----双向链表

单向链表的特点
在这里插入图片描述
单向链表的缺点
在这里插入图片描述
双向链表
在这里插入图片描述
双向链表的缺点
在这里插入图片描述
在这里插入图片描述
双向链表的特点
在这里插入图片描述
双向链表基本属性的封装
在单向链表中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
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章