数据结构之LinkedList的简单实现

关于如何查看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;
}
}























评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值