数据结构-链表(一)

104 阅读1分钟

数据结构学习第三天, 了解了链表的基本定义和结构,我的理解是链表是由值跟引用组成的元素首尾相连的线性数据结构。与数组对比链表不需要定义时开辟一个固定长度的内存空间,一个非常形象的例子就是把链表比作火车头以及火车车厢,如图:
image.png

单向链表的实现:
    class LinkedList {
      head = null
      length = 0
      constructor(element) {
        this.data = element
        this.next = null
      }

      // 追加元素
      append(element) {
        // 创建新节点
        let newNode = {
          data: element,
          next: null
        }
        // 判断链表是否为空
        if (this.length === 0) {
          this.head = newNode
        } else {
          // 不为空从第一个元素开始找 直到找到最后一个元素
          let curr = this.head
          while (curr.next) {
            curr = curr.next
          }
          // 将元素插入到链表的最后
          curr.next = newNode
        }
        this.length++
      }
      // 特定位置插入新的元素
      insert(position, element) {
        // 边界判断position
        if (position < 0 || position > this.length) return false
        // 根据data创建newNode
        const newNode = {
          data: element,
          next: null
        }
        // 插入数据
        if (position === 0) {
          newNode.next = this.head
          this.head = newNode
        } else {
          let index = 0
          let prev = null
          let curr = this.head
          while (index++ < position) {
            prev = curr
            curr = curr.next
          }
          newNode.next = curr
          prev.next = newNode
        }
        this.length++
        return true
      }
      // 获取对应位置的元素
      get(position) {
        // 边界判断position
        if (position < 0 || position >= this.length) return null
        // 获取对应的元素
        let curr = this.head
        let index = 0
        while (index++ < position) {
          curr = curr.next
        }
        return curr.data
      }
      // 返回元素的索引 没有则返回-1
      indexOf(element) {
        let curr = this.head
        let index = 0
        while (curr.next) {
          if (curr.data === element) {
            return index
          }
          curr = curr.next
          index++
        }
        return -1
      }
      // 修改某个位置元素
      update(position, element) {
        // 边界判断position
        if (position < 0 || position >= this.length) return false
        // 获取对应的元素
        let curr = this.head
        let index = 0
        while (index++ < position) {
          curr = curr.next
        }
        curr.data = element
        return true
      }
      // 从链表的特定位置移除某一项
      removeAt(position) {
        // 边界判断position
        if (position < 0 || position >= this.length) return false
        // 删除元素
        if (position === 0) {
          this.head = this.head.next
        } else {
          let index = 0
          let prev = null
          let curr = this.head
          while (index++ < position) {
            prev = curr
            curr = curr.next
          }
          prev.next = curr.next
        }
        this.length--
        return curr.data
      }
      // 从链表中移除某一项
      remove(element) {
        let position = this.indexOf(element)
        this.removeAt(position)
      }
      // toString方法
      toString() {
        let curr = this.head
        const stringList = []
        // 循环获取节点
        while (curr) {
          stringList.push(curr.data)
          curr = curr.next
        }
        return stringList.map(item => String(item)).join()
      }
}

与之前的栈结构,队列结构相比,链表的实现稍微复杂了些,但是理清楚思路还是不难。除了单向链表之外,还有双向链表更为复杂,明天尝试实现一波