您的位置:首页 > 编程语言 > Java开发

循环双链表之Java实现(模拟JDK中LinkedList)

2013-05-02 17:04 756 查看
单链表只有一个指针,仅仅指向当前结点的直接后继,为了弥补这个缺陷,故而引入双链表。

所谓双链表,就是每个Element都包含它本身存储的数据和两个指针,分别指向上一个和下一个Element,其结构如下:



我们可以很容易的写出表示链表结点的Java Code:

private T value=null;//use storage data
private Node<T> previous=null;//a reference which means the previous object of current node
private Node<T> next=null;//a reference which means the next object of current node
/**
* the constructor of Node
* @param value
* @param previous
* @param next
*/
public Node(T value, Node<T> previous, Node<T> next) {
this.value = value;
this.previous = previous;
this.next = next;
}


而循环双链表的所有操作,几乎都是围绕头结点操作的。下面是add方法:

private void addBefore(Node<T> currentNode,T value){
/*
* constructor a object of Node<T>,the value of this object is the param of object
* the previous of this value is headNode.previous(value=[null],previous=headNode,next=headNode)
* the next of this object is  headNode(value=[null],previous=headNode,next=headNode)
*/
Node<T> newNode=new Node<T>(value, currentNode.previous, currentNode);
newNode.previous.next=newNode;
newNode.next.previous=newNode;
size++;
}


remove方法如下:

public T remove(int index){
rangeCheck(index);
Node<T> node=getNode(index);
T result = node.value;
node.previous.next = node.next;
node.next.previous = node.previous;
size--;
return result;

}


完整的示例如下:

package com.lemon.linkedlist;

/**
* This class realize the linkedlist of data structures
* The object of MyLinkedList is good at the operation such as add or remove,
* and the disadvantage is random access.
* @author yanan
* @param <T>
*/
public class MyLinkedList<T> {
/**
* the number of this list
*/
private int size;

/**
* construction method
*/
public MyLinkedList (){
headNode.next = headNode.previous = headNode;
}
/**
* the header of this list
*/
private Node<T> headNode=new Node<T>(null, null, null);

/**
* return a number of objects in this list
* @return
*/
public int size(){
return size;
}
/**
* test this list whether is null or not
* @return
*/
public boolean isEmpty(){
return size==0;
}

/**
* add an object to list
* @param object
* @return
*/
public boolean add(T object){
addBefore(headNode,object);
return true;
}
/**
* get an object at specified position in this list
* @param index
* @return
*/
public T get(int index){
rangeCheck(index);
return this.getNode(index).value;
}

private void rangeCheck(int index){
if (index < 0 || index >= size)
throw new IndexOutOfBoundsException("Index: "+index+
", Size: "+size);
}

/**
* return an array which contains all object,which belong to the list,from head to the last.
* @return
*/
public Object[] toArray(){
Object[] result=new Object[size()];
for(int i=0;i<result.length;i++){
result[i]=headNode.next.value;
headNode=headNode.next;
}
return result;

}

private Node<T> getNode(int index){

Node<T> e = headNode;
for(int i=0;i<size();i++){
if(i==index){
return e.next;
}else{
e=e.next;
}
}
return e;
}
/**
* remove an object at specified position which on behalf of index in this list
* return an object that has been removed from this list.
* @param index
* @return
*/
public T remove(int index){ rangeCheck(index); Node<T> node=getNode(index); T result = node.value; node.previous.next = node.next; node.next.previous = node.previous; size--; return result; }

private void addBefore(Node<T> currentNode,T value){
/*
* constructor a object of Node<T>,the value of this object is the param of object
* the previous of this value is headNode.previous(value=[null],previous=headNode,next=headNode)
* the next of this object is headNode(value=[null],previous=headNode,next=headNode)
*/
Node<T> newNode=new Node<T>(value, currentNode.previous, currentNode);
newNode.previous.next=newNode;
newNode.next.previous=newNode;
size++;
}

/**
* a static class,which object that on behalf of an object of the MyLinkedList class
* @author yanan
* @param <T>
*/
private static class Node<T> {
private T value=null;//use storage data
private Node<T> previous=null;//a reference which means the previous object of current node
private Node<T> next=null;//a reference which means the next object of current node
/**
* the constructor of Node
* @param value
* @param previous
* @param next
*/
public Node(T value, Node<T> previous, Node<T> next) {
this.value = value;
this.previous = previous;
this.next = next;
}
}
}


测试如下:

package com.lemon.linkedlist;

public class TestMyLinkedList {

/**
* @param args
*/
public static void main(String[] args) {
MyLinkedList<String> list=new MyLinkedList<String>();
/**
* test add and get
*/
list.add("ChangNinNa");
list.add("ChangNinMeng");
list.add("ChangNinFang");
System.out.println("after add....");
for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
}

/**
* test remove
*/
list.remove(0);
System.out.println("after remove....");
for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
}

/**
* test toArray
*/
Object[] objs=list.toArray();
for(int i=0;i<objs.length;i++){
System.out.println(objs[i]);
}
}

}


当明白了双向链表的原理后,可以很容易理解:为什么Java中LinkedList长于删除、添加;而短于遍历。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐