js数据结构- 双向链表

双向链表

双向链表概念

既可以从头遍历到尾,又可以从尾遍历到头。也就是说链表连接的过程是双向的,它的实现原理是:一个节点既有向前连接的引用,也有一个向后连接的引用

双向链表的缺点:

  • 每次在插入或删除某个节点时,都需要处理四个引用,而不是两个,实现起来会困难些;
  • 相对于单向链表,所占内存空间更大一些;
  • 但是,相对于双向链表的便利性而言,这些缺点微不足道。

双向链表的结构:

  • 双向链表不仅有head指针指向第一个节点,而且有tail指针指向最后一个节点;

  • 每一个节点由三部分组成:item储存数据、prev指向前一个节点、next指向后一个节点;

  • 双向链表的第一个节点的prev指向null

  • 双向链表的最后一个节点的next指向null

双向链表常见的操作(方法):

  • append(element):向链表尾部添加一个新的项;
  • inset(position,element):向链表的特定位置插入一个新的项;
  • get(element):获取对应位置的元素;
  • indexOf(element):返回元素在链表中的索引,如果链表中没有元素就返回-1;
  • update(position,element):修改某个位置的元素;
  • removeAt(position):从链表的特定位置移除一项;
  • isEmpty():如果链表中不包含任何元素,返回trun,如果链表长度大于0则返回false;
  • size():返回链表包含的元素个数,与数组的length属性类似;
  • toString():由于链表项使用了Node类,就需要重写继承自JavaScript对象默认的toString方法,让其只输出元素的值;
  • forwardString():返回正向遍历节点字符串形式;
  • backwordString():返回反向遍历的节点的字符串形式;
// 双向链表节点
export class DoublyLnode{
  constructor(data){
      this.data = data
      this.pre = null
      this.next = null
  }
}
// 封装双向链表
export class DoublyLinkedList{
  constructor(){
    this.head =null  // 头指针
    this.tail = null // 尾指针
    this.length = 0

  }
  // 向尾部添加一项
  append(element){
    const newNode = new DoublyLnode(element)
     if(this.length == 0){ //判断是不是要插入第一个
       this.head = newNode
       this.tail = newNode
     }else{
        newNode.pre = this.tail
        this.tail.next = newNode
        this.tail = newNode
     }
  }
  // 将链表转为字符串的形式
   toString(){
        return this.backwardString()
   }
   forwardToString(){ // 从后往前遍历
    const current = this.tail
    const res =''
    while(current){
      res +=current.data +' '
      current = current.pre
    }
    return res
   }
   backwardString(){  // 从前往后遍历
     const current = this.head
     const res =''
     while(current){
       res +=current.data +' '
       current = current.next
     }
     return res
   }
  //  向链表的特定位置插入一个新的项
  insert(position,element){
    if(position <0 || position >=this.length) return null
    const newNode = new DoublyLnode(element)
    if(position == 0){
      if( this.head === null){
        this.head = newNode;
        this.tail = newNode;
      }else{
        newNode.next = this.head
        this.head.pre = newNode
        this.head = newNode
      }
      
    }else if(position == this.length){
      newNode.pre = this.tail
      this.tail.next = newNode
      this.tail = newNode
    }else{
      const index = 0
      const current = this.head
      while(index < position){
        current = current.next
        index++
      }
      newNode.next = current
      current.pre.next = current
      newNode.pre = current.pre
      current.pre = newNode
    }
    this.length++
    return ture
  }
  // 获取对应位置的元素
  get(position){
    if(position <0 || position >=this.length) return null
    const index = 0
    const current = this.head
    while(index < position){
      current = current.next
      index++
    }
    return current.data
  }
  // 根据元素值,返回位置
  indexOf(data){
    const index = 0
    const current = this.head
    while(current){
      if(current.data == data){
        return index
      }
      current = current.next
      index++
    }
    return -1
  }
  // 删除指定位置的节点
  removeAt(position){
    if(position <0 || position >=this.length) return null
    let current = this.head;
    if(position == 0){
      if(this.length === 1){
          this.head = null
          this.tail = null
      }else{
        this.head = this.head.next
        this.head.pre = null
      }
    }else if(position === this.length -1){
      current = this.tail;
      this.tail.pre.next = null
      this.tail = this.tail.pre
      return 
    }else{
      let index =0
      while(index < position){
        current = current.next
        index++
      }
      current.pre.next = current.next
      current.next.pre = current.pre
      return current.data
    }
    this.length--
  }
  // 修改指定位置的节点
  update(position, data){
    if(position <0 || position >=this.length) return null
    const res = this.removeAt(position)
    this.insert(position,data)
    return res
  }
  // 删除指定 data 所在的节点
  remove(data){
    return this.removeAt(this.indexOf(data))
  }
  // 判断链表是否为空
  isEmpty(){
    if(this.length === 0){
      return ture
    }else{
      return false
    }
  }
  // 获取链表的长度
  size(){
    return this.length
  }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值