单向链表

64 阅读2分钟
  1. 单向链表
  • 要存储多个元素, 另外一个选择就是使用链表.
  • 但不同于数组, 链表中的元素在内存中不必是连续的空间.
  • 链表的每个元素由一个存储元素本身的节点和一个指向下一个元素的引用(有些语言称为指针或者链接)组成.
  1. 相对于数组, 链表有一些优点:
  • 内存空间是连续的. 可以充分利用计算机的内存. 实现灵活的内存动态管理.
  • 链表不必在创建时就确定大小, 并且大小可以无限的延伸下去.
  • 链表在插入和删除数据时, 时间复杂度可以达到O(1). 相对数组效率高很多.
  1. 相对于数组, 链表有一些缺点:
  • 链表访问任何一个位置的元素时, 都需要从头开始访问.(无法跳过第一个元素访问任何一个元素).
  • 无法通过下标直接访问元素, 需要从头一个个访问, 直到找到对应的位置.

image.png

   // 设置节点的结构
  class Lnode {
    constructor(data) {
        this.data = data;
        this.next = null
    }
}

// 链表的结构
class LinkList {
    constructor() {
        this.head = null
        this.length = 0
    }
    // 添加新节点
    append(el) {
        // 创建新节点
        let newnode = new Lnode(el)
        // console.log(newnode);
        if (this.head == null) {
            this.head = newnode;

        } else {
            let current = this.head;

            while (current.next != null) {
                // 继续找
                current = current.next
            };

            current.next = newnode;
        }
        this.length++
    }

    // 任意位置插入节点
    insert(position, el) {
        // 检测位置是否合法
        if (position < 0 || position > this.length || !Number.isInteger(position)) {
            return false
        }
        let newnode = new Lnode(el)

        // 在头部添加
        if (position == 0) {
            if (this.head == null) {
                // 空链表
                this.head = newnode
            } else {
                // 非空
                newnode.next = this.head
                this.head = newnode
            }
            this.length++
        } else if (
            // 尾部添加
            position == this.length) {
            this.append()
        } else { //任意位置
            let current = this.head
            let index = 0
            while (index < position - 1) {
                current = current.next
                index++
            }
            // current就是插入位置的前一个节点
            newnode = current.next
            current.next = newnode

        }
        this.length++
    }

    removeAt(position) {
        // 检测位置是否合法
        if (position < 0 || position > this.length || !Number.isInteger(position)) {
            return false
        }

        if (this.head == null) { //空链表
            return
        } else {
            // 删除头部
            if (position == 0) {
                this.head = this.head.next
            } else {
                // 移除其他任意位置
                let current = this.head
                var index = 0
                while (index < position - 1) {
                    current = current.next
                    index++
                }
                current.next = current.next.next
            }
            this.length--
        }

    }
    // 查找指定元素位置
    indexOf(el) {
        let current = this.head
        var index = 0
        while (index < this.length) {
            if (current.data == el) {
                return index
            } else {
                current = current.next
                index++;
            }
        }
        return -1
    }
    // 移除指定元素
    remove(el) {
        let index = this.indexOf(el)
        console.log(index);
        this.removeAt(index)
    }

    // 是否为空列表
    isEmpty() {
        if (this.head == null) {
            return true
        } else {
            return false
        }
    }
//链表的长度
    sise() {
        return this.length
    }
}