LinkedList的源码分析

LinkedList 简介

LinkedList 是继承于AbstractSequentialList的双向链表, 它可以被当做堆栈,队列或双端队列使用。
LinkedList 实现了List接口, 能对它进行队列操作。
LinkedList 实现了Cloneable接口, 覆盖了函数clone(), 支持克隆。
LinkedList 实现了Deque接口, 能将 LinkedList当做双端队列使用。
LinkedList 实现了Serializable接口,意味着支持序列化, 便于在网络中传输和保存。

public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable {
    
    }

LinkedList 是采用链表的方式来实现List接口的,它本身有自己特定的方法, 如: addFirst(),addLast(),getFirst(),getLast(),removeFirst()removeFirst()removeLast()

元素的插入与获取

addFirst() 和 addLast()

直接插入头部元素 和 尾部元素实现方式

public void addFirst(E e) {
    linkFirst(e);
}
private void linkFirst(E e) {
    final Node<E> f = first;
    final Node<E> newNode = new Node<>(null, e, f); //构造头部对象
    first = newNode;
    if (f == null) //如果f为空,则first == last
        last = newNode;
    else
        f.prev = newNode;  //否则 头节点为newNode
    size++;
    modCount++;
}
public void addLast(E e) {
        linkLast(e);
    }
//默认的添加方式也是由此方法实现    
void linkLast(E e) {
        final Node<E> l = last;
        final Node<E> newNode = new Node<>(l, e, null); //构造尾部对象
        last = newNode;
        if (l == null) //如果l为空,则first == last
            first = newNode;
        else
            l.next = newNode; //否则,尾节点为newNode
        size++;
        modCount++;
}
getFirst() 和 getLast()

直接获取头部元素 和 尾部元素实现方式

public E getFirst() {
    final Node<E> f = first;
    if (f == null)
        throw new NoSuchElementException();
    return f.item;
}
 public E getLast() {
        final Node<E> l = last;
        if (l == null)
            throw new NoSuchElementException();
        return l.item;
}

LinkedList 查找元素

public E get(int index) {
    checkElementIndex(index);
    return node(index).item;
}

Node<E> node(int index) {
    // assert isElementIndex(index);

    if (index < (size >> 1)) { //判断index 是否为 list size 的 一半
        Node<E> x = first;
        for (int i = 0; i < index; i++) // 从 0 ~ index 中循环遍历 
            x = x.next;
        return x;
    } else {
        Node<E> x = last;
        for (int i = size - 1; i > index; i--) // 从 index ~ zize - 1 中遍历
            x = x.prev;
        return x;
    }
}
由此得出结论:

LinkedList 采用了链表结构,所以在添加和删除方面效率高,查找比较慢

元素的删除

removeFirst() 和 removeLast()

LinkedList 移除首个元素 和 移除最后一个元素

//removeFirst 主要实现
private E unlinkFirst(Node<E> f) {
        // assert f == first && f != null;
        final E element = f.item;
        final Node<E> next = f.next;
        f.item = null; //将当前元素清空
        f.next = null; // help GC
        first = next;  //指针后移
        if (next == null)
            last = null;
        else
            next.prev = null; //将节点prev置空
        size--;
        modCount++;
        return element;
}

//removeLast 主要实现
private E unlinkLast(Node<E> l) {
        // assert l == last && l != null;
        final E element = l.item;
        final Node<E> prev = l.prev;
        l.item = null; //将当前元素清空
        l.prev = null; // help GC
        last = prev; //指针前移
        if (prev == null)
            first = null;
        else
            prev.next = null; //将节点next置空
        size--;
        modCount++;
        return element;
}

主要移除元素底层实现(根据下标移除,根据元素移除)
链表结构图如下:

将链表重新组装

E unlink(Node<E> x) {
        // assert x != null;
        final E element = x.item;
        final Node<E> next = x.next; //获取当前节点下一节点
        final Node<E> prev = x.prev; //获取当前节点上一节点

        if (prev == null) { //如果上一节点为空,则首节点下一节点
            first = next;
        } else { //将上一节点的下一节点替换为当前元素的下一节点
            prev.next = next;
            x.prev = null;
        }

        if (next == null) { //如果下一节点为空,则尾节点上一节点
            last = prev;
        } else { //将下一节点的上一节点替换为当前元素的下一节点
            next.prev = prev;
            x.next = null;
        }

        x.item = null;
        size--;
        modCount++;
        return element;
    }

LinkedList 用作堆栈

/**
 * LinkedList 实现堆栈的先进后出
 */
public class StackDemo {
    private LinkedList linkedList = new LinkedList<>();

    /**
     * 将每次添加的元素都添加到第一个位置
     *
     * @param o
     */
    public void push(Object o) {
        linkedList.addFirst(o);
    }

    /**
     * 取出第一个元素但是不删除元素
     *
     * @return
     */
    public Object peek() {
        return linkedList.peek();
    }

    /**
     * 取出并移除元素
     *
     * @return
     */
    public Object poll() {
        return linkedList.poll();
    }

    /**
     * 获取元素个数
     *
     * @return
     */
    public int size() {
        return linkedList.size();
    }

    /**
     * 判断堆栈是否为空 
     * (即判断 linkedList是否为空) 
     *
     * @return 
     */
    public boolean isEmpty() {
        return linkedList.isEmpty();
    }

    public static void main(String[] args) {
        StackDemo stackDemo = new StackDemo();
        stackDemo.push("1");
        stackDemo.push("2");
        stackDemo.push("3");
        stackDemo.push("4");
        stackDemo.push("5");

        System.out.println("取出第一个元素::::" + stackDemo.peek());
        System.out.println("取出第一个元素::::" + stackDemo.poll());

        while (!stackDemo.isEmpty()) {
            System.out.print(stackDemo.poll());
        }
    }
}

LinkedList 用作堆栈 输出结果为

插入第1个元素,值为 1
插入第2个元素,值为 2
插入第3个元素,值为 3
插入第4个元素,值为 4
插入第5个元素,值为 5
取出第一个元素 5
取出第一个元素 5
输出顺序为 4
输出顺序为 3
输出顺序为 2
输出顺序为 1

LinkedList 用作队列

/**
 * LinkedList 实现先进先出队列
 */
public class QueueDemo {


    public static void main(String[] args) {
        Queue queue = new LinkedList();
        //offer()方法是往队列尾部加入元素
        for (int i = 0; i < 5; i++) {
            queue.offer(i + 1);
            System.out.println("插入第"+ (i + 1) +"个元素," + "值为 " + (i + 1));
        }

        while (!queue.isEmpty()) {
            System.out.println("输出顺序 " + queue.poll());
        }


    }
}

输出结果为

插入第1个元素,值为 1
插入第2个元素,值为 2
插入第3个元素,值为 3
插入第4个元素,值为 4
插入第5个元素,值为 5
输出顺序 1
输出顺序 2
输出顺序 3
输出顺序 4
输出顺序 5

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。在编写C程序时,需要注意变量的声明和定义、指针的使用、内存的分配与释放等问题。C语言中常用的数据结构包括: 1. 数组:一种存储同类型数据的结构,可以进行索引访问和修改。 2. 链表:一种存储不同类型数据的结构,每个节点包含数据和指向下一个节点的指针。 3. 栈:一种后进先出(LIFO)的数据结构,可以通过压入(push)和弹出(pop)操作进行数据的存储和取出。 4. 队列:一种先进先出(FIFO)的数据结构,可以通过入队(enqueue)和出队(dequeue)操作进行数据的存储和取出。 5. 树:一种存储具有父子关系的数据结构,可以通过中序遍历、前序遍历和后序遍历等方式进行数据的访问和修改。 6. 图:一种存储具有节点和边关系的数据结构,可以通过广度优先搜索、深度优先搜索等方式进行数据的访问和修改。 这些数据结构在C语言中都有相应的实现方式,可以应用于各种不同的场景。C语言中的各种数据结构都有其优缺点,下面列举一些常见的数据结构的优缺点: 数组: 优点:访问和修改元素的速度非常快,适用于需要频繁读取和修改数据的场合。 缺点:数组的长度是固定的,不适合存储大小不固定的动态数据,另外数组在内存中是连续分配的,当数组较大时可能会导致内存碎片化。 链表: 优点:可以方便地插入和删除元素,适用于需要频繁插入和删除数据的场合。 缺点:访问和修改元素的速度相对较慢,因为需要遍历链表找到指定的节点。 栈: 优点:后进先出(LIFO)的特性使得栈在处理递归和括号匹配等问题时非常方便。 缺点:栈的空间有限,当数据量较大时可能会导致栈溢出。 队列: 优点:先进先出(FIFO)的特性使得
该资内项目码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资内项目码是个人的课程设计,代码都测试ok,都是运行成功后才上传资,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。
该资内项目码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资内项目码是个人的课程设计,代码都测试ok,都是运行成功后才上传资,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值