本文的代码来自于《数据结构与算法(JAVA语言版)》,是笔者在网上找到的资料,非正式出刊版物。笔者对代码一些比较难以理解的部分添加了注释和图解,欢迎大家来讨论。
双链表实现结构图
public class LinkedListDLNode implements LinkedList {
private int size; //规模
private DLNode head;//头结点,哑元结点
private DLNode tail;//尾结点,哑元结点
public LinkedListDLNode() {
size = 0;
head = new DLNode();//构建只有头尾结点的链表
tail = new DLNode();
head.setNext(tail);
tail.setPre(head);
}
//辅助方法,判断结点p是否合法,如合法转换为DLNode
private DLNode checkPosition(Node p) throws InvalidNodeException {
if (p==null)
throw new InvalidNodeException("错误:p为空。");
if (p==head)
throw new InvalidNodeException("错误:p指向头节点,非法。");
if (p==tail)
throw new InvalidNodeException("错误:p指向尾结点,非法。");
DLNode node = (DLNode)p;
return node;
}
//查询链接表当前的规模
public int getSize() {
return size;
}
//判断链接表是否为空
public boolean isEmpty() {
return size==0;
}
//返回第一个结点
public Node first() throws OutOfBoundaryException{
if (isEmpty())
throw new OutOfBoundaryException("错误:链接表为空。");
return head.getNext();
}
//返回最后一结点
public Node last() throws OutOfBoundaryException{
if (isEmpty())
throw new OutOfBoundaryException("错误:链接表为空。");
return tail.getPre();
}
//返回p之后的结点
public Node getNext(Node p) throws InvalidNodeException, OutOfBoundaryException {
DLNode node = checkPosition(p);
node = node.getNext();
if (node==tail)
throw new OutOfBoundaryException("错误:已经是链接表尾端。");
return node;
}
//返回p之前的结点
public Node getPre(Node p) throws InvalidNodeException, OutOfBoundaryException {
DLNode node = checkPosition(p);
node = node.getPre();
if (node==head)
throw new OutOfBoundaryException("错误:已经是链接表前端。");
return node;
}
//将e作为第一个元素插入链接表
public Node insertFirst(Object e) {
DLNode node = new DLNode(e,head,head.getNext());
head.getNext().setPre(node);
head.setNext(node);
size++;
return node;
}
//将e作为最后一个元素插入列表,并返回e所在结点
public Node insertLast(Object e) {
DLNode node = new DLNode(e,tail.getPre(),tail);
tail.getPre().setNext(node);
tail.setPre(node);
size++;
return node;
}
public Node insertAfter(Node p, Object e) throws InvalidNodeException {
DLNode node = checkPosition(p);
DLNode newNode = new DLNode(e,node,node.getNext());
node.getNext().setPre(newNode);//将q节点的前驱设置成e节点
node.setNext(newNode);//将p节点的后驱设置成e节点
size++;
return newNode;
}//将e插入至p之后的位置,并返回e所在结点
//将e插入至p之前的位置,并返回e所在结点
public Node insertBefore(Node p, Object e) throws InvalidNodeException {
DLNode node = checkPosition(p);
DLNode newNode = new DLNode(e,node.getPre(),node);
node.getPre().setNext(newNode);
node.setPre(newNode);
size++;
return newNode;
}
public Object remove(Node p) throws InvalidNodeException {
DLNode node = checkPosition(p);
Object obj = node.getData();
node.getPre().setNext(node.getNext());
node.getNext().setPre(node.getPre());
size--;
return obj;
}//删除给定位置处的元素,并返回之
//删除首元素,并返回之
public Object removeFirst() throws OutOfBoundaryException{
return remove(head.getNext());
}
//删除末元素,并返回之
public Object removeLast() throws OutOfBoundaryException{
return remove(tail.getPre());
}
//将处于给定位置的元素替换为新元素,并返回被替换的元素
public Object replace(Node p, Object e) throws InvalidNodeException {
DLNode node = checkPosition(p);
Object obj = node.getData();
node.setData(e);
return obj;
}
//元素迭代器
public Iterator elements() {
return new LinkedListIterator(this);
}
}
----------
public interface LinkedList {
//查询链接表当前的规模
public int getSize();
//判断链接表是否为空
public boolean isEmpty();
//返回第一个结点
public Node first() throws OutOfBoundaryException;
//返回最后一结点
public Node last() throws OutOfBoundaryException;
//返回p之后的结点
public Node getNext(Node p) throws InvalidNodeException, OutOfBoundaryException;
//返回p之前的结点
public Node getPre(Node p) throws InvalidNodeException, OutOfBoundaryException;
//将e作为第一个元素插入链接表,并返回e所在结点
public Node insertFirst(Object e);
//将e作为最后一个元素插入列表,并返回e所在结点
public Node insertLast(Object e);
//将e插入至p之后的位置,并返回e所在结点
public Node insertAfter(Node p, Object e) throws InvalidNodeException;
//将e插入至p之前的位置,并返回e所在结点
public Node insertBefore(Node p, Object e) throws InvalidNodeException;
//删除给定位置处的元素,并返回之
public Object remove(Node p) throws InvalidNodeException;
//删除首元素,并返回之
public Object removeFirst() throws OutOfBoundaryException;
//删除末元素,并返回之
public Object removeLast() throws OutOfBoundaryException;
//将处于给定位置的元素替换为新元素,并返回被替换的元素
public Object replace(Node p, Object e) throws InvalidNodeException;
//元素迭代器
public Iterator elements();
}
public interface Node {
//获取结点数据域
public Object getData();
//设置结点数据域
public void setData(Object obj);
}
public class DLNode implements Node {
private Object element;
private DLNode pre;
private DLNode next;
public DLNode() {
this(null,null,null);
}
public DLNode(Object ele, DLNode pre, DLNode next){
this.element = ele;
this.pre = pre;
this.next = next;
}
public DLNode getNext(){
return next;
}
public void setNext(DLNode next){
this.next = next;
}
public DLNode getPre(){
return pre;
}
public void setPre(DLNode pre){
this.pre = pre;
}
/****************Node Interface Method**************/
public Object getData() {
return element;
}
public void setData(Object obj) {
element = obj;
}
}
public interface Iterator {
//移动到第一个元素
public void first();
//移动到下一个元素
public void next();
//检查迭代器中是否还有剩余的元素
public boolean isDone();
//返回当前元素
public Object currentItem();
}
public class LinkedListIterator implements Iterator {
private LinkedList list;//链接表
private Node current;//当前结点
//构造方法
public LinkedListIterator(LinkedList list) {
this.list = list;
if (list.isEmpty()) //若列表为空
current = null; //则当前元素置空
else
current = list.first();//否则从第一个元素开始
}
//移动到第一个元素
public void first(){
if (list.isEmpty()) //若列表为空
current = null; //则当前元素置空
else
current = list.first();//否则从第一个元素开始
}
//移动到下一个元素
public void next() throws OutOfBoundaryException{
if (isDone())
throw new OutOfBoundaryException("错误:已经没有元素。");
if (current==list.last()) current = null;
else current = list.getNext(current);
}
//检查迭代器中是否还有剩余的元素
public boolean isDone() { return current==null; }
//返回当前元素
public Object currentItem() throws OutOfBoundaryException{
if (isDone())
throw new OutOfBoundaryException("错误:已经没有元素。");
return current.getData();
}
}
public class InvalidNodeException extends RuntimeException {
public InvalidNodeException(String err) {
super(err);
}
}
public class OutOfBoundaryException extends RuntimeException{
public OutOfBoundaryException(String err){
super(err);
}
}