1.概念

  单向链表是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始;链表是使用指针进行构造的列表;又称为结点列表,因为链表是由一个个结点组装起来的;其中每个结点都有指针成员变量指向列表中的下一个结点;链表是由节点构成,head指针指向第一个成为表头结点,而终止于最后一个指向null的指针。

  可以将链表看成是一节节火车车厢,每一节车厢都连接着下一节车厢。示意图如下。

2.对链表进行封装

// 封装链表的构造函数
function LinkedList() {
  // 封装一个Node类, 用于保存每个节点信息
  function Node(element) {
    this.element = element
    this.next = null
  }
  // 链表中的属性
  this.length = 0
  this.head = null

  // 链表尾部追加元素方法
  LinkedList.prototype.append = function (element) {
    // 1.根据新元素创建节点
    var newNode = new Node(element)
    // 2.判断原来链表是否为空
    if (this.head === null) { // 链表尾空
      this.head = newNode
    } else { // 链表不为空
      // 2.1.定义变量, 保存当前找到的节点
      var current = this.head
      while (current.next) {
        current = current.next
      }
      // 2.2.找到最后一项, 将其next赋值为node
      current.next = newNode
    }
    // 3.链表长度增加1
    this.length++
  }

  // 链表的toString方法
  LinkedList.prototype.toString = function () {
    // 1.定义两个变量
    var current = this.head
    var listString = ""
    // 2.循环获取链表中所有的元素
    while (current) {
      listString += "," + current.element
      current = current.next
    }
    // 3.返回最终结果
    return listString.slice(1)
  }

  // 根据下标删除元素
  LinkedList.prototype.insert = function (position, element) {
    // 1.检测越界问题: 越界插入失败
    if (position < 0 || position > this.length) return false
    // 2.定义变量, 保存信息
    var newNode = new Node(element)
    var current = this.head
    var previous = null
    index = 0
    // 3.判断是否列表是否在第一个位置插入
    if (position === 0) {
      newNode.next = current
      this.head = newNode
    } else {
      while (index++ < position) {
        previous = current
        current = current.next
      }
      newNode.next = current
      previous.next = newNode
    }
    // 4.length+1
    this.length++
    return true
  }

  // 根据位置移除节点
  LinkedList.prototype.removeAt = function (position) {
    // 1.检测越界问题: 越界移除失败, 返回null
    if (position < 0 || position >= this.length) return null
    // 2.定义变量, 保存信息
    var current = this.head
    var previous = null
    var index = 0
    // 3.判断是否是移除第一项
    if (position === 0) {
      this.head = current.next
    } else {
      while (index++ < position) {
        previous = current
        current = current.next
      }
      previous.next = current.next
    }
    // 4.length-1
    this.length--
    // 5.返回移除的数据
    return current.element
  }

  // 根据元素获取链表中的位置
  LinkedList.prototype.indexOf = function (element) {
    // 1.定义变量, 保存信息
    var current = this.head
    index = 0
    // 2.找到元素所在的位置
    while (current) {
      if (current.element === element) {
        return index
      }
      index++
      current = current.next
    }
    // 3.来到这个位置, 说明没有找到, 则返回-1
    return -1
  }

  // 根据元素删除信息
  LinkedList.prototype.remove = function (element) {
    var index = this.indexOf(element)
    return this.removeAt(index)
  }

  // 判断链表是否为空
  LinkedList.prototype.isEmpty = function () {
    return this.length === 0
  }

  // 获取链表的长度
  LinkedList.prototype.size = function () {
    return this.length
  }

  // 获取第一个节点
  LinkedList.prototype.getFirst = function () {
    return this.head.element
  }
}
// 测试
var list = new LinkedList()
list.append(15)
list.append(10)
list.append(20)
list.insert(0, 100)
list.insert(4, 200)
list.insert(2, 300)
console.log(list)      // 100,15,300,10,20,200
list.removeAt(0)   //100
list.removeAt(1)   //300
list.removeAt(3)   //200
console.log(list)         // 15, 10, 20
console.log(list.indexOf(15))  // 0
console.log(list.indexOf(10))  // 1
console.log(list.indexOf(20))  // 2
console.log(list.indexOf(100)) // -1
console.log(list.isEmpty())   // false
console.log(list.size())      // 3
console.log(list.getFirst())  // 15
posted on 2021-03-14 14:33  李起桉  阅读(116)  评论(0)    收藏  举报