• LinkedList


    类的属性

    public class LinkedList<E>
        extends AbstractSequentialList<E>
        implements List<E>, Deque<E>, Cloneable, java.io.Serializable
    {
        // 实际元素个数
        transient int size = 0;
        // 指向头节点的指针
        transient Node<E> first;
        // 指向尾节点的指针
        transient Node<E> last;
    }    
    

    构造函数

    LinkedList()型构造函数 

    public LinkedList() {
    }
    

    LinkedList(Collection<? extends E>)型构造函数  

    public LinkedList(Collection<? extends E> c) {
            // 调用无参构造函数
            this();
            // 添加集合中所有的元素
            addAll(c);
        }
    

    核心函数分析

    add(E e)函数

    public boolean add(E e) {
            // 添加到末尾
            linkLast(e);
            return true;
        }
    

    linklast(E e)函数分析 addLast函数的实际调用

    	void linkLast(E e) {
            // 记住尾结点指针
            final Node<E> l = last;
            // 新结点的prev为l,后继为null,值为e
            final Node<E> newNode = new Node<>(l, e, null);
            // 更新尾结点指针
            last = newNode;    
            if (l == null) // 如果链表为空
                first = newNode; // 头指针等于尾指针
            else // 尾结点不为空
                l.next = newNode; // 尾结点的后继为新生成的结点
            // 大小加1    
            size++;
            // 结构性修改加1
            modCount++;
        }
    

    linkFirst(E e)函数 addFirst函数的实际调用

    	private void linkFirst(E e) {
    		//记住头结点
            final Node<E> f = first;
            //实例化新节点,prev = null,last = first
            final Node<E> newNode = new Node<>(null, e, f);
            //头指针指向新节点
            first = newNode;
            if (f == null)
            	//如果头指针为空的话,尾指针也指向新节点
                last = newNode;
            else
                f.prev = newNode;
            size++;
            modCount++;
        }
    

    add(int index,E element)函数

        public void add(int index, E element) {
            checkPositionIndex(index);
    
            if (index == size)
                linkLast(element);
            else
                linkBefore(element, node(index));
        }
    

    linkBefore(E e,Node succ)

       void linkBefore(E e, Node<E> succ) {
            // 记住前驱
            final Node<E> pred = succ.prev;
            //实例化新节点,初始化前驱,后继
            final Node<E> newNode = new Node<>(pred, e, succ);
            succ.prev = newNode;
            if (pred == null)
            	//如果为头插,修改头指针指向该新节点
                first = newNode;
            else
                pred.next = newNode;
            size++;
            modCount++;
        }
    

    addAll(int index, Collection<? extends E> c)函数

    	// 添加一个集合
        public boolean addAll(int index, Collection<? extends E> c) {
            // 检查插入的的位置是否合法
            checkPositionIndex(index);
            // 将集合转化为数组
            Object[] a = c.toArray();
            // 保存集合大小
            int numNew = a.length;
            if (numNew == 0) // 集合为空,直接返回
                return false;
    
            Node<E> pred, succ; // 前驱,后继,注意是插入整个集合的入前驱与后继
            if (index == size) { // 如果插入位置为链表末尾,则后继为null,前驱为尾结点
                succ = null;
                pred = last;
            } else { // 插入位置为其他某个位置
                succ = ode(index); n// 寻找到该结点
                pred = succ.prev; // 保存该结点的前驱
            }
    
            for (Object o : a) { // 遍历数组
                E e = (E) o; // 向下转型
                // 生成新结点
                Node<E> newNode = new Node<>(pred, e, null);
                if (pred == null) // 表示在第一个元素之前插入(索引为0的结点)
                    first = newNode;
                else
                    pred.next = newNode;
                pred = newNode;
            }
    
            if (succ == null) { // 表示在最后一个元素之后插入
                last = pred;
            } else {
                pred.next = succ;
                succ.prev = pred;
            }
            // 修改实际元素个数
            size += numNew;
            // 结构性修改加1
            modCount++;
            return true;
        }
    

    node(int index)函数

    Node<E> node(int index) {
            // 判断插入的位置在链表前半段或者是后半段
            if (index < (size >> 1)) { // 插入位置在前半段
                Node<E> x = first; 
                for (int i = 0; i < index; i++) // 从头结点开始正向遍历
                    x = x.next;
                return x; // 返回该结点
            } else { // 插入位置在后半段
                Node<E> x = last; 
                for (int i = size - 1; i > index; i--) // 从尾结点开始反向遍历
                    x = x.prev;
                return x; // 返回该结点
            }
        }
    

    为什么不分成三段,因为链表的取index结点依赖于first和last指针,即使分成再多的段,定位多么的精确,还是要从first或者last开始遍历

    remove(Object o)函数

        public boolean remove(Object o) {
            if (o == null) {
            	//同样说明LinkedList允许插入null
                for (Node<E> x = first; x != null; x = x.next) {
                    if (x.item == null) {
                        unlink(x);
                        return true;
                    }
                }
            } else {
                for (Node<E> x = first; x != null; x = x.next) {
                    if (o.equals(x.item)) {
                        unlink(x);
                        return true;
                    }
                }
            }
            return false;
        }
    

    unlink(Node x)函数

        E unlink(Node<E> x) {
            //返回x的结点值
            final E element = x.item;
            //记住前驱
            final Node<E> next = x.next;
            //记住后继
            final Node<E> prev = x.prev;
            //如果删除的结点是头结点,头指针指向next
            if (prev == null) {
                first = next;
            } else {
                prev.next = next;
                x.prev = null;
            }
            //如果删除的结点是尾结点,尾指针指向prev
            if (next == null) {
                last = prev;
            } else {
                next.prev = prev;
                x.next = null;
            }
            //集合内容清null
            x.item = null;
            size--;
            modCount++;
            return element;
        }
    

    unlinkFirst(Node f)函数 removeFirst函数的实际调用

        private E unlinkFirst(Node<E> f) {
            // 记住结点值和后继
            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;
            size--;
            modCount++;
            return element;
        }
    

    unlinkLast(Node l) removeLast函数的实际调用

        private E unlinkLast(Node<E> l) {
            // 记住结点值和前驱
            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;
            size--;
            modCount++;
            return element;
        }
    
  • 相关阅读:
    你真的知道什么是三观吗?
    iOS block 的两大常见用法
    微信小程序开发入门
    Linux 简介
    OC 的Runtime 消息转发机制
    关于 ES6 的 let ,var和 const
    python time,datetime
    python操作mysql(pymysql + sqlalchemy)
    python操作redis
    python操作memcached
  • 原文地址:https://www.cnblogs.com/kundeg/p/8386953.html
Copyright © 2020-2023  润新知