双向链表的节点结构,双向链表不但可以访问后面的数据,还可以访问前面的数据
1.节点接口定义
public interface Node {
//获取节点数据域
public Object getData();
//设置节点数据域
public void setData(Object obj);
//删除节点时起关键作用
public Node getNext();
}
2.双向链表接口定义
public class DLNode implements Node{
private Object element;
public DLNode pre;
public DLNode next;
public DLNode() {
this(null,null,null);
}
public DLNode(Object element, DLNode pre, DLNode next) {
super();
this.element = element;
this.pre = pre;
this.next = next;
}
public DLNode getPre() {
return pre;
}
public void setPre(DLNode pre) {
this.pre = pre;
}
public void setNext(DLNode next) {
this.next = next;
}
public DLNode getNext() {
return next;
}
@Override
public Object getData() {
return element;
}
@Override
public void setData(Object obj) {
element = obj;
}
}
3.链接表接口
public interface LinkedList {
//返回线性表的大小,即数据元素的个数
public int getSize();
//判断线性表是否为空
public boolean isEmploy();
//返回第一个节点
public Node first() throws OutOfBoundaryException;
//返回最后一个节点
public Node last() throws OutOfBoundaryException;
//返回p之前的节点
public Node getPre(Node p) throws InvalidNodeException,OutOfBoundaryException;
//返回p之后的节点
public Node getNext(Node p) throws InvalidNodeException,OutOfBoundaryException;
//将e作为第一个元素插入链接表,并返回e所在的节点
public Node insertFirst(Object e);
//将e作为最后一个元素插入链接表,并返回e所在的节点
public Node insertLast(Object e);
//将e插入到节点p之前的位置,并且返回e的节点位置
public Node insertBefor(Node p,Object e) throws InvalidNodeException;
//将e插入到节点p之后的位置,并且返回e的节点位置
public Node insertAfter(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 Object get(int i)throws OutOfBoundaryException;
//迭代器
public Iterator element();
}
4.定义异常
/*
* 结点在以下情况下是不合法的
* p=null
* p在链表中不存在
* 在调用方法getPre(p)的时候,p是第一个存数据的节点
* 在调用方法getNext(p)的时候,p是最后一个存数据的节点
*/
public class InvalidNodeException extends RuntimeException{
public InvalidNodeException(String err){
super(err);
}
}
/*
* 越界异常
*/
public class OutOfBoundaryException extends RuntimeException{
public OutOfBoundaryException(String err){
super(err);
}
}
5.基于双向链接表实现的链接表
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);
head.setPre(head);
}
/*
* 辅助方法,判断节点p是否合法
*/
protected DLNode checkPosition(Node p) throws InvalidNodeException {
if (p == null)
throw new InvalidNodeException("老刁,节点是空的GG");
if (p == head)
throw new InvalidNodeException("老刁,节点指向了我的头了GG");
if (p == tail)
throw new InvalidNodeException("小刁,节点指向了我的尾巴了GG");
DLNode node = (DLNode) p;
return node;
}
/*
* 链表的大小
*/
public int getSize() {
return size;
}
/*
* 链表是否为空
*/
public boolean isEmploy() {
return size == 0;
}
/*
* 返回第一个节点
*/
public Node first() throws OutOfBoundaryException {
if (isEmploy())
throw new OutOfBoundaryException("链表为空,怎么访问节点");
return head.getNext();
}
/*
* 返回最后一个节点
*/
public Node last() throws OutOfBoundaryException {
if (isEmploy())
throw new OutOfBoundaryException("链表为空,怎么访问节点");
return tail.getPre();
}
/*
* 返回p之前的节点
*/
public Node getPre(Node p) throws InvalidNodeException, OutOfBoundaryException {
DLNode node = checkPosition(p);
node = node.getPre();
if (node == head)
throw new OutOfBoundaryException("小伙子,欢迎来到头节点,可我没有东西招待你");
return node;
}
/*
* 返回p之后的节点
*/
public Node getNext(Node p) throws InvalidNodeException, OutOfBoundaryException {
DLNode node = checkPosition(p);
node = node.getNext();
if (node == tail)
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作为最后一个元素插入到链表
*/
public Node insertLast(Object e) {
DLNode node = new DLNode(e, tail.getPre(), tail);
tail.getPre().setNext(node);
tail.setPre(node);
size++;
return node;
}
/*
* 将e插入到节点p之前的位置,并且返回e的节点位置
*/
public Node insertBefor(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;
}
/*
* 将e插入到节点p之后的位置,并且返回e的节点位置
*/
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);
node.setNext(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 element() {
return new LinkedListIterator(this);
}
/*
* 遍历双向链表
*/
public void print() {
DLNode temp = (DLNode) head;
while (temp != null) {
System.out.print(temp.getData() + ",");
temp = (DLNode) temp.getNext();
}
System.out.println();
//
}
/*
返回指定位置上的元素
*/
public Object get(int i) {
if(i<0 || i>size)
throw new OutOfBoundaryException("别再让我看见你越界");
return null;
}
}
6.迭代器接口
/*
* 迭代器接口
*/
public interface Iterator {
//移动到第一个元素
public void first();
//移动到下一个元素
public void next();
//检查迭代器中是否还有剩余元素
public boolean isDone();
//返回当前元素
public Object currentItem();
}
如果代码有什么问题请大家在评论区留言,谢谢,再说一句,写代码这东西还是要多练!