Java自带的LinkedList的实现的方式,可以说是最高效的。
可以分析一下其他的实现方式:
1.如果我们用只有一个头指针的单链表的方式实现LinkedList,那么在链表的末尾进行的操作效率就不是很高,例如,我们在链表的末尾的增加一个元素的操作,或者删除一个元素的操作,时间负责度都为O(n)。那么如果增加一个尾指针呢,是不是就可以实现效率高的操作了?
public boolean addLast(Object element){
Entry temp=new Entry();
temp.element=element;
temp.next=null;
if(head==null)
head=tail=temp;
else{
tail.next=temp;
tail=temp;
}
return true;
}
此方法的时间复杂度为O(1),常量。
但是,如果我们要删除末尾的一个元素呢?现在仍然需要O(n)的时间。
2.改进:我们使用一个带有头尾指针的双链表来实现
public boolean addLast(Object element){
Entry temp=new Entry(element,null,tail);
if(head==null){
head=tail=temp;
}
else{
tail=tail.next=temp;
}
size++;
modCount++;
return true;
}
可见,这种实现方式也是比较麻烦的
原来的LinkedList的实现就一句话:
public void addLast(Object o){
addBefore(o,header);
}
public Object removeLast(){
if(head==null)//空链表
throw new NoSuchElementException();
Object last=tail.element;
if(head==tail)//仅仅一个元素在List里
head=tail=null;
else{
tail=tail.previous;
tail.next=null;
}
size--;
modCount++;
return Last;
}
总的来说,这种实现方式,在书写代码时,需要head.previous和tail.next为null的情况。
3.使用带头尾指针的双循环链表
这种实现方式,我们需要注意链表为空插入元素或者只有一个元素时删除元素的问题。
private Entry<E> addBefore(E e, Entry<E> entry) {
Entry<E> newEntry = new Entry<E>(e, entry, entry.previous);
newEntry.previous.next = newEntry;
newEntry.next.previous = newEntry;
size++;
modCount++;
return newEntry;
}
public boolean addLast(Object element){
if(head==null){
Entry temp=new Entry(null,element,null);
head=tail=temp.next=temp.previous=temp;
size++;
modCount++;
}else
tail=addBefore=(element,head);
return true;
}
public Object removeLast(){
Object last=tail.element;
remove(tail);
return last;
}
public void remove(Entry e){
if(e==null)
throw new NoSuchElementException();
if(tail==head)
head=tail=null;
else{
e.previous.next=e.next;
e.next.previous=e.previous;
if(e==tail)
tail=tail.previous;
}
size--;
modCount++;
}
从上面的分析可以看出,Java里的LinkedList的实现方式是非常好的。其他的实现要么性能难以达到要求,要么实现相对复杂一些。
可以分析一下其他的实现方式:
1.如果我们用只有一个头指针的单链表的方式实现LinkedList,那么在链表的末尾进行的操作效率就不是很高,例如,我们在链表的末尾的增加一个元素的操作,或者删除一个元素的操作,时间负责度都为O(n)。那么如果增加一个尾指针呢,是不是就可以实现效率高的操作了?
public boolean addLast(Object element){
Entry temp=new Entry();
temp.element=element;
temp.next=null;
if(head==null)
head=tail=temp;
else{
tail.next=temp;
tail=temp;
}
return true;
}
此方法的时间复杂度为O(1),常量。
但是,如果我们要删除末尾的一个元素呢?现在仍然需要O(n)的时间。
2.改进:我们使用一个带有头尾指针的双链表来实现
public boolean addLast(Object element){
Entry temp=new Entry(element,null,tail);
if(head==null){
head=tail=temp;
}
else{
tail=tail.next=temp;
}
size++;
modCount++;
return true;
}
可见,这种实现方式也是比较麻烦的
原来的LinkedList的实现就一句话:
public void addLast(Object o){
addBefore(o,header);
}
public Object removeLast(){
if(head==null)//空链表
throw new NoSuchElementException();
Object last=tail.element;
if(head==tail)//仅仅一个元素在List里
head=tail=null;
else{
tail=tail.previous;
tail.next=null;
}
size--;
modCount++;
return Last;
}
总的来说,这种实现方式,在书写代码时,需要head.previous和tail.next为null的情况。
3.使用带头尾指针的双循环链表
这种实现方式,我们需要注意链表为空插入元素或者只有一个元素时删除元素的问题。
private Entry<E> addBefore(E e, Entry<E> entry) {
Entry<E> newEntry = new Entry<E>(e, entry, entry.previous);
newEntry.previous.next = newEntry;
newEntry.next.previous = newEntry;
size++;
modCount++;
return newEntry;
}
public boolean addLast(Object element){
if(head==null){
Entry temp=new Entry(null,element,null);
head=tail=temp.next=temp.previous=temp;
size++;
modCount++;
}else
tail=addBefore=(element,head);
return true;
}
public Object removeLast(){
Object last=tail.element;
remove(tail);
return last;
}
public void remove(Entry e){
if(e==null)
throw new NoSuchElementException();
if(tail==head)
head=tail=null;
else{
e.previous.next=e.next;
e.next.previous=e.previous;
if(e==tail)
tail=tail.previous;
}
size--;
modCount++;
}
从上面的分析可以看出,Java里的LinkedList的实现方式是非常好的。其他的实现要么性能难以达到要求,要么实现相对复杂一些。