java集合-LinkedList算法详解。
众所周知LinkedList是用链表算法实现,其优点是:
1、插入速度快
2、删除速度快
缺点:
1、检索速度慢
熟悉链表算法就知道是什么原因,接下来详细讲解一下链表算法,首先给大家看一下我简单实现的链表node:
/** * * @author sheyong * * @param <T> */ class LinkNode<T> { public LinkNode(LinkNode<T> next, LinkNode<T> previous, T obj) { this.next = next; this.previous = previous; this.obj = obj; } private LinkNode<T> next;//下一个节点 private LinkNode<T> previous;//上一个节点 private T obj; /** * 删除节点 */ public void remove() { next.previous = previous; previous.next = next; } /** * 修改节点 */ public void set(T t) { obj=t;
} public String toString() { return obj.toString(); } }
从这段代码可以看出:
1、当前对象保存着上一个和下一个对象的引用
private LinkNode<T> next;//下一个节点 private LinkNode<T> previous;//上一个节点
2、remove一个对象(这里有点不好理解,你可以把链表想成一个锁链,形象思维。):
2.1、当前对象的previous对象的next对先指向的当前对象next。
2.2、当前对象的next对象previous指向当前对先previous。
next.previous = previous;//前与后相连 previous.next = next;//后与前相连
这样就实际上把要删除的对象挤出链接里了。
3、set一个对象(理解删除这里就比较好理解):
1、创建一个新对象,这个对象的next和previous与当前对象相同。
2、把this.next.previous指向新创建的对象。
3、把this.previous.next指向新创建的对象。
public void set(T t) { LinkNode<T> link = new LinkNode<T>(next, previous, t);//新对象 next.previous = link;//改变next previous.next = link;//改变previous }
这样这个对象就被替换掉了。
接下来给大家介绍一下整个链(LinkList):
/** * * @author sheyong * */ class LinkList { LinkNode<T> head = new LinkNode<T>(null, null, null);// 头节点 public LinkList() { head.next = head; head.previous = head; // 首尾相连 } /** * 返回头节点 * @Author : sheyong */ public LinkNode<T> getFirst() { return head; } /** * 返回最后一个节点 * @Author : sheyong */ public LinkNode<T> getLast() { LinkNode<T> node = head.previous;// 返回最后一个节点 if (node == head) { return null; } return node; } /** * 将节点添加到头节点后 * @Author : sheyong */ public LinkNode<T> addFirst(T element) { return addAfter(element, head); } public LinkNode<T> addAfter(T e, LinkNode<T> node) { LinkNode<T> newNode = new LinkNode<T>(node.next, node, e); newNode.previous.next = newNode; newNode.next.previous = newNode; size++; return newNode; } /** * 将节点添加到头节点后 * @Author : sheyong */ public LinkNode<T> addLast(T e) { return addAfter(e, head.previous); } /* * @see java.lang.Object#toString() */ public String toString() { String tempStr = "[" + head.next; LinkNode<T> temp = head.next; while ((temp = temp.next) != head) { tempStr += " " + temp; } return tempStr + "]"; } }
大家仔细看看toString方法运行过程,你就能体会到链表的妙笔之处:
1、链表的一个标志是head也就是他的头节点。
2、此链表是一个链环,尾部的next指向头部(也就是当this.next==head的时候此node就是尾部)
3、通过n次temp = temp.next可以找到链表的尾部。
介绍到这里,大家可以把链表联想到集合中来(java中LinkedList就是通过此算法实现):
大家可以把add操作想成往链表插入元素,把set操作想成修改元素,把index操作想成取到元素......现在的问题就是控制index(在这里给出本人实现的MyLinkedList):
public class MyLinkedList<T> extends AbstractSequentialList<T> implements Collection<T> { private LinkList list = new LinkList(); private int size; public int size() { return size; } public boolean isEmpty() { return list.head.next == list.head; } public boolean add(T e) { list.addAfter(e, list.getFirst().previous); return true; } public String toString() { return list.toString(); } /** * * @author sheyong * */ class LinkList { LinkNode<T> head = new LinkNode<T>(null, null, null);// 头节点 public LinkList() { head.next = head; head.previous = head; // 首尾相连 } /** * 返回头节点 * @Author : sheyong */ public LinkNode<T> getFirst() { return head; } /** * 返回最后一个节点 * @Author : sheyong */ public LinkNode<T> getLast() { LinkNode<T> node = head.previous;// 返回最后一个节点 if (node == head) { return null; } return node; } /** * 将节点添加到头节点后 * @Author : sheyong */ public LinkNode<T> addFirst(T element) { return addAfter(element, head); } public LinkNode<T> addAfter(T e, LinkNode<T> node) { LinkNode<T> newNode = new LinkNode<T>(node.next, node, e); newNode.previous.next = newNode; newNode.next.previous = newNode; size++; return newNode; } /** * 将节点添加到头节点后 * @Author : sheyong */ public LinkNode<T> addLast(T e) { return addAfter(e, head.previous); } /* * @see java.lang.Object#toString() */ public String toString() { String tempStr = "[" + head.next; LinkNode<T> temp = head.next; while ((temp = temp.next) != head) { tempStr += " " + temp; } return tempStr + "]"; } } /** * * @author sheyong * * @param <T> */ class LinkNode<T> { public LinkNode(LinkNode<T> next, LinkNode<T> previous, T obj) { this.next = next; this.previous = previous; this.obj = obj; } private LinkNode<T> next;//下一个节点 private LinkNode<T> previous;//上一个节点 private T obj; /** * 删除节点 */ public void remove() { next.previous = previous;//前与后相连 previous.next = next;//后与前相连 } /** * 修改节点 */ public void set(T t) { LinkNode<T> link = new LinkNode<T>(next, previous, t);//新对象 next.previous = link;//改变next previous.next = link;//改变previous } public String toString() { return obj.toString(); } } /** * * @author sheyong * * @param <T> */ public ListIterator<T> listIterator(int index) { return this.new MyLinkedListIterator(index); } private class MyLinkedListIterator implements ListIterator<T> { private LinkNode<T> current = (LinkNode<T>) list.getFirst();// 当前对象 private int nextIndex;// 下一个索引 public MyLinkedListIterator(int index) { if (index < 0 || index > size) throw new IndexOutOfBoundsException("index:" + index + " ?"); if (index > size >> 1) { for (nextIndex = size; nextIndex > index; nextIndex--) { current = current.previous; } } else { for (nextIndex = 0; nextIndex < index; nextIndex++) { current = current.next; } } } public boolean hasNext() { return nextIndex != size; } public T next() { if (nextIndex == size) throw new IndexOutOfBoundsException("越界"); current = current.next; nextIndex++; return current.obj; } public boolean hasPrevious() { return nextIndex != 0; } public T previous() { if (nextIndex == 0) throw new IndexOutOfBoundsException("越界"); current = current.next; nextIndex--; return current.obj; } public int nextIndex() { return nextIndex; } public int previousIndex() { return nextIndex - 1; } public void remove() { current.remove(); size--; nextIndex--; } public void set(T e) { current.set(e); } public void add(T e) { MyLinkedList.this.list.addLast(e); size++; } } }
此类事面向AbstractSequentialList编写的(java api为了提高效率有些方法并没有面向他),此类提供了一个
/** * Returns a list iterator over the elements in this list (in proper * sequence). * * @param index index of first element to be returned from the list * iterator (by a call to the <code>next</code> method) * @return a list iterator over the elements in this list (in proper * sequence) * @throws IndexOutOfBoundsException {@inheritDoc} */ public abstract ListIterator<E> listIterator(int index)
可以看出他是个抽象方法,给子类实现,此类还有(add,index,remove...)都是面向此方法实现,充分的利用了面向对象的特性。子类甚至只用实现此抽象方法就能java集合的基本操作。
下一篇:ArrayList源码详解