JDK中的LinkedList属于双向循环链表.
下面是使用Java来实现一个双向非循环链表.
package org.cgz.practice2;
import java.util.NoSuchElementException;
/**
* 双向非循环链表
* @author cgz
* @param <E>
*/
public class MyLinkedList<E> {
/**
* 定义一个结点类
* @author cgz
* @param <E>
*/
private static class Node<E> {
private Node<E> prev;
private Node<E> next;
private E data;
public Node(E data, Node<E> prev, Node<E> next) {
this.data = data;
this.prev = prev;
this.next = next;
}
}
private Node<E> head;
private Node<E> tail;
private transient int size = 0;
public MyLinkedList() {
head = tail = null;
}
/** ------------------添加------------------ **/
public void add(E e) {
addLast(e);
}
/**
* 在index处插入一个元素
*
* @param index
* @param e
*/
public void add(int index, E e) {
if (index < 0 || index > size) {
throw new IndexOutOfBoundsException("index:" + index + ",size:"+ size);
}
if (head == null) { // 当链表为空时,添加一个新结点
head = new Node<E>(e, null, null);
tail = head;
} else {
if (index == 0) { // 在链表头部插入元素
Node<E> newNode = new Node<E>(e, null, head);
head.prev = newNode;
head = newNode;
} else if (index == size) { // 在链表尾部插入
Node<E> newNode = new Node<E>(e, tail, null);
tail.next = newNode;
tail = newNode;
} else {
Node<E> newNode = new Node<E>(e, null, null);
Node<E> current = getNodeByIndex(index);
current.prev.next = newNode;
newNode.prev = current.prev;
current.prev = newNode;
newNode.next = current;
}
}
size++;
}
/**
* 在链表头添加元素
*
* @param e
*/
public void addFirst(E e) {
add(0, e);
}
/**
* 在链表末尾添加元素
*
* @param e
*/
public void addLast(E e) {
add(size, e);
}
/**
* 根据index获取所在位置的元素
* @param index
* @return
*/
private Node<E> getNodeByIndex(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("index:" + index + ",size:"+ size);
}
if(size==0) {
throw new NoSuchElementException();
}
Node<E> current;
// 如果index在链表前半段,则从表头开始查找
if (index <= size / 2) {
current = head;
for (int i = 1; i <= index; i++) {
current = current.next;
}
} else {
// 如果index在链表后半段,则从尾部查找
current = tail;
for (int i = size-1; i >= index+1; i--) {
current = current.prev;
}
}
return current;
}
/** ------------------删除------------------ **/
public boolean remove(E e) {
int index = indexOf(e);
if(index!=-1) {
remove(index);
return true;
}
return false;
}
/**
* 根据index删除元素
* @param index
* @return
*/
public E remove(int index) {
Node<E> node = getNodeByIndex(index);
E old = null;
//删除链表头
if (index == 0) {
old = head.data;
head.next.prev = null;
head = head.next;
//删除链表尾
} else if (index == size-1) {
old = tail.data;
tail.prev.next = null;
tail = tail.prev;
} else {
old = node.data;
node.prev.next = node.next;
node.next.prev = node.prev;
}
size--;
return old;
}
/**
* 删除首元素
* @return
*/
public E removeFirst() {
return remove(0);
}
/**
* 删除尾元素
* @return
*/
public E removeLast() {
return remove(size-1);
}
/**
* 清空链表
*/
public void clear() {
Node<E> current = head;
while(current!=null) {
Node<E> next = current.next;
current.prev = current.next = null;
current.data = null;
current = next;
}
size = 0;
}
/** ------------------修改------------------ **/
public E set(int index, E e) {
Node<E> oldNode = getNodeByIndex(index);
E oldData = oldNode.data;
oldNode.data = e;
return oldData;
}
/** ------------------查询------------------ **/
/**
* 返回index处的元素
* @param index
* @return
*/
public E get(int index) {
return getNodeByIndex(index).data;
}
/**
* 返回首元素
* @return
*/
public E getFirst() {
return get(0);
}
/**
* 返回最后一个元素
* @return
*/
public E getLast() {
return get(size-1);
}
/**
* 返回元素在链表中的位置
* @param e
* @return
*/
public int indexOf(E e) {
Node<E> current = head;
int count = 0;
while(current!=null) {
if(current.data.equals(e)) {
return count;
}
current = current.next;
count++;
}
return -1;
}
/**
* 是否包含元素e
* @param e
* @return
*/
public boolean contains(E e) {
return indexOf(e)!=-1;
}
/**
* 链表是否为空
* @return
*/
public boolean isEmpty() {
return size == 0;
}
/**
* 链表长度
* @return
*/
public int size() {
return size;
}
/**
* 输出链表中的所有元素
*/
public void print() {
System.out.print(this.getClass().getSimpleName() + ":[");
Node<E> current = head;
while(current!=null) {
System.out.print(current.data + " ");
current = current.next;
}
System.out.print("]");
}
}