一、单向链表
1、链表的结点类
public class Node {
int val; // 表示数据域的值
Node next; // 表示指针域,指向下一个结点
// 构造方法,为数据域赋值
public Node(int val) {
this.val = val;
}
// 链表结点的构造函数:使用数组arr作为参数,创建一个链表,当前的Node为链表的头结点
public Node(int[] arr) {
if(arr == null || arr.length == 0)
throw new IllegalArgumentException("arr can not be empty!");
// 将数组转换为链表结构
this.val = arr[0];
Node cur = this;
for(int i=1; i<arr.length; i++) {
cur.next = new Node(arr[i]);
cur = cur.next;
}
}
// 以当前结点为头结点的链表信息字符串表示
@Override
public String toString() {
StringBuilder result = new StringBuilder();
Node cur = this; // 创建一个当前结点
// 循环遍历,输出链表的每个结点
while(cur != null) {
result.append(cur.val + "->");
cur = cur.next;
}
result.append("NULL"); // 表示链表结束
return result.toString(); // 返回链表的字符串表示
}
}
2、链表的反转
【题目】输入一个链表,按链表值从尾到头的顺序返回一个ArrayList集合。
/**
* 内部类
**/
public class Node {
int val; // 表示数据域的值
Node next = null; // 表示指针域,指向下一个结点
// 构造方法,为数据域赋值
Node(int val) {
this.val = val;
}
}
/**
* 链表的反转
**/
public static Node reverse(Node node) {
// 创建两个空结点
Node prev = null; // 用于存储当前结点的前一个结点
Node temp = null; // 用于存储临时结点
// 循环遍历链表中的每个结点
while(node != null) {
temp = node.next;
node.next = prev;
prev = node;
node = temp;
}
return prev;
}
public ArrayList<Integer> reverse02(Node node) {
ArrayList<Integer> list = new ArrayList<>();
// 准备两个空结点:
Node prev = null; // 用于存储当前结点的前一个结点
Node temp = null; // 用于存储临时结点
while(node != null) {
temp = node.next;
node.next = prev; // 将指针由:向后指,变为向前指
prev = node;
node = temp;
}
// 将链表中的数值存储到集合中
while(prev != null) {
list.add(prev.val);
prev = prev.next;
}
return list;
}
3、删除链表中指定元素
【题目】删除链表中所有等于给定值x的元素。
public static Node removeElements(Node head, int x) {
// 若该链表非空,并且头结点的数值即为指定元素
while(head != null && head.val == x) {
Node delNode = head; // 新建一个delNode结点
head = head.next;
delNode.next = null;
}
// 若链表为空,则返回null
if(head == null)
return null;
// 删除中间为指定值的元素
Node prev = head; // prev表示要删除结点的前一个结点
// 循环遍历链表
while(prev.next != null) {
// 当前结点的数值等于指定数时
if(prev.next.val == x) {
Node delNode = prev.next; // 新建一个delNode结点
prev.next = delNode.next;
delNode.next = null;
} else {
prev = prev.next;
}
}
return head;
}
/**
* 使用虚拟头结点dummyHead,简化操作
*/
public static Node removeElements02(Node head, int x) {
Node dummyHead = new Node(-1); // 新建一个虚拟头结点,任意赋值
dummyHead.next = head;
Node prev = dummyHead; // 新建一个prev结点,表示当前结点的前一个结点
// 循环遍历链表
while(prev.next != null) {
// 若当前结点的数值等于指定数时
if(prev.next.val == x) {
Node delNode = prev.next; // 新建一个delNode结点,用于存储要删除的结点
prev.next = delNode.next;
delNode.next = null;
} else {
prev = prev.next;
}
}
return dummyHead.next;
}
/**
* 使用递归的方法
*/
public static Node removeElements03(Node head, int x) {
// 若链表为空,返回null
if(head == null)
return null;
Node result = removeElements03(head.next, x);
if(head.val == x) {
return result;
} else {
head.next = result;
return head;
}
}