LinkedList类的实现
这里提供双向链表的实现,为避免与Java API冲突,取名为MyLinkedList。
LinkedList类的属性
public class MyLinkedList<AnyType> implements Iterable<AnyType> {
private int theSize = 0;//链表的大小
private int modCount = 0;//链表修改的次数
private Node<AnyType> HeadNode;
private Node<AnyType> LastNode;
}
该类有四个属性,包括theSize,modCount,HeadNode,LastNode。其中modCount是对链表进行修改的次数,记录modCount的原因后面会说明。HeadNode和LastNode分别为头节点和尾节点,他们本身不存储数据,用于标记链表的头部和末尾。下面就其部分方法进行解释及类。
Node类
private static class Node<AnyType> {
public AnyType data; //存储的数据
public Node<AnyType> prevNode; //指向上一个节点
public Node<AnyType> nextNode; //指向下一个节点
public Node(AnyType data, Node<AnyType> prevNode, Node<AnyType> nextNode){
this.data = data;
this.nextNode = nextNode;
this.prevNode = prevNode;
}
}
Node类用于表示节点。其包含3个属性data,prevNode,nextNode以及一个构造器。
doClear方法
private void doClear() {
HeadNode = new Node<AnyType>(null, null, null);
LastNode = new Node<AnyType>(null, HeadNode, null);
HeadNode.nextNode = LastNode;
theSize = 0;
modCount ++;
}
该方法用于初始化链表。初始化的过程如下:
- 将尾节点的前指针指向头节点
- 将头节点的后指针指向尾节点
- 将链表大小置0
该方法用于构造器及清空链表方法clear中
public MyLinkedList() {
doClear();
}
public void clear() {
doClear();
}
getNode方法
private Node<AnyType> getNode(int idx, int lower, int upper) {
Node<AnyType> node;
//如果索引超过了链表的索引,则报错
if (idx < lower || idx > upper)
throw new IndexOutOfBoundsException();
//如果数据在前半段则从头节点开始检索,如果在后半段则从尾向前检索
if (idx < size() / 2) {
node = HeadNode.nextNode;
for (int i = 0; i < idx; i ++) {
node = node.nextNode;
}
} else {
node = LastNode;
for (int i = size(); i > idx; i --) {
node = node.prevNode;
}
}
return node;
}
该方法用于获取指定位置的节点。包含3个形参:idx,lower,upper。其中lower和upper用于表示索引的范围,当索引超出范围时会抛出异常。
获取节点的过程:
- 判断索引位于链表的前半段还是后半段
- 位于前半段则从头节点开始向后遍历,位于后半段则从尾节点开始向前遍历
该方法可以用于获取指定节点数据、获取指定节点、删除指定位置节点等。
LinkedListIterator类
private class LinkedListIterator implements Iterator<AnyType> {
private MyLinkedList.MyLinkedList.Node<AnyType> current = HeadNode.nextNode; //当前节点的下一个节点
private int expectedModCount = modCount;//确保迭代器在使用时原表数据没有变动
private boolean okToRemove = false;
@Override
public boolean hasNext() {
return current != LastNode;
}
@Override
public AnyType next() {
//确保迭代器在使用时原表数据没有变动
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
if (!hasNext())
throw new NoSuchElementException();
AnyType nextItem = current.data;
current = current.nextNode;
okToRemove = true; //确保能够使用Remove
return nextItem;
}
public void remove() {
//确保迭代器在使用时原表数据没有变动
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
if (!okToRemove)
throw new IllegalStateException();
MyLinkedList.this.remove(current.prevNode);
expectedModCount ++;
okToRemove = false;
}
}
该类用于创建LinkedList的迭代器。包含了3个属性:current、expectedModCount、okToRemove。c其中urrent表示当前节点的下一个节点。expectedModCount用于判断在使用迭代器的过程中,链表是否进行过修改。如果进行过修改,则迭代器失效。okToRemove保证迭代器能够使用remove方法,防止出现异常。
hasNext的实现原理是判断current是否为尾节点,如果为尾节点则说明当前节点位于链表的尾部。
全部代码
public class MyLinkedList<AnyType> implements Iterable<AnyType> {
private int theSize = 0;//链表的大小
private int modCount = 0;//链表修改的次数
private Node<AnyType> HeadNode;
private Node<AnyType> LastNode;
public MyLinkedList() {
doClear();
}
/**
* @Author: pocean
* @Description: 节点
* @Date: 15:31 2021/9/25
*/
private static class Node<AnyType> {
public AnyType data; //存储的数据
public Node<AnyType> prevNode; //指向上一个节点
public Node<AnyType> nextNode; //指向下一个节点
public Node(AnyType data, Node<AnyType> prevNode, Node<AnyType> nextNode){
this.data = data;
this.nextNode = nextNode;
this.prevNode = prevNode;
}
}
public void clear() {
doClear();
}
public int size() {
return theSize;
}
public boolean isEmpty() {
return size() == 0;
}
/**
* @Author: pocean
* @Description: 初始化链表
* @Date: 15:37 2021/9/25
*/
private void doClear() {
HeadNode = new Node<AnyType>(null, null, null);
LastNode = new Node<AnyType>(null, HeadNode, null);
HeadNode.nextNode = LastNode;
theSize = 0;
modCount ++;
}
/**
* @Author: pocean
* @Description: 添加数据至链表末尾
* @Date: 15:55 2021/9/25
*/
public void add(AnyType x) {
add(size(), x);
}
/**
* @Author: pocean
* @Description: 添加数据至指定位置
* @Date: 15:56 2021/9/25
*/
public void add(int idx, AnyType data) {
addBefore(getNode(idx,0,size()), data);
}
/**
* @Author: pocean
* @Description: 获取指定位置节点的数据
* @Date: 15:58 2021/9/25
*/
public AnyType getData(int idx) {
return getNode(idx).data;
}
/**
* @Author: pocean
* @Description: 设置指定位置的节点数据
* @Date: 16:00 2021/9/25
*/
public void set(int idx, AnyType newVal) {
Node<AnyType> p = getNode(idx);
p.data = newVal;
}
/**
* @Author: pocean
* @Description: 添加至指定节点的前端
* @Date: 15:40 2021/9/25
*/
private void addBefore(Node<AnyType> p, AnyType x) {
//将数据存入新节点,新节点的前指针指向指定节点的前一个节点,后指针指向指定节点
Node<AnyType> newNode = new Node<AnyType>(x, p.prevNode, p);
//将指定指针的前一个节点指向新节点
p.prevNode.nextNode = newNode;
//将指定指针的前指针指向新节点
p.prevNode = newNode;
//添加完毕
theSize ++;
modCount ++;
}
/**
* @Author: pocean
* @Description: 删除指定节点
* @Date: 15:54 2021/9/25
*/
private void remove(Node<AnyType> p) {
//将该节点的后一个节点的前指针指向该节点的前一个节点
p.nextNode.prevNode = p.prevNode;
//将该节点的前一个节点的后指针指向该节点的后一个节点
p.prevNode.nextNode = p.nextNode;
//移除完毕
theSize --;
modCount ++;
}
/**
* @Author: pocean
* @Description: 获取指定位置的节点
* @Date: 16:06 2021/9/25
*/
private Node<AnyType> getNode(int idx) {
return getNode(idx, 0, size() - 1);
}
/**
* @Author: pocean
* @Description: 获得指定位置的节点
* @Date: 16:07 2021/9/25
*/
private Node<AnyType> getNode(int idx, int lower, int upper) {
Node<AnyType> node;
//如果索引超过了链表的索引,则报错
if (idx < lower || idx > upper)
throw new IndexOutOfBoundsException();
//如果数据在前半段则从头节点开始检索,如果在后半段则从尾向前检索
if (idx < size() / 2) {
node = HeadNode.nextNode;
for (int i = 0; i < idx; i ++) {
node = node.nextNode;
}
} else {
node = LastNode;
for (int i = size(); i > idx; i --) {
node = node.prevNode;
}
}
return node;
}
private class LinkedListIterator implements Iterator<AnyType> {
private MyLinkedList.MyLinkedList.Node<AnyType> current = HeadNode.nextNode; //当前节点的下一个节点
private int expectedModCount = modCount;//确保迭代器在使用时原表数据没有变动
private boolean okToRemove = false;
@Override
public boolean hasNext() {
return current != LastNode;
}
@Override
public AnyType next() {
//确保迭代器在使用时原表数据没有变动
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
if (!hasNext())
throw new NoSuchElementException();
AnyType nextItem = current.data;
current = current.nextNode;
okToRemove = true; //确保能够使用Remove
return nextItem;
}
public void remove() {
//确保迭代器在使用时原表数据没有变动
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
if (!okToRemove)
throw new IllegalStateException();
MyLinkedList.this.remove(current.prevNode);
expectedModCount ++;
okToRemove = false;
}
}
@Override
public Iterator<AnyType> iterator() {
return new LinkedListIterator();
}
}