From 7f055c75f671ae3492a4976376101bae3206bf89 Mon Sep 17 00:00:00 2001 From: ConanJu_pc Date: Thu, 19 Dec 2019 16:55:53 +0800 Subject: [PATCH] add week_01/42/LinkedList.md LinkedList.md --- week_01/42/LinkedList.md | 694 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 694 insertions(+) create mode 100644 week_01/42/LinkedList.md diff --git a/week_01/42/LinkedList.md b/week_01/42/LinkedList.md new file mode 100644 index 0000000..c964064 --- /dev/null +++ b/week_01/42/LinkedList.md @@ -0,0 +1,694 @@ +/** + * 继承与AbstractSequentialList的双向链表 + * 实现了List接口,那么可以当作队列来进行操作 + * 支持序列化,可以支持流传输 + * + * + */ +public class LinkedList + extends AbstractSequentialList + implements List, Deque, Cloneable, java.io.Serializable +{ + transient int size = 0; + + // 链表头节点 + transient Node first; + + // 链表尾节点 + transient Node last; + + // 节点使用内部类表示 + private static class Node { + E item; // 当前元素 + Node next; // 指向该节点的下一个节点 + Node prev; // 指向该节点的上一个节点 + + Node(Node prev, E element, Node next) { + this.item = element; + this.next = next; + this.prev = prev; + } + } + + public LinkedList() { + } + + // 先调用无参构造方法,在添加元素 + public LinkedList(Collection c) { + this(); + addAll(c); + } + + + // 获取首节点元素,如果首节点为空抛出异常(RuntimeException) + public E getFirst() { + final Node f = first; + if (f == null) + throw new NoSuchElementException(); + return f.item; + } + + // 获取尾节点元素,如果首节点为空抛出异常(RuntimeException) + public E getLast() { + final Node l = last; + if (l == null) + throw new NoSuchElementException(); + return l.item; + } + + // 删除首节点,首节点不存在抛出异常 + public E removeFirst() { + final Node f = first; + if (f == null) + throw new NoSuchElementException(); + return unlinkFirst(f); + } + + // 删除尾节点,尾节点不存在抛出异常 + public E removeLast() { + final Node l = last; + if (l == null) + throw new NoSuchElementException(); + return unlinkLast(l); + } + + // 添加首节点 + public void addFirst(E e) { + linkFirst(e); + } + + // 添加尾节点 + public void addLast(E e) { + linkLast(e); + } + + // 添加集合元素,添加成功之后返回true + public boolean addAll(Collection c) { + return addAll(size, c); + } + + // 在当前集合最后一个元素之后添加元素 + public boolean addAll(int index, Collection c) { + // 检查当前集合是否以及最大长度 + checkPositionIndex(index); + // 入参集合转化为对象数组 + Object[] a = c.toArray(); + // 被添加的集合为空则添加失败并且返回为false + int numNew = a.length; + if (numNew == 0) + return false; + + // 如果添加的元素时,当前集合没有发生变化,则定义pred 指向尾节点。 + Node pred, succ; + if (index == size) { + succ = null; + pred = last; + } else { + // 如果发生了变化,移动末节点 + succ = node(index); + // 指向末节点的下一个元素 + pred = succ.prev; + } + + // 遍历集合数组 + for (Object o : a) { + @SuppressWarnings("unchecked") E e = (E) o; + // 创建节点对象 + Node newNode = new Node<>(pred, e, null); + // 说明首节点元素为空 + if (pred == null) + // should节点赋值给第一个元素 + first = newNode; + else + // 其他元素依次指向下一个节点(以链表的形式) + pred.next = newNode; + pred = newNode; + } + + if (succ == null) { + last = pred; + } else { + pred.next = succ; + succ.prev = pred; + } + + size += numNew; + modCount++; + return true; + } + + + /** + * Returns the (non-null) Node at the specified element index. + */ + Node node(int index) { + // assert isElementIndex(index); + + if (index < (size >> 1)) { + Node x = first; + for (int i = 0; i < index; i++) + x = x.next; + return x; + } else { + Node x = last; + for (int i = size - 1; i > index; i--) + x = x.prev; + return x; + } + } + + /** + * 从队首添加元素 + */ + private void linkFirst(E e) { + // 首节点 + final Node f = first; + // 创建一个新的节点对象,该节点的next节点是首节点 + final Node newNode = new Node<>(null, e, f); + // 新节点作为新的首节点 + first = newNode; + // 如果原始首节点为空(第一次添加元素) + if (f == null) + // 新节点对象作为尾节点(创建一个双向链表) + last = newNode; + else // 原始首对象对象不为空(不是第一次添加元素) + // 则原始首节点的前一个元素指向新节点对象 + f.prev = newNode; + size++; //元素个数+1 + modCount++; // 操作记录+1 + } + + /** + * 从队列尾端添加元素 + */ + void linkLast(E e) { + // 尾结点 + final Node l = last; + // 创建新的节点对象,尾节点的next元素指向新节点对象 + final Node newNode = new Node<>(l, e, null); + // 新的节点作为新的尾节点 + last = newNode; + if (l == null) // 原始尾节点为空(第一次添加元素) + first = newNode; // 新的节点作为首节点(创建双向队列) + else // 如果不是第一次添加元素 + l.next = newNode; // 元素尾结点的下一个节点指向新节点对象 + size++; // 元素+1 + modCount++; // 操作+1 + } + + /** + * Inserts element e before non-null Node succ. + * 在指定节点succ前添加一个元素 + */ + void linkBefore(E e, Node succ) { + // assert succ != null; + // 指定节点前一个元素 + final Node pred = succ.prev; + // 创建新节点对象,新节点对象的next节点对象是succ,新节点对象prev节点是succ.prev + final Node newNode = new Node<>(pred, e, succ); + // 新节点作为,succ的prev节点 + succ.prev = newNode; + // 原始 succ.prev 如果为空(则说明succ本身就是首节点) + if (pred == null) + // 新节点对象作为首节点 + first = newNode; + else // 如果succ不是首节店 + // 新的节点作为 succ原始prev节点的next节点 + pred.next = newNode; + size++; // 元素+1 + modCount++; // 操作+1 + } + + /** + * Unlinks non-null first node f. + * 删除首节点 + */ + private E unlinkFirst(Node f) { + // assert f == first && f != null; + // 首节点元素 + final E element = f.item; + // 首节点的下一个元素 + final Node next = f.next; + // 首节点置为空 + f.item = null; + // 首节点的下一个元素置为空 + f.next = null; // help GC + // 原始首节点的下一个元素作为新的首节点 + first = next; + // 如果原始首节点下一个节点为空 + if (next == null) + // 尾节点也置为空 + last = null; + else // 原始首节点下一个节点不为空 + // 原始首节点的下一个节点的prev置为空 + next.prev = null; + size--; // 元素-1 + modCount++; // 操作+ 1 + return element; // 返回删除的元素 + } + + /** + * Unlinks non-null last node l. + * 删除尾节点 + */ + private E unlinkLast(Node l) { + // assert l == last && l != null; + // 尾节点元素 + final E element = l.item; + // 尾节点前置元素 + final Node prev = l.prev; + // 尾节点元素置为空 + l.item = null; + // 尾结点前置元素也置为空 + l.prev = null; // help GC + // 原始尾节点的prev节点作为新的尾节点 + last = prev; + // 如果原始尾结点的prev节点为空(也就是只有一个元素的时候) + if (prev == null) + // 首节点置为空 + first = null; + else // 如果元素集合不止一个元素 + // 原始尾节点的prev节点后置节点置为空 + prev.next = null; + size--; // 元素-1 + modCount++; // 操作+1 + return element; // 返回该元素 + } + + /** + * Unlinks non-null node x. + * 删除指定节点 + */ + E unlink(Node x) { + // assert x != null; + // 指定节点元素 + final E element = x.item; + // 指定节点后置节点 + final Node next = x.next; + // 指定节点前置节点 + final Node prev = x.prev; + + // 如果前置节点为空(说明只有一个元素) + if (prev == null) { + // 则指定节点后置节点作为新的首节点 + first = next; + } else { // 如果前置节点不为空(大于1个元素) + // 则指定节点后置节点作为指定节点前置节点的next元素 + prev.next = next; + // 指定节点的prev节点置为空(去掉无效引用) + x.prev = null; + } + + // 如果后置节点为空(说明只有一个元素) + if (next == null) { + // 指定节点前置节点作为新的首节点 + last = prev; + } else { + // 如果后置节点不为空(说明不只有一个元素) + // 指定节点的前置节点作为,指定节点后置节点的prev + next.prev = prev; + // 指定节点的后置引用置为空 + x.next = null; + } + // 指定节点置为空 + x.item = null; + // 元素-1 + size--; + modCount++; // 操作+1 + return element; // 返回删除的元素 + } + + + + + + + public boolean contains(Object o) { + return indexOf(o) != -1; + } + + + public int size() { + return size; + } + + // 添加元素方法,从队列尾端添加元素,并且返回true + public boolean add(E e) { + linkLast(e); + return true; + } + + // 删除第一次出现的指定对象, + //(可以存相同对象,但是调用该方法只删除第一次出现的对象) + public boolean remove(Object o) { + // 如果被删除的元素为空 + if (o == null) { + for (Node x = first; x != null; x = x.next) { + if (x.item == null) { + unlink(x); + return true; + } + } + } else { + for (Node x = first; x != null; x = x.next) { + if (o.equals(x.item)) { + unlink(x); + return true; + } + } + } + return false; + } + + + + // 清楚集合 + public void clear() { + + for (Node x = first; x != null; ) { + Node next = x.next; + x.item = null; + x.next = null; + x.prev = null; + x = next; + } + first = last = null; + size = 0; + modCount++; + } + + + // 获取指定为空元素 + public E get(int index) { + // 是否越界 + checkElementIndex(index); + // 获取指定节点对象元素 + return node(index).item; + } + + // 替换指定下表元素并且返回被替换的对象,从0开始计数 + public E set(int index, E element) { + // 检查是否越界 + checkElementIndex(index); + // 获取指定位置元素对象 + Node x = node(index); + // 取出老对象 + E oldVal = x.item; + // 替换对象 + x.item = element; + // 返回老对象 + return oldVal; + } + + // 指定位置添加元素 + public void add(int index, E element) { + checkPositionIndex(index); + + if (index == size) + linkLast(element); + else + linkBefore(element, node(index)); + } + + // 删除指定位置元素 + public E remove(int index) { + // 是否越界 + checkElementIndex(index); + // 获取指定位置节点,然后再删除改节点 + return unlink(node(index)); + } + + // 是否在元素下标范围内(用来检查元素是否越界) + private boolean isElementIndex(int index) { + return index >= 0 && index < size; + } + + // 检查是否可插入元素范围(可插入范围[0,size]) + private boolean isPositionIndex(int index) { + return index >= 0 && index <= size; + } + + + private String outOfBoundsMsg(int index) { + return "Index: "+index+", Size: "+size; + } + + private void checkElementIndex(int index) { + if (!isElementIndex(index)) + throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); + } + + private void checkPositionIndex(int index) { + if (!isPositionIndex(index)) + throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); + } + + /** + * Returns the (non-null) Node at the specified element index. + * 根据指定下标找到对应元素[0,size] + * 分段便于集合,前半段返回的时候是返回的指定下标前一个元素的next节点 + * 后半段遍历的时候是返回指定下标的,prev节点 + */ + Node node(int index) { + // assert isElementIndex(index); + // size >> 1 表示size右移一位,相当于除以2 + // 指定位置,是否位于集合前半段 + if (index < (size >> 1)) { + Node x = first; + // 从0遍历到指定位置,然后返回 + for (int i = 0; i < index; i++) + x = x.next; + return x; + } else { + Node x = last; + // 从尾端开始遍历,返回指定位置前置元素 + for (int i = size - 1; i > index; i--) + x = x.prev; + return x; + } + } + + // Search Operations + + + public int indexOf(Object o) { + int index = 0; + if (o == null) { + for (Node x = first; x != null; x = x.next) { + if (x.item == null) + return index; + index++; + } + } else { + for (Node x = first; x != null; x = x.next) { + if (o.equals(x.item)) + return index; + index++; + } + } + return -1; + } + + public int lastIndexOf(Object o) { + int index = size; + if (o == null) { + for (Node x = last; x != null; x = x.prev) { + index--; + if (x.item == null) + return index; + } + } else { + for (Node x = last; x != null; x = x.prev) { + index--; + if (o.equals(x.item)) + return index; + } + } + return -1; + } + + // Queue operations. + + // 取出首节点,拉 + public E peek() { + final Node f = first; + return (f == null) ? null : f.item; + } + + + public E element() { + return getFirst(); + } + + // 删除首元素并返回 + public E poll() { + final Node f = first; + return (f == null) ? null : unlinkFirst(f); + } + + + public E remove() { + return removeFirst(); + } + + + public boolean offer(E e) { + return add(e); + } + + + public boolean offerFirst(E e) { + addFirst(e); + return true; + } + + + public boolean offerLast(E e) { + addLast(e); + return true; + } + + public E peekFirst() { + final Node f = first; + return (f == null) ? null : f.item; + } + + + public E peekLast() { + final Node l = last; + return (l == null) ? null : l.item; + } + + + public E pollFirst() { + final Node f = first; + return (f == null) ? null : unlinkFirst(f); + } + + + public E pollLast() { + final Node l = last; + return (l == null) ? null : unlinkLast(l); + } + + public void push(E e) { + addFirst(e); + } + + public E pop() { + return removeFirst(); + } + + + public boolean removeFirstOccurrence(Object o) { + return remove(o); + } + + + public ListIterator listIterator(int index) { + checkPositionIndex(index); + return new ListItr(index); + } + + private class ListItr implements ListIterator { + private Node lastReturned; + private Node next; + private int nextIndex; + private int expectedModCount = modCount; + + ListItr(int index) { + // assert isPositionIndex(index); + next = (index == size) ? null : node(index); + nextIndex = index; + } + + public boolean hasNext() { + return nextIndex < size; + } + + public E next() { + checkForComodification(); + if (!hasNext()) + throw new NoSuchElementException(); + + lastReturned = next; + next = next.next; + nextIndex++; + return lastReturned.item; + } + + public boolean hasPrevious() { + return nextIndex > 0; + } + + public E previous() { + checkForComodification(); + if (!hasPrevious()) + throw new NoSuchElementException(); + + lastReturned = next = (next == null) ? last : next.prev; + nextIndex--; + return lastReturned.item; + } + + public int nextIndex() { + return nextIndex; + } + + public int previousIndex() { + return nextIndex - 1; + } + + public void remove() { + checkForComodification(); + if (lastReturned == null) + throw new IllegalStateException(); + + Node lastNext = lastReturned.next; + unlink(lastReturned); + if (next == lastReturned) + next = lastNext; + else + nextIndex--; + lastReturned = null; + expectedModCount++; + } + + public void set(E e) { + if (lastReturned == null) + throw new IllegalStateException(); + checkForComodification(); + lastReturned.item = e; + } + + public void add(E e) { + checkForComodification(); + lastReturned = null; + if (next == null) + linkLast(e); + else + linkBefore(e, next); + nextIndex++; + expectedModCount++; + } + + public void forEachRemaining(Consumer action) { + Objects.requireNonNull(action); + while (modCount == expectedModCount && nextIndex < size) { + action.accept(next.item); + lastReturned = next; + next = next.next; + nextIndex++; + } + checkForComodification(); + } + + final void checkForComodification() { + if (modCount != expectedModCount) + throw new ConcurrentModificationException(); + } + } + + + +} -- Gitee