设计背景
动态数组(ArrayList)拥有良好的随机访问能力,虽然从用户的层面讲其为动态的,但其仍然没有摆脱容量的约束,它内部依旧面临着扩容/缩容等繁琐操作。我们希望设计一种存储风格类似于数组,却完全不需要涉及到容量的纯动态线性结构。在这个结构中,每一个元素通过指针引用的形式指向下一个元素,直至NULL值,以串成一条数据链,这种结构就被称之为链表(LinkedList)。
结构分析
【结构类型】线性结构
【底层实现】Node模型(元素+指针)
【核心方法】
public void addFirst(E e); //在链表头添加元素
public E removeFirst(); //移除链表头的元素
public E getFirst(); //获取链表头的元素
代码实现
public class LinkedList<E> {
/**
* 内部类:节点
*/
private class Node {
/**
* 实例域:节点元素、节点引用
*/
public E e;
public Node next;
/**
* 构造器:对实例域进行初始化
* @param e 元素
* @param next 引用指向
*/
public Node(E e, Node next) {
this.e = e;
this.next = next;
}
public Node(E e) {
this(e, null);
}
public Node() {
this(null, null);
}
}
/**
* 实例域:头指针、元素个数
*/
private Node head;
private int size;
/**
* 无参构造器:利用默认值初始化实例域
*/
public LinkedList() {
head = null;
size = 0;
}
/**
* 方法:在链表头部添加元素
* @param e
*/
public void addFirst(E e) {
// 创建一个存储元素e的节点,该节点指向head所指向的节点,再将head引用到该节点
head = new Node(e, head);
// 元素个数加一
size++;
}
/**
* 方法:移除链表头部的元素
* @return 被删除的元素
*/
public E removeFirst() {
// 将头节点存入临时变量
Node delNode = head;
// 将head指针引用到后一位
head = head.next;
// 将临时变量指向NULL,以完成移除操作
delNode.next = null;
// 返回临时变量所存储的值
return delNode.e;
}
/**
* 方法:获取链表头部的元素
* @return 链表头元素
*/
public E getFirst() {
return head.e;
}
/**
* 方法:判断数组是否为空
* @return 若为空则返回true,反之false
*/
public boolean isEmpty() {
return size == 0;
}
/**
* 方法:获取链表元素个数
* @return 链表元素个数
*/
public int getSize() {
return size;
}
/**
* 方法:判断链表是否包含某元素
* @param e 元素
* @return 若包含则返回true,反之false
*/
public boolean contains(E e) {
Node cur = head;
while (cur.next != null) {
if (e.equals(cur.e)) {
return true;
}
cur = cur.next;
}
return false;
}
@Override
public String toString() {
StringBuilder res = new StringBuilder();
Node cur = head;
while (cur != null) {
res.append(cur.e + "->");
cur = cur.next;
}
res.append("NULL");
return res.toString();
}
}