JavaScript实现单链表

86 阅读1分钟

单链表

    原来的数组结构缺点很多
    1、数组通常需要申请一端连续的内存空间,而且大小固定,所以当这个数组不能满足容量要求需要扩容
    2、插入成本高
    3、虽然JavaScript的Array类可以给我们做这一些事,但背后的原理依然是这样的
    
    链表优点: 
    1、内存空间不是连续的
    2、每一个元素存储元素本身的节点和一个指向下一个元素的引用
    3、不必要在创建确定大小,区别数组
    4、插入和删除操作效率高,时间复杂度为O(1)
    5、但是查找效率低,需要从头访问元素
    
    链表结构: head -> [item, next] -> [item, next] -> null
/**
* @Description: 单向链表
* @Author: 谭舒琪
* @Date: 2022-12-27 20:12:20
* @LastEditTime: 2022-12-27 20:12:20
* @LastEditors: Please set LastEditors
*/

function LinkedList() {
    this.head = null
    this.length = 0

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

    // 添加
    LinkedList.prototype.append = (data) => {
        const newNode = new Node(data)

        // 是否是第一个节点
        if (this.length === 0) {
            this.head = newNode
        } else {
            let current = this.head
            while(current.next) {
                current = current.next
            }
            current.next = newNode
        }
        this.length += 1
    }

    // 打印
    LinkedList.prototype.toString = () => {
        let listStr = ''
        let current = this.head
        while(current) {
            listStr += current.data + " "
            current = current.next
        }
        return listStr
    }

    // 插入指定位置
    LinkedList.prototype.insert = (position, data) => {
        if (position < 0 || position > this.length) {
            return false
        }
        const newNode = new Node(data)
        // 是否是插入头部
        if (position === 0) {
            newNode.next = this.head
            this.head = newNode
        } else {
            let index = 0
            let current = this.head
            let previous = null
            while(index++ < position) {
                previous = current
                current = current.next    
            }
            newNode.next = current
            previous.next = newNode
        }
        this.length += 1
        return true
    }

    // 获取指定元素
    LinkedList.prototype.get = (position) => {
        if (position < 0 || position >= this.length) {
            return null
        }
        let index = 0
        let current = this.head
        while(index++ < position) {
            current = current.next
        }
        return current.data
    }

    // 获取索引
    LinkedList.prototype.indexOf = (data) => {
        let index = 0
        let current = this.head
        while(current) {
            if (current.data === data) {
                return index
            }
            current = current.next
            index += 1
        }
        return -1
    }

    // 修改一个元素
    LinkedList.prototype.update = (position, data) => {
        if (position < 0 || position >= this.length) {
            return false
        }
        let current = this.head 
        let index = 0
        while(index++ < position) {
            current = current.next
        }
        current.data = data
        return true
    }

    // 移除指定下标的元素
    LinkedList.prototype.removeAt = (position) => {
        if (position < 0 || position >= this.length) {
            return false
        }
        // 是否是移除头部
        if (position === 0) {
            let current = this.head
            this.head = current.next 
        } else {
            let index = 0
            let current = this.head
            let previous = null
            while(index++ < position) {
                previous = current
                current = current.next
            }
            previous.next = current.next
        }
        this.length -= 1
        return true
    }

    // 移除指定元素
    LinkedList.prototype.remove = (data) => {
        let index = 0
        let current = this.head
        while(current) {
            if (current.data === data) {
                this.removeAt(index)
                return true
            } else {
                current = current.next
                index += 1
            }
        }
        return false
    }

    // 是否为空
    LinkedList.prototype.isEmpty = () => {
        if (this.length > 0) {
            return false
        } else {
            return true
        }
    }

    // 获取元素大小
    LinkedList.prototype.size = () => {
        return this.length
    }
}