链表

复习 链表

链表被称为线性表的链式存储结构

定义

链表:可以存储多个元素,由n个结点和指针链组成一个链表,称为线性表的链式存储结构;每个节点由数据域和指针域两部分组成

单链表

单链表:由n个节点和指针链组成,每一个结点由数据域(存放元素本身的数据)和指针域(指向下一个元素的引用(或称为指针))组成

在这里插入图片描述

单链表的代码实现

function LinkedList() {
  /**
   * 头指针,用于指向链表的第一个节点的引用,
   * 当链表为空的时候,head指向 null
   * 最后一个节点指向下一个元素的引用为null
   *  */
  this.head = null

  /**
   * Node:节点,每个节点包含自己的数据和指向下一个节点的引用
   */
  function Node(ele, next = null) {
    this.ele = ele
    this.next = next
  }

  /**
   * length: 链表的长度
   */
  this.length = 0

  //append 向列表末尾插入节点
  LinkedList.prototype.append = ele => {
    const newNode = new Node(ele)
    if (this.length === 0) {
      // 链表为空时直接插入
      this.head = newNode
      // newNode.next = null
    } else {
      // 链表不为空的时候插入到最后一个节点后面
      let currentNode = this.head
      // 遍历链表,找到最后一个节点
      while (currentNode.next) {
        currentNode = currentNode.next
      }
      currentNode.next = newNode
      newNode.next = null
    }
    // 让长度加一
    this.length += 1
  }

  //insert 在position位置插入节点
  LinkedList.prototype.insert = (position, ele) => {
    if (position < 0 || position > this.length) return
    const newNode = new Node(ele)
    let currentNode = this.head
    if (position === 0) {
      this.head = newNode
      newNode.next = currentNode
    } else {
      let index = 1 // index 对应 每个节点
      while (index < this.length) {
        // 当前节点的前驱
        const previous = currentNode
        // 当前节点
        currentNode = currentNode.next
        // 新节点插入两者中间中间
        if (position === index) {
          previous.next = newNode
          newNode.next = currentNode
        }
        index++
      }
    }
    this.length += 1
  }

  // get 获取对应位置的元素
  LinkedList.prototype.getNode = position => {
    if (position < 0 || position >= this.length) return null
    let index = 0
    let currentNode = this.head
    while (index < this.length) {
      if (index >= 1) currentNode = currentNode.next
      if (position === index) return currentNode
      index++
    }
  }

  // indexOf 返回元素在列表中的索引
  LinkedList.prototype.indexOf = data => {
    let index = 0
    let currentNode = this.head
    while (index < this.length) {
      if (index >= 1) currentNode = currentNode.next
      if (data === currentNode.ele) return index
      index++
    }
    return -1
  }

  // update 用于修改节点数据
  LinkedList.prototype.update = (position, data) => {
    if (position < 0 || position >= this.length) return false
    let index = 0
    let currentNode = this.head
    while (index < this.length) {
      if (position === index) {
        return currentNode.ele = data
      }
      index++
      currentNode = currentNode.next
    }
  }

  // removeAt 删除特定位置的节点
  LinkedList.prototype.removeAt = position => {
    if (position < 0 || position >= this.length) return false
    let node = this.head
    // 处理 删除的是第一个节点的情况
    if (position === 0) {
      this.head = node.next
      this.length -= 1
      // 返回被删除的节点
      return node
    }
    let index = 1
    while (index < this.length) {
      if (position === index) {
        // 当前节点(index对应位置的节点)的前一个节点
        const previousNode = node
        // 当前节点
        const currentNode = node.next
        //  下一个节点
        // const nextNode = currentNode.next
        // 前一个节点的指针域 next 指向 下一个节点
        previousNode.next = currentNode.next
        this.length -= 1
        return currentNode
      }
      index++
      node = node.next
    }
  }

  // remove 删除特定元素节点
  LinkedList.prototype.remove = data => {
    let node = this.head
    if (data === node.ele) {
      this.head = node.next
      return (this.length -= 1)
    }
    let index = 1
    while (index < this.length) {
      const previous = node
      const currentNode = node.next
      const nextNode = currentNode.next
      if (data === currentNode.ele) {
        previous.next = nextNode
        return (this.length -= 1)
      }
      index++
    }
    return console.log('链表中的节点没有此数据')
  }

  //toString 将链表的所有节点的值拼接成一个字符串
  LinkedList.prototype.toString = () => {
    if (this.length === 0) return ''
    let currentNode = this.head
    let resultStr = ''
    while (currentNode) {
      resultStr += currentNode.ele + ' '
      currentNode = currentNode.next
    }
    return resultStr
  }

  // size
  LinkedList.prototype.size = () => {
    return this.length
  }

  // isEmpty
  LinkedList.prototype.isEmpty = () => {
    return this.length === 0
  }
}

双向链表

双向链表在单链表的基础上每一个结点指针域增加了一个指向前一个结点的引用

在这里插入图片描述

双向链表的代码实现

function BidirectionalLinkedList() {
  /**
   * 头指针
   */
  this.head = null

  /**
   * 尾指针
   */
  this.tail = null

  function Node(data, pre = null, next = null) {
    this.data = data
    this.pre = pre
    this.next = next
  }

  /**
   * 链表长度
   */
  this.length = 0

  //append 向列表末尾插入节点
  BidirectionalLinkedList.prototype.append = ele => {
    const newNode = new Node(ele)
    //  链表为空时直接插入
    if (this.length === 0) {
      this.head = newNode
      this.tail = newNode
    } else {
      // 链表不为空时
      const lastNode = this.tail
      lastNode.next = newNode
      newNode.pre = lastNode
      this.tail = newNode
    }
    this.length += 1
  }

  // 在 position 位置插入节点
  BidirectionalLinkedList.prototype.insert = (position, ele) => {
    if (position < 0 || position > this.length) return
    const newNode = new Node(ele)
    let currentNode = this.head
    if (position === 0) {
      this.head = newNode
      currentNode.pre = newNode
      newNode.next = currentNode
      return this.length += 1
    }
    let index = 1
    while (index < this.length) {
      const preNode = currentNode
      currentNode = currentNode.next
      if (position === index) {
        preNode.next = newNode
        currentNode.pre = newNode
        newNode.pre = preNode
        newNode.next = currentNode
        return this.length += 1
      }
      index++

    }
  }

  // get 获取对应位置的结点
  BidirectionalLinkedList.prototype.get = position => {
    if (position < 0 || position >= this.length) return null
    let index = 0
    let currentNode = this.head
    while (index < this.length) {
      if (index >= 1) currentNode = currentNode.next
      if (position === index) return currentNode
      index++
    }
  }

  // indexOf 返回元素在列表中的索引
  BidirectionalLinkedList.prototype.indexOf = ele => {
    let index = 0
    let currentNode = this.head
    while (index < this.length) {
      if (index >= 1) currentNode = currentNode.next
      if (currentNode.data === ele) return index
      index++
    }
    return -1
  }

  // update 修改某个位置的元素
  BidirectionalLinkedList.prototype.update = (position, ele) => {
    if (position < 0 || position >= this.length) return false
    let index = 0
    let currentNode = this.head
    while (index < this.length) {
      if (index >= 1) currentNode = currentNode.next
      if (position === index) {
        currentNode.data = ele
        return true
      }
      index++
    }
  }

  // removeAt 删除某个位置的结点
  BidirectionalLinkedList.prototype.removeAt = position => {
    if (position < 0 || position >= this.length) return false
    let node = this.head
    if (position === 0) {
      if (this.length > 1) {
        node.next.pre = null
        this.head = node.next
      } else {
        this.head = this.tail = null
      }
      this.length -= 1
      return true
    }
    let index = 1
    while (index < this.length) {
      if (position === index) {
        // 当前index索引位置结点的前驱
        const preNode = node
        // const currentNode = node.next
        // 当前index索引位置结点的后继
        const nextNode = node.next.next
        // 如果是最后一个结点,尾结点前移
        if (position === this.length - 1) {
          preNode.next = nextNode
          this.tail = preNode
        } else {
          nextNode.pre = preNode
          preNode.next = nextNode
        }
        this.length -= 1
        return true
      }
      index++
      node = node.next
    }
  }

  // remove 删除特定元素节点
  BidirectionalLinkedList.prototype.remove = data => {
    let node = this.head
    if (node.data === data) {
      if (this.length > 1) {
        const newHeadNode = node.next
        newHeadNode.pre = null
        this.head = newHeadNode
      } else {
        this.head = this.tail = null
      }
      this.length -= 1
      return true
    }
    let index = 1
    while (index < this.length) {
      const preNode = node
      const currentNode = node.next
      const nextNode = currentNode.next
      if (currentNode.data === data) {
        if (index === this.length - 1) {
          preNode.next = nextNode
          this.tail = preNode
        } else {
          nextNode.pre = preNode
          preNode.next = nextNode
        }
        this.length -= 1
        return true
      }
      node = node.next
      index++
    }
    return false
  }

  //toString 将链表的所有节点的值拼接成一个字符串
  BidirectionalLinkedList.prototype.toString = () => {
    if (this.length === 0) return ''
    let currentNode = this.head
    let resultStr = ''
    while (currentNode) {
      resultStr += currentNode.data + ' '
      currentNode = currentNode.next
    }
    return resultStr
  }

  // forwardString 返回正向遍历的结点字符串形式
  BidirectionalLinkedList.prototype.forwardString = () => this.toString()

  // backwordString 返回反向遍历的结点字符串形式
  BidirectionalLinkedList.prototype.backwordString = () => {
    let lastNode = this.tail
    let resultStr = ''
    while (lastNode) {
      resultStr += lastNode.data + ' '
      lastNode = lastNode.pre
    }
    return resultStr
  }
  BidirectionalLinkedList.prototype.size = () => this.length

  BidirectionalLinkedList.prototype.isEmpty = () => this.length === 0
}

与数组的区别
  • 数组是线性表的顺序存储结构,链表是数组的链式存储结构:数组的内存空间必须是连续的,知道上一个元素的内存地址就可以推导出其他元素的内存地址,而链表的内存空间不是必须的连续,逻辑上连续但物理上不一定连续,可以实现灵活的内存动态管理
  • 数组可以通过索引号直接拿到元素,而链表找一个元素必须从头开始找,无法通过下标值直接访问某个元素
  • 链表在插入和删除时效率非常高O(1),而数组在插入和删除时效率比较低,因为需要移动数组里面元素的位置
栈、队列、链表、数组区别

待补充

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值