链表的javascript实现

作者: 会飞小超人 | 来源:发表于2019-01-15 15:42 被阅读3次

链表数据结构

链表存储有序的元素集合,但不同于数组,链表中的元素在内存中并不是连续放置的。每个元素由一个存储本身的节点和一个指向下一个元素的引用(指针)组成。下图展示了一个链表的结构:


NeatReader-1547536785071.png

相对于传统的数组,链表的一个好处在于,添加或移除元素的时候不需要移动其他元素。然而,链表需要使用指针,因此实现链表时需要额外注意。数组的另一个细节是可以直接访问任何位置的任何元素,而想要访问链表中间的一个元素,需要从起点开始迭代列表直到找到所需的元素。

链表的js实现

单向链表

单向链表只元素间只存在单向引用的链表。上面的图表示的就是单向链表的结构。

function LinkedList() {
  let Node = function (element) {
    this.element = element
    this.next = null
  }

  let length = 0
  let head = null

  this.append = function (element) { // 向链表尾部加一个元素
    let node = new Node(element)
    let current

    if (head === null) {
      head = node
    } else {
      current = head

      while (current.next) {
        current = current.next
      }

      current.next = node
    }

    length++
  }

  this.removeAt = function (position) { // 移除指定位置的元素
    if (position > -1 && position < length) {
      let current = head
      previous,
        index = 0

      if (position === 0) {
        head = current.next
      } else {
        while (index++ < position) {
          previous = current
          current = current.next
        }

        previous.next = current.next
      }

      length--

      return current.element
    } else {
      return null
    }
  }

  this.insert = function (position, element) { // 在任意位置插入元素
    if (position >= 0 && position <= length) {
      let node = new Node(element),
        current = head,
        previous,
        index = 0

      if (position === 0) {
        node.next = current
        head = node
      } else {
        while (index++ < position) {
          previous = current
          current = current.next
        }
        node.next = current
        previous.next = node
      }

      length++

      return true
    } else {
      return false
    }
  }

  this.toString = function () {
    let current = head,
      string = ''

    while (current) {
      string += current.element + (current.next ? ',' : '')
      current = current.next
    }
    return string
  }

  this.indexOf = function (element) {
    let current = head,
      index = 0

    while (current) {
      if (element === current.element) {
        return index
      }
      index++
      current = current.next
    }
    return -1
  }

  this.remove = function (element) {
    let index = this.indexOf(element)
    return this.removeAt(index)
  }

  this.isEmpty = function () {
    return length === 0
  }

  this.size = function () {
    return length
  }

  this.getHead = function () {
    return head
  }

}

双向链表

双向链表只一个节点包含上节点和下节点的引用。因此称为双向的。如下图:


NeatReader-1547537580674.png
function DoubleLinkedList() {
  let Node = function (element) {
    this.element = element
    this.next = null
    this.prev = null
  }

  let length = 0
  let head = null
  let tail = null

  this.append = function (element) {
    let node = new Node(element),
      current

    if (head === null) {
      head = node
      tail = node
    } else {
      current = tail
      current.next = node
      node.prev = current
      tail = node
    }
    length++
  }

  this.insert = function (position, element) {
    if (position >= 0 && position <= length) {
      let node = new Node(element),
        current = head,
        previous,
        index = 0

      if (position === 0) {
        if (!head) {
          head = node
          tail = node
        } else {
          node.next = current
          current.prev = node
          head = node
        }
      } else if (position === length) {
        current = tail
        current.next = node
        node.prev = current
        tail = node
      } else {
        while (index++ < position) {
          previous = current
          current = current.next
        }
        node.next = current
        previous.next = node

        current.prev = node
        node.prev = previous
      }

      length++

      return true
    } else {
      return false
    }
  }

  this.removeAt = function (position) {
    if (position > -1 && position < length) {
      let current = head,
        previous,
        index = 0

      if (position === 0) {
        head = current.next

        if (length === 1) {
          tail = null
        } else {
          head.prev = null
        }
      } else if (position === length - 1) {
        current = tail
        tail = current.prev
        tail.next = null
      } else {
        while (index++ < position) {
          previous = current
          current = current.next
        }

        previous.next = current.next
        current.next.prev = previous
      }

      length--

      return current.element
    } else {
      return null
    }
  }

  // 其他方法实现和单向链表一样
}

循环链表

循环链表指链表的尾部链表的头部之间存在引用,因此形成了一个循环。如下图:
单向循环链表


NeatReader-1547537771149.png

双向循环链表


NeatReader-1547537822210.png

下面是单向循环链表的实现,双向循环链表的实现大同小异。

unction CircularLinkedList() {
  const Node = function (element) {
    this.element = element
    this.next = null
  }
  let head = null
  let length = 0

  this.append = function (element) {
    let node = new Node(element)
    let current
    if (head === null) {
      head = node
    } else {
      current = head
      while (current.next !== head) {
        current = current.next
      }
      current.next = node
      node.next = head
      length++
    }
  }

  this.removeAt = function (position) {
    if (position > -1 && position < length) {
      let current = head,
        previous,
        index = 0

      if (position === 0) {
        while (current.next !== head) {
          current = current.next
        }
        head = head.next
        current.next = head
      } else {
        while (index++ < position) {
          previous = current
          current = current.next
        }
        previous.next = current.next
      }
      length--
      return current.element
    } else {
      return null
    }
  }

  this.insert = function (position, element) {
    if (position >= 0 && position <= length) {
      let node = new Node(element),
        current = head,
        previous,
        index = 0

      if (position === 0) {
        node.next = current
        while (current.next !== head) {
          current = current.next
        }
        head = node
        current.next = head
      } else {
        while (index++ < position) {
          previous = current
          current = current.next
        }
        previous.next = node
        node.next = current

        if (node.next === null) {
          node.next = head
        }
      }

      length++
      return true
    } else {
      return false
    }
  }

  // 其他方法实现和单向链表一样
  
}

总结

链表对比数组主要有以下有优缺点:

  • 数组添加或者移除元素需要移动其他的元素,而链表不用,链表只需要改动相邻的元素即可。
  • 数组可以直接访问指定位置的元素,而链表则需要从表头开始迭代直至找到指定位置的元素。

相关文章

  • 用JavaScript实现双向链表

    用JavaScript实现双向链表 前言 JavaScript本身是没有指针的,所以要实现链表的话没有现成的数据结...

  • javaScript简单实现链表

    JavaScript没有直接的链表实现,以下是自己对链表的简单实现 实现之后进行如下调用:var linkedLi...

  • javascript实现链表

    一:线性表的定义 线性表是一种数结构;线性表有两种存储方式连续存储以及链表存储;其基本组成称为数据节点; 1:连续...

  • 链表的javascript实现

    链表数据结构 链表存储有序的元素集合,但不同于数组,链表中的元素在内存中并不是连续放置的。每个元素由一个存储本身的...

  • javascript 实现单链表

    链表是什么?链表(Linked-List)是由一组不必相连的节点,按照一定的顺序链接在一起的抽象数据模型 增删查操...

  • JavaScript 实现链表(LinkedList)

    单向链表 双向链表 未完待续

  • 05 (1)| javascript实现单链表

    在了解链表的基本结构和相关操作的原理,我们可以使用Javascript来实现链表以及其相关的增删该查工作了。 下面...

  • Merge Two Sorted Lists(LeetCode)

    Merge Two Sorted Lists 合并两个有序链表。 JavaScript 实现算法 更多语言方法解析...

  • 单链表 & 双链表& 单向循环链表的实现

    单链表 具体实现: 双链表 代码实现: 单向循环链表的实现 代码实现:

  • 单项链表(JavaScript实现)

    _链表:是一种物理存储单元上非连续、非顺序的存储结构。由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行...

网友评论

    本文标题:链表的javascript实现

    本文链接:https://www.haomeiwen.com/subject/hdqzrqtx.html