关于如何查看java里面各个类的源代码,参考这里:http://blog.csdn.net/qq_27857857/article/details/71250401
大家可以自己去看LinkedList的具体代码。
1.介绍
LinkedList是java集合中常用的类,可能大家经常用ArrayList而忽略了LinkedList,其实弄清楚它们之间的区别,在合适的地方分别使用它们 性能会更好。
上面是链表的表示图,在java里就表示成:public class Node{
int data;
Node next;
}
Node类里一个成员放数据,一个成员放指向下一个Node的引用,这样就串起来了。看不明的也不要纠结为什么类里能声明一个它自己类型的变量,记住可以这样就够了。
2.MyLinkedList
下面我们会实现自己的MyLinkedList,我们采用双向链表、并带有头尾节点(头和尾也是Node类型,只是不存放数据)。
private static class Node<AnyType>{
public AnyType data;
public Node<AnyType> prev;
public Node<AnyType> next;
public Node(AnyType data, Node<AnyType> prev, Node<AnyType> next) {
super();
this.data = data;
this.prev = prev;
this.next = next;
}
}
这是Node类,它是一个静态内部类,是声明在MyLinkedList内部的。 可以看出,它有保存数据、前一个节点、后一个节点三个成员。通过它就能表示一个双向链表
public class MyLinkedList<AnyType> {
private static class Node<AnyType>{
public AnyType data;
public Node<AnyType> prev;
public Node<AnyType> next;
public Node(AnyType data, Node<AnyType> prev, Node<AnyType> next) {
super();
this.data = data;
this.prev = prev;
this.next = next;
}
}
private int theSize=0;
private Node<AnyType> head;
private Node<AnyType> tail;
public MyLinkedList(){
head = new Node<AnyType>(null,null,null);
tail = new Node<AnyType>(null,null,null);
head.next = tail;
tail.prev=head;
head.prev=null;
tail.next=null;
}
这个是MyLinkedList类,它表示一整个链表(包含了头尾和许多数据节点),刚才的Node仅仅表示链表中的某一个节点。
这里head和tail节点仅仅做指示,不存数据。链表是空的时候 head和tail也是存在的(这时候只有它们两个节点)。
每插入一个真正的数据节点,就是在head和tail之间插入。比如上图表示 插入了N0,N1两个节点,在用MyLinkedList的size()、printAll()方法时,会得到2 (而并非4)。
这里为了简单,我们把头节点的pre和尾节点的next 置空(当然你也可以让它们首位相连,类似于形成一个环).
public void addLast(AnyType data){
Node<AnyType> node = new Node<>(data, null, null);
Node<AnyType> preNode = tail.prev;
preNode.next = node;
node.prev = preNode;
node.next = tail;
tail.prev = node;
theSize++;
}
这个方法表示在链表尾部插入,也就是插入到tail节点的前边,就像上图的N1节点。这时候如果插入一个N2节点,N2就会处于N1和tail之间。
这个方法内部的代表就是 改变 prev和next的指向而已,大家在纸上画一画、想一想就能明白(大家完全可以不按我这样的顺序改变prev和next,先改变prev还是next都没有关系,只要最终节点之间的指向是正确的), 我这里还用了Node<AnyType> preNode = tail.prev; 来表示tail的前节点,你也完全可以不用这个临时节点(但这时可能就会有tail.prev.next这样的语句)。
addLast 方法明白了,大家可以自己类比着实现addFirst方法,也就是插入到Head节点之后。
public AnyType get(int index){
if(index<0 || index >=theSize)
throw new ArrayIndexOutOfBoundsException();
Node<AnyType> now = head;
for(int i=0;i<index+1;i++)
{
now = now.next;
}
return now.data;
}
get方法需要注意的是,head这个节点并不是你真正插入的节点。所以你应该搜索的节点是head和tail之间的节点,不包括head和tail;
大家可以再去实现get的重载版本,比如传来的参数不是一个下标,而是一个AnyType实例。
这几个方法明白了,就可以去实现set、size、isEmpty等更多的方法。
下面是完整的代码:
package LikedList模拟实现;(没有实现迭代器,大家可以自己尝试)
public class MyLinkedList<AnyType> {
private static class Node<AnyType>{
public AnyType data;
public Node<AnyType> prev;
public Node<AnyType> next;
public Node(AnyType data, Node<AnyType> prev, Node<AnyType> next) {
super();
this.data = data;
this.prev = prev;
this.next = next;
}
}
private int theSize=0;
private Node<AnyType> head;
private Node<AnyType> tail;
public MyLinkedList(){
head = new Node<AnyType>(null,null,null);
tail = new Node<AnyType>(null,null,null);
head.next = tail;
tail.prev=head;
head.prev=null;
tail.next=null;
}
public void add(AnyType data){
// Node<AnyType> newNode = new Node<>(data, null, null);
addLast(data);
}
public void addLast(AnyType data){
Node<AnyType> node = new Node<>(data, null, null);
Node<AnyType> preNode = tail.prev;
preNode.next = node;
node.prev = preNode;
node.next = tail;
tail.prev = node;
theSize++;
}
public void addFirst(AnyType data){
Node<AnyType> node = new Node<>(data, null, null);
Node<AnyType> nextNode = head.next;
nextNode.prev = node;
node.prev=head;
node.next = nextNode;
head.next = node;
theSize++;
}
public int size(){
return theSize;
}
public boolean isEmpty(){
return size()==0;
}
public AnyType get(int index){
if(index<0 || index >=theSize)
throw new ArrayIndexOutOfBoundsException();
Node<AnyType> now = head;
for(int i=0;i<index+1;i++)
{
now = now.next;
}
return now.data;
}
public void printAll(){
System.out.print("[ ");
Node<AnyType> temp = head.next;
while(temp != tail)
{
System.out.print(temp.data==null?"null":temp.data.toString());
if(temp.next!=tail)
System.out.print(",");
temp = temp.next;
}
System.out.print(" ]");
System.out.println("");
}
public void set(int index,AnyType data){
if(index<0 || index >=theSize)
throw new ArrayIndexOutOfBoundsException();
Node<AnyType> now = head;
for(int i=0;i<index+1;i++)
{
now = now.next;
}
now.data = data;
}
}