【数据结构与算法】--JavaScript 链表(一)

简介: 【数据结构与算法】--JavaScript 链表(一)

一、介绍


JavaScript 原生提供了数组类型,但是却没有链表,虽然平常的业务开发中,数组是可以满足基本需求,但是链表在大数据集操作等特定的场景下明显具有优势,那为何 JavaScript 不提供链表类型呢?怎么实现一个完整可用的链表呢?


数组的特点

  1. 线性结构,顺序存储
  2. 插入慢,查找快
  3. 查找、更新、插入、删除,的时间复杂度分别为,O(1)、O(1)、O(n)、O(n)

链表的特点

  1. 线性结构,随机存储(省内存)
  2. 插入快,查找慢
  3. 查找、更新、插入、删除,的时间复杂度分别为,O(n)、O(1)、O(1)、O(1)

二、单链表


talk is easy, show the code, 下面用 JavaScript 实现一个相对完整的单链表,并提供以下方法供调用:

  1. push(element) // 链表尾部插入节点
  2. pop() // 链表尾部删除节点
  3. shift() // 删除头部节点、
  4. unshift(element) // 插入头部节点
  5. find(index) // 查找指定位置节点
  6. insert(element, index) // 指定位置插入节点
  7. edit(element, index) // 修改指定位置节点
  8. delete(index) // 链表删除指定位置节点
  9. cycle() // 使链表首尾成环


function initList() {
    class Node {
        constructor(item) {
            this.element = item
        }
    }
    class List {
        constructor() {
            this.head = null
            this.size = 0
            this.last = null
        }
        /**
        * 链表查找元素
        * @param index 查找的位置
        */
        find(index) {
            let current = this.head
            for (let i = 0; i < index; i++) {
                current = current.next
            }
            return current
        }
        /**
        * 链表尾部插入元素
        * @param element 插入的元素
        */
        push(element) {
            let newNode = new Node(element)
            if (this.size === 0) {
                this.head = newNode
                this.head.next = null
                this.last = this.head
            } else {
                this.last.next = newNode
                this.last = newNode
                newNode.next = null
            }
            this.size += 1
        }
        /**
        * 链表尾部删除元素
        * @param element 删除的位置
        */
        pop(element) {
            this.last.next = null
        }
        /**
        * 链表头部删除元素
        */
        shift() {
            if (this.size === 0)
                return
            this.head = this.head.next
            if (this.size === 1)
                this.last = null
            this.size -= 1
        }
        /**
        * 链表头部插入元素
        * @param element 插入的元素
        */
        unshift(element) {
            let newNode = new Node(element)
            newNode.next = this.head
            this.head = newNode
            if (this.size === 0)
                this.last = this.head
            this.size += 1
        }
        /**
        * 链表插入元素
        * @param element 插入的位置, index 插入的位置
        */
        insert(element, index) {
            if (index < 0 || index > this.size) {
                console.error('超出链表节点范围')
                return
            }
            let newNode = new Node(element)
            if (this.size === 0) {
                // 空链表
                newNode.next = null
                this.head = newNode
                this.last = newNode
            } else if (index === 0) {
                // 插入头部
                newNode.next = this.head
                this.head = newNode
            } else if (index == this.size) {
                //插入尾部
                newNode.next = null
                this.last.next = newNode
                this.last = newNode
            } else {
                // 中间插入
                let preNode = this.find(index - 1)
                newNode.next = preNode.next
                preNode.next = newNode
            }
            this.size += 1
        }
        /*
        *链表编辑元素
        * @param element 编辑的元素,index 元素位置
        */
        edit(element, index) {
            let current = this.find(index)
            current.element = element
        }
        /*
        *链表删除元素
        * @param index 删除元素位置
        */
        delete(index) {
            let current = this.find(index)
            if (index === 0) {
                // 删除头节点
                this.head = this.head.next
            } else if (index === ((this.size) - 1)) {
                // 删除尾节点
                let preNode = this.find(index - 1)
                preNode.next = null
            } else {
                // 删除中间节点
                let preNode = this.find(index - 1)
                let nextNode = preNode.next.next
                let removeNode = preNode.next
                preNode.next = nextNode
            }
            this.size -= 1
        }
        /*
        *链表使首尾成环
        */
        cycle() {
            this.last.next = this.head
        }
    }
    return new List()
}
let list = initList()


目录
相关文章
|
2天前
|
存储
数据结构第二课 -----线性表之单向链表
数据结构第二课 -----线性表之单向链表
|
21小时前
|
前端开发 JavaScript 算法
JavaScript 中实现常见数据结构:栈、队列与树
JavaScript 中实现常见数据结构:栈、队列与树
|
22小时前
|
存储
数据结构链表详解(不仅顺序表可以,我链表也可以)
数据结构链表详解(不仅顺序表可以,我链表也可以)
9 0
|
2天前
|
存储 算法 Java
数据结构与算法 数组和链表
数据结构与算法 数组和链表
11 0
|
2天前
|
存储 Java
深入浅出数据结构之链表
深入浅出数据结构之链表
|
2天前
|
C++
数据结构(双链表
数据结构(双链表
10 1
|
2天前
|
存储 缓存
[数据结构]~双向+循环链表从(0~1)
[数据结构]~双向+循环链表从(0~1)
|
2天前
|
存储
数据结构第三课 -----线性表之双向链表
数据结构第三课 -----线性表之双向链表
|
2天前
|
存储 Java
数据结构奇妙旅程之顺序表和链表
数据结构奇妙旅程之顺序表和链表
|
2天前
|
存储 C语言
数据结构基础:双链表结构、实现
数据结构基础:双链表结构、实现