单向链表

本文探讨了数组和单向链表的数据结构特点,包括数组的固定大小和内存连续性带来的缺点,以及链表的内存灵活性、高效插入和删除的优处。同时提供了单向链表的实现代码示例。
摘要由CSDN通过智能技术生成

目录

数组的缺点

单向链表 

优点

缺点 

实现单向链表


链表和数组一样,可以用于存储一系列的元素,但是链表和数组的实现机制完全不同。 

数组的缺点

  • 数组的创建通常需要申请一段连续的内存空间(一整块的内存),并且大小是固定的(大多数编程语言数组都是固定的),所以当当前数组不能满足容量需求时,需要扩容.(一般情况下是申请一个更大的数组,比如2倍,然后将原数组中的元素复制过去)
  • 而且在数组开头或中间位置插入数据的成本很高,需要进行大量元素的位移,。
  • 尽管我们的JavaScript的Array类方法可以帮我们做这些事,但背后的原理依然是这样。

单向链表 

链表类似于火车: 有一个火车头,火车头会连接一个节点,节点上有乘客(类似于数据),并且这个节点会连接下-个节点,以此类推.

要存储多个元素,可以选择链表,但不同于数组,链表中的元素在内存中不必是连续的空间
链表的每个元素由一个存储元素本身的节点和一个指向下一个元素的引用(有些语言称为指针或者连接)组成

优点

  • 内存空间不是必须连续的.可以充分利用计算机的内存,实现灵活的内存动态管理
  • 链表不必在创建时就确定大小,并且大小可以无限的延伸下去.
  • 链表在插入和删除数据时,时间复杂度可以达到O(1).相对数组效率高很多.

缺点 

  • 链表访问任何一个位置的元素时,都需要从头开始访问.(无法跳过第一个元素访问任何一个元素).
  • 无法通过下标直接访问元素,需要从头一个个访问,直到找到对应的元素.

实现单向链表

export class Node {
    constructor(element) {
        // 保存元素
        this.element = element
        // 指向下一个节点
        this.next = null
    }
}

export class LinkedList {
    constructor() {
        this.head = null
        this.length = 0
    }

    // append(element): 向列表尾部添加一个新的项
    append(element) {
        // 1. 根据element创建Node对象
        const newNode = new Node(element)
        // 2. 追加到最后
        if (!this.head) {
            this.head = newNode
        } else {
            let current = this.head
            while (current.next) {
                current = current.next
            }
            // next指向下一个节点
            current.next = newNode
        }
        this.length++
    }

    // insert(position, element): 向列表的特定位置插入一个新的项
    insert(position, element) {
        if (position < 0 || position > this.length) return false // 链表不能超过默认长度
        const newNode = new Node(element)
        // 插入元素
        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
            }
            previous.next = newNode
            newNode.next = current
        }
        this.length++
        return true
    }

    // get(position) 获取对应位置的元素
    get(position) {
        // 判断越界问题
        if (position < 0 || position > this.length - 1) return null
        // 查找该位置的元素
        let index = 0
        let current = this.head
        while (index++ < position) {
            current = current.next
        }
        return current.element
    }

    // indexOf(element) 返回元素在列表中的索引,如果列表中没有该元素则返回-1
    indexOf(element) {
        // 获取第一个元素
        let current = this.head
        let index = 0
        // 开始查找
        while (current) {
            if (current.element == element) {
                return index
            }
            index++
            current = current.next
        }
        return -1
    }

    // removeAt(position) 从列表的特定位置移除一项
    removeAt(position) {
        // 判断越界问题
        if (position < 0 || position > this.length - 1) return null
        // 删除元素
        let current = this.head
        let previous = null
        let index = 0
        if (position === 0) {
            this.head = current.next
        } else {
            while (index++ < position) {
                previous = current
                current = current.next
            }
            previous.next = current.next
        }
        this.length--
        return current.element
    }

    // update(position, element) 修改某个位置的元素
    update(position, element) {
        // 1. 删除position位置的元素
        const result = this.removeAt(position)
        // 2. 插入position位置element元素
        this.insert(position, element)
        return result
    }

    // remove(element) 从列表中移除一项
    remove(element) {
        // 获取元素的位置
        const index = this.indexOf(element)
        if (index === -1) return
        // 删除该位置的元素
        this.removeAt(index)
    }

    // isEmpty() 如果链表中不包含任何元素,返回true,如果链表长度大于0则返回false
    isEmpty() {
        return this.length === 0
    }

    // size() 返回链表包含的元素个数,与数组的length属性类似
    size() {
        return this.length
    }
}

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山楂树の

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值