java linklist6_分析轮子(六)- LinkedList.java

注:玩的是JDK1.7版本

一:先上类的继承结构图

933f8648be3290316cef4894ec55226f.png

二:再看一下他的底层实现数据结构

94c26820875f2657faea65770bcd857f.png

三:然后从源码中找点好玩的东西

1)双向链表的结构构成元素,头指针、尾指针、节点信息(前向指针、后向指针、节点信息)

/*** Pointer to first node.

* Invariant: (first == null && last == null) ||

* (first.prev == null && first.item != null)*/

transient Nodefirst;/*** Pointer to last node.

* Invariant: (first == null && last == null) ||

* (last.next == null && last.item != null)*/

transient Node last;

private static class Node{

E item;

Nodenext;

Nodeprev;

Node(Node prev, E element, Nodenext) {this.item =element;this.next =next;this.prev =prev;

}

}

2)在链表尾部添加新节点,只需要改变链表尾指针的指针指向就可了,所以,性能相对 ArrayList.java 的数组拷贝会好很多

/*** Appends the specified element to the end of this list.

*

*

This method is equivalent to {@link#addLast}.

*

*@parame element to be appended to this list

*@return{@codetrue} (as specified by {@linkCollection#add})*/

public booleanadd(E e) {

linkLast(e);return true;

}

/*** Links e as last element.*/

voidlinkLast(E e) {final Node l =last;final Node newNode = new Node<>(l, e, null);

last=newNode;if (l == null)

first=newNode;elsel.next=newNode;

size++;

modCount++;

}

3)根据索引位置,获取节点,会遍历链表性能相对会差一些,并且我们也能看到遍历的时候也有一个优化,通过索引位置和链表长度的一半比较,决定从头遍历还是从尾遍历,这样能通过减少遍历长度加快遍历速度的作用,不过当索引位置在中间的时候,就不好玩了,无论从头或从尾遍历性能不会比较差

/*** Returns the element at the specified position in this list.

*

*@paramindex index of the element to return

*@returnthe element at the specified position in this list

*@throwsIndexOutOfBoundsException {@inheritDoc}*/

public E get(intindex) {

checkElementIndex(index);returnnode(index).item;

}

/*** Returns the (non-null) Node at the specified element index.*/Node node(intindex) {//assert isElementIndex(index);

if (index < (size >> 1)) {

Node x =first;for (int i = 0; i < index; i++)

x=x.next;returnx;

}else{

Node x =last;for (int i = size - 1; i > index; i--)

x=x.prev;returnx;

}

}

4)根据节点信息获取索引位置的方法,可以看到节点信息是允许为null的

/*** Returns the index of the first occurrence of the specified element

* in this list, or -1 if this list does not contain the element.

* More formally, returns the lowest index {@codei} such that

* (o==null ? get(i)==null : o.equals(get(i))),

* or -1 if there is no such index.

*

*@paramo element to search for

*@returnthe index of the first occurrence of the specified element in

* this list, or -1 if this list does not contain the element*/

public intindexOf(Object o) {int index = 0;if (o == null) {for (Node x = first; x != null; x =x.next) {if (x.item == null)returnindex;

index++;

}

}else{for (Node x = first; x != null; x =x.next) {if(o.equals(x.item))returnindex;

index++;

}

}return -1;

}

5)下面的三个方法,是根据索引位置,修改、删除索引位置的节点,都会遍历链表,所以,性能相对会差一些,ArrayListljava 是通过数组的索引位置直接操作的

/*** Replaces the element at the specified position in this list with the

* specified element.

*

*@paramindex index of the element to replace

*@paramelement element to be stored at the specified position

*@returnthe element previously at the specified position

*@throwsIndexOutOfBoundsException {@inheritDoc}*/

public E set(intindex, E element) {

checkElementIndex(index);

Node x =node(index);

E oldVal=x.item;

x.item=element;returnoldVal;

}

/*** Inserts the specified element at the specified position in this list.

* Shifts the element currently at that position (if any) and any

* subsequent elements to the right (adds one to their indices).

*

*@paramindex index at which the specified element is to be inserted

*@paramelement element to be inserted

*@throwsIndexOutOfBoundsException {@inheritDoc}*/

public void add(intindex, E element) {

checkPositionIndex(index);if (index ==size)

linkLast(element);elselinkBefore(element, node(index));

}

/*** Removes the element at the specified position in this list. Shifts any

* subsequent elements to the left (subtracts one from their indices).

* Returns the element that was removed from the list.

*

*@paramindex the index of the element to be removed

*@returnthe element previously at the specified position

*@throwsIndexOutOfBoundsException {@inheritDoc}*/

public E remove(intindex) {

checkElementIndex(index);returnunlink(node(index));

}

6)双向链表也可以当做双向队列使用

6ade853189c7307bf57b52e531ad390e.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值