手写部分链表的代码
package com.ds.d230626;
import java.util.Arrays;
/**
* 链表
* @param <E>
*/
public class Test<E> implements Cloneable {
/**
* 链表长度
*/
transient int size = 0;
/**
* 头节点
*/
Node<E> first;
/**
* 尾节点
*/
Node<E> last;
private static class Node<E> {
E element;
Node<E> prev;
Node<E> next;
public Node(Node<E> prev, E element, Node<E> next) {
this.prev = prev;
this.element = element;
this.next = next;
}
}
/**
* 头插
* @param e 节点值
*/
void linkFirst(E e) {
// 获取头结点数据
Node<E> f = first;
// 获取新的节点数据,新节点的 next 指向头节点
Node<E> node = new Node<>(null, e, first);
first = node;
if (f == null) {
// 头结点是 null 值,新节点也就是尾节点
last = node;
} else {
// 头结点不是 null 值,将头结点的 prev 指向新节点的
f.prev = node;
}
size++;
}
/**
* 尾插
* @param e 节点值
*/
void linkLast(E e) {
Node<E> l = last;
Node<E> node = new Node<>(last, e, null);
last = node;
if (l == null) {
first = node;
} else {
l.next = node;
}
size++;
}
/**
* 在某个节点前插入
* @param e 要插入的值
* @param node 节点
*/
void linkBefore(E e, Node<E> node) {
// node 节点的上一个节点
Node<E> prevNode = node.prev;
// 要插入的节点,因为是要出插入在 node 节点前,所以它的 prev 就是 node 节点的 prev, 它的 next 就是 node 节点
Node<E> eNode = new Node<>(prevNode, e, node);
if (prevNode == null) {
// node 节点的 prev 指向为 null 时, eNode 节点就是头节点
first = eNode;
} else {
// node 节点的 prev 指向不为 null 时,prevNode 的 next 指向 eNode 节点
prevNode.next = eNode;
}
size++;
}
/**
* 按顺序添加元素
* @param e 元素值
*/
public void add(E e) {
linkLast(e);
}
/**
* 在索引index处添加元素值
* @param index 索引值
* @param e 元素值
*/
public void add(int index, E e) {
checkPositionIndex(index);
if (index == size) {
linkLast(e);
} else {
linkBefore(e, getNodeByIndex(index));
}
}
/**
* 删链操作
* @param node
*/
void unLink(Node<E> node) {
// 节点前指向节点
Node<E> prevNode = node.prev;
// 节点后指向节点
Node<E> nextNode = node.next;
if (prevNode == null) {
// prevNode 为空,由于要删除 node 节点,所以 nextNode 节点就可以作为 first 节点
first = nextNode;
} else {
// prevNode 为空,由于要删除 node 节点,所以 prevNode.next 就要指向 nextNode
prevNode.next = nextNode;
// 删除 node.prev 节点的关系
node.prev = null;
}
if (nextNode == null) {
// nextNode 为空,由于要删除 node 节点,所以 prevNode 节点就可以作为 last 节点
last = prevNode;
} else {
// nextNode 为空,由于要删除 node 节点,所以 nextNode.prev 节点就要指向 prevNode
nextNode.prev = prevNode;
// 删除 node.next 节点的关系
node.next = null;
}
size--;
}
/**
* 删除元素
* @param o 元素值
*/
boolean remove(Object o) {
if (o == null) {
// 传入对象为 null 值情况
for (Node<E> node = first; node != null; node = node.next) {
// 遍历,查询 null 的节点值
if (node.element == null) {
// 拆链操作
unLink(node);
return true;
}
}
} else {
for (Node<E> node = first; node != null; node = node.next) {
// 遍历,对比节点值是否一致
if (node.element.equals(o)) {
// 拆链操作
unLink(node);
return true;
}
}
}
return false;
}
/**
* 根据索引获取当前节点
* @param index 索引值
* @return Node
*/
Node<E> getNodeByIndex(int index) {
// >> 右移操作,size >> 1 相当于 size 除以 2 取整
if (index < (size >> 1)) {
// 由于 index 在链表的前半部分,所以循环从 first 头节点开始
Node<E> node = first;
for (int i = 0; i < index; i++) {
// node 下一个节点
node = node.next;
}
return node;
} else {
// 由于 index 在链表的前半部分,所以循环从 last 尾节点开始
Node<E> node = last;
for (int i = (size - 1); i > index; i--) {
// node 上一个节点
node = node.prev;
}
return node;
}
}
/**
* 根据索引获取当前节点的值
* @param index 索引值
* @return E
*/
public E get(int index) {
checkElementIndexOut(index);
return getNodeByIndex(index).element;
}
/**
* 替换索引处的值
* @param index 索引值
* @param e 要替换的值
*/
public void set(int index, E e) {
checkElementIndexOut(index);
// 获取索引处的节点
Node<E> indexNode = getNodeByIndex(index);
indexNode.element = e;
}
/**
* 获取元素出现的第一个位置的索引值
* @param o 元素值
* @return int
*/
public int indexOf(Object o) {
int index = 0;
if (o == null) {
// 因为是要找最初出现的位置,所以从 first 头节点开始遍历;每一次循环结束 node 为下一个节点 node.next
for (Node<E> node = first; node != null; node = node.next) {
if (node.element == null) {
// 找到直接返回
return index;
}
// 未找到,索引值自增
index++;
}
} else {
// 因为是要找最初出现的位置,所以从 first 头节点开始遍历;每一次循环结束 node 为下一个节点 node.next
for (Node<E> node = first; node != null; node = node.next) {
if (node.element.equals(o)) {
// 找到直接返回
return index;
}
// 未找到,索引值自增
index++;
}
}
// 表是不存在这个值
return -1;
}
/**
* 获取元素出现的最后一个位置的索引值
* @param o 元素值
* @return int
*/
public int lastIndexOf(Object o) {
int index = size - 1;
if (o == null) {
// 因为是要找最初出现的位置,所以从 last 尾节点开始遍历;每一次循环结束 node 为下一个节点 node.next
for (Node<E> node = last; node != null; node = node.prev) {
if (node.element == null) {
// 找到直接返回
return index;
}
// 未找到,索引值自减
index--;
}
} else {
// 因为是要找最初出现的位置,所以从 last 尾节点开始遍历;每一次循环结束 node 为下一个节点 node.next
for (Node<E> node = last; node != null; node = node.prev) {
if (node.element.equals(o)) {
// 找到直接返回
return index;
}
// 未找到,索引值自减
index--;
}
}
// 表是不存在这个值
return -1;
}
/**
* 校验索引是否越界
* @param index 索引值
*/
private void checkElementIndexOut(int index) {
if (!isElementIndex(index)) {
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
}
/**
* 校验索引是否越界
* @param index 索引值
*/
private boolean isElementIndex(int index) {
return index >= 0 && index < size;
}
/**
* 校验索引值是否在范围内
* @param index 索引值
*/
private void checkPositionIndex(int index) {
if (!isPositionIndex(index)) {
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
}
/**
* 校验索引是否越界
* @param index 索引值
*/
private boolean isPositionIndex(int index) {
return index >= 0 && index <= size;
}
/**
* 异常提示信息
* @param index 索引值
*/
private String outOfBoundsMsg(int index) {
return "Size:" + size + "; Index:" + index;
}
/**
* 链表转换成数组
* @return Object[]
*/
public Object[] toArray() {
Object[] result = new Object[size];
int index = 0;
for (Node<E> node = first; node != null; node = node.next) {
result[index] = node.element;
index++;
}
return result;
}
/**
* 链表转换成对应数据类型的数组
* @return T[]
* @param <T> 泛型
*/
public <T> T[] toArrayT(T[] arr) {
if (arr.length < size) {
// 复制一个 size 大小的数组
arr = Arrays.copyOf(arr, size);
}
int index = 0;
for (Node<E> node = first; node != null; node = node.next) {
// 把链表中的数据存储到数组中
arr[index++] = (T) node.element;
}
return arr;
}
/**
* 深拷贝一个链表
* @return Test
*/
public Test<E> clone() {
// 获取一个浅拷贝对象
Test<E> clone = superClone();
// 进行深拷贝
clone.first = null;
clone.last = null;
clone.size = 0;
for (Node<E> node = first; node != null ; node = node.next) {
// 进行拷贝
clone.add(node.element);
}
return clone;
}
/**
* 获取一个浅拷贝对象
* @return Test
*/
private Test<E> superClone() {
try {
return (Test<E>) super.clone();
} catch (CloneNotSupportedException e) {
throw new InternalError(e);
}
}
public static void main(String[] args) {
Test<Integer> t = new Test<>();
t.linkFirst(3);
t.linkFirst(5);
t.linkFirst(6);
t.linkFirst(1);
t.linkFirst(11);
t.linkLast(11);
System.out.println(Arrays.toString(t.toArray()));
Test<Integer> clone = t.clone();
System.out.println(Arrays.toString(clone.toArray()));
System.out.println(t == clone);
}
}