首先是定义结点类
public class LinkNode {
private String data;
private LinkNode pre;
private LinkNode next;
private int id;
public LinkNode() {
}
public LinkNode(String data, LinkNode pre, LinkNode next, int id) {
// TODO Auto-generated constructor stub
this.data = data;
this.pre = pre;
this.next = next;
this.id = id;
}
public LinkNode(String data, int id) {
// TODO Auto-generated constructor stub
this.data = data;
this.id = id;
}
public LinkNode(String data) {
// TODO Auto-generated constructor stub
this.data = data;
}
public void print() {
//输出该结点的data
System.out.print(this.data);
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public LinkNode getPre() {
return pre;
}
public void setPre(LinkNode pre) {
this.pre = pre;
}
public LinkNode getNext() {
return next;
}
public void setNext(LinkNode next) {
this.next = next;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
接下来定义链表类
//本链表是一个 带有头结点和尾结点的双向链表 其中,头结点和尾节点不存放数据,其data和id为固定内容
public class LinkList {
LinkNode headNode;
LinkNode tailNode;
private int length;
public LinkList() {
length = 0;//链表长度初始化为0
headNode = new LinkNode("Head", null, null, -1);//新建一个头结点
tailNode = new LinkNode("Tail", null, null, -2);//新建一个尾结点,它的pre是headNode
headNode.setNext(tailNode);//headNode的next初始是tailNode
tailNode.setPre(headNode);
}
public void add(String data) {
//为链表新增结点,该方法默认添加至表尾
LinkNode newNode = new LinkNode(data, length);//创建新结点
LinkNode temp = tailNode.getPre();
temp.setNext(newNode);
newNode.setNext(tailNode);
newNode.setPre(temp);
tailNode.setPre(newNode);
setLength(length + 1);//每新增一个结点,链表长度+1
}
public void remove(int id) throws NodeException {
//移除下标为id的结点
LinkNode temp = headNode;//定义一个遍历用的指针
while(temp.getNext() != tailNode && temp.getNext().getId() != id) {
temp = temp.getNext();
}
if(temp.getNext().getId() != id) {
throw new NodeException("结点下标输入有误, 操作失败");
}else {
System.out.println("本次删除操作删除了下标为 "+ id +"的结点, 该结点的data为: " + temp.getNext().getData());
LinkNode tempTail = temp.getNext().getNext();
temp.setNext(tempTail);
tempTail.setPre(temp);
setLength(length - 1);
}
if(temp.getNext() != tailNode) {
updateId(temp.getNext(), id);
}
}
public void remove(String data) throws NodeException {
//移除值为data的结点
LinkNode temp = headNode;//定义一个遍历用的指针
while(temp.getNext() != tailNode && !temp.getNext().getData().equals(data)) {
temp = temp.getNext();
}
if(!temp.getNext().getData().equals(data)) {
throw new NodeException("结点的data输入有误, 操作失败");
}else {
System.out.println("本次删除操作删除了下标为 "+ temp.getNext().getId() +"的结点, 该结点的data为: " + data);
LinkNode tempTail = temp.getNext().getNext();
temp.setNext(tempTail);
tempTail.setPre(temp);
setLength(length - 1);
}
if(temp.getNext() != tailNode) {
updateId(temp.getNext(), temp.getId() + 1);
}
}
private void updateId(LinkNode node, int id) {
// TODO Auto-generated method stub
while(node.getNext() != null) {
node.setId(id);
id++;
node = node.getNext();
}
}
public void printLength() {
//打印本链表的长度
System.out.println("本链表共含有"+length+"个结点.");
}
public void print() {
//打印本链表
LinkNode temp = headNode;
while(temp != null) {
temp.print();
temp = temp.getNext();
if(temp != null) {
System.out.print(" --> ");
}else {
System.out.println();
return;
}
}
}
public int getLength() {
//获取链表长度
return length;
}
private void setLength(int length) {
//更新链表长度
this.length = length;
}
}
在实现链表的remove方法时,需要主动抛出下标异常或者data异常
public class NodeException extends Exception{
public NodeException() {
// TODO Auto-generated constructor stub
super();
}
public NodeException(String msg) {
// TODO Auto-generated constructor stub
System.out.println(msg);
}
}
测试类
public class HomeWork2 {
// 实现一个类似LinkedList存储数据的链表类,尽量加泛型,
// 实现添加,通过下标删除方法,如果下标超出范围,抛出一个自定义异常
public static void main(String[] args) throws NodeException {
//首先需要声明一个LinkList对象ll, 该对象中默认包含一个头结点和一个尾结点
//之后可进行add操作,添加结点到链表中
//之后可使用print功能,输出这条链表
//当需要删除链表中某个结点时, 可输入该结点的下标来实现删除操作
//也可以通过输入该结点的值来删除该结点
//Tip:每次移除结点后都会更新结点的下标,注意进行移除操作后的的新结点下标
//使用printLength功能可以获取当前链表的长度
LinkList ll = new LinkList();
ll.add("a");
ll.add("b");
ll.add("c");
ll.add("d");
ll.add("e");
ll.add("f");
ll.add("g");
ll.add("h");
ll.add("i");
ll.add("j");
ll.add("k");
ll.add("l");//添加结点
ll.print();//打印链表
System.out.println();
ll.remove("a");//删除"a",(通过data进行删除操作的前边界值)
ll.print();
System.out.println();
ll.remove(0);//删除下标为0的结点,(通过下标进行删除操作的前边界值)
ll.print();
System.out.println();
ll.remove("l");//删除"l",(通过data进行删除操作的后边界值)
ll.print();
System.out.println();
ll.remove(ll.getLength() - 1);//删除下标为(链表长度值 - 1)的结点,(通过下标进行删除操作的后边界值)
ll.print();
System.out.println();
ll.remove("f");//删除"f",(通过data进行删除操作的中间值)
ll.print();
System.out.println();
ll.remove(5);//删除下标为5的结点,(通过下标进行删除操作的中间值)
ll.print();
System.out.println();
ll.printLength();
}
}
功能实现效果示例