package class03;
import java.util.ArrayList;
/**
* 把给定的值都删除
* 入参:单链表的头节点head,要删除的数字num。
* 返回值:把值是num的所有节点都删除后的单链表的头节点。
* attention:删除的可能是头节点。删除的可能是连续的节点。
*/
public class Code02_RemoveNodes {
static class Node {
private int value;
private Node next;
public Node(int v) {
value = v;
}
}
//把给定的值都删除
public static Node removeNodes(Node head, int num) {
while (head != null) {
if (head.value != num) {
break;
}
head = head.next;
//如果head.value == num,head就往下出溜。
//如果从第一个节点开始,head.value一直等于num,那head就一直往下出溜。知道第一个不是num的节点出现。break;
}
//来到这儿
//1) head == null
//2) head != null
//❤:) ^_^😀
Node cur = head;//定义cur作为当前节点。
Node pre = head;//定义pre作为当前节点cur的前一个节点。
while (cur != null) {
if (cur.value == num) {//当前节点的值等于num。
pre.next = cur.next;//很关键。在cur每次要跳步之前,总是将pre的next,指向cur的next。
} else {//如果当前节点的值,不等于num。
pre = cur;//pre跳到cur的位置。可能是一下跳一步,也可能是一下跳很多步。
}
cur = cur.next;//不管当前节点的值,等不等于num,当前节点cur,都要跳一步。
}
//返回头节点。head可能是原来的旧头,也可能是跳过了很多个节点后的新头。
return head;
}
public static void main(String[] args) {
int maxSize = 6;
int maxValue = 20;
int testTimes = 10000;
boolean flag = true;
System.out.println("测试开始!");
for (int i = 0; i < testTimes; i++) {
Node node = generateRandomLinkedList(maxSize, maxValue);
// Node node2 = copyLinkedList(node);
Node node2 = copyRandomList(node);//have a look
printLinkedList(node);
int num = (int) (Math.random() * maxValue);//生成随机要删除的数字num
// System.out.println("num = " + num);
Node resultHeadNode = removeNodes(node, num);
String s1 = printLinkedList(resultHeadNode);
Node testHeadNode = test(node2, num);
String s2 = printLinkedList(testHeadNode);
boolean linkedListEquals = isLinkedListEquals(resultHeadNode, testHeadNode);
if (!linkedListEquals) {
flag = false;
break;
}
// System.out.println("s1 = " + s1);
// System.out.println("s2 = " + s2);
if (!s1.equals(s2)) {
flag = false;
break;
}
}
System.out.println("测试结束!");
System.out.println(flag ? "nice!" : "oops!");
}
//打印单链表
public static String printLinkedList(Node head) {
StringBuilder s = new StringBuilder();
while (head != null) {
// System.out.print(head.value + "->");//打印
// s.append(head.value).append("->");
head = head.next;
}
// System.out.println("null");//打印
// s.append("null");
// System.out.println("s = " + s);//打印
return s.toString();
}
//for test
public static Node test(Node head, int num) {
ArrayList<Node> list = new ArrayList<>();
while (head != null) {
if (head.value != num) {
break;
}
head = head.next;
}
while (head != null) {
list.add(head);
head = head.next;
}
list.add(null);
Node node0 = list.get(0);
Node pre = node0;
for (int i = 1; i < list.size() - 1; i++) {//node111
if (list.get(i).value == num) {
pre.next = list.get(i).next;
} else {
list.get(i).next = list.get(i + 1);
pre = list.get(i);
}
// printLinkedList(list.get(0));
}
return node0;
}
//生成随机单链表
public static Node generateRandomLinkedList(int maxSize, int maxValue) {
int[] arr = new int[(int) (Math.random() * maxSize + 2)];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) (Math.random() * maxValue);
}
// System.out.println("arr = " + Arrays.toString(arr));
for (int i = 0; i < arr.length - 1; i++) {
Node node0 = new Node(arr[i]);
node0.next = new Node(arr[i + 1]);
}
Node node0 = new Node(arr[0]);
Node pre = node0;
for (int i = 1; i < arr.length; i++) {
Node cur = new Node(arr[i]);
pre.next = cur;
pre = cur;
}
return node0;
}
//看两个链表是否相等
public static boolean isLinkedListEquals(Node node1, Node node2) {
if (node1 == null && node2 == null) {
return true;
}
if (node1 == null && node2 != null) {
return false;
}
if (node1 != null && node2 == null) {
return false;
}
try {
while (node1 != null || node2 != null) {
if (node1.value != node2.value) {
return false;
}
node1 = node1.next;
node2 = node2.next;
}
} catch (NullPointerException e) {
// throw new RuntimeException(e);
System.out.println("e = " + e);
return false;
}
return true;
}
//1->1->2->3->null
/*public static Node copyLinkedList(Node h1) {
Node h2 = new Node(h1.value);
Node cur = null;
Node pre = h2;
while (h1 != null) {
cur = new Node(h1.value);
pre.next = cur;
pre = cur;
h1 = h1.next;
printLinkedList(h2);
}
return h2;
}*/
//复制链表
public static Node copyRandomList(Node head) {///
Node cur = head;
Node dum = new Node(0);
Node pre = dum;
while (cur != null) {
Node node = new Node(cur.value); // 复制节点 cur
pre.next = node; // 新链表的 前驱节点 -> 当前节点
// pre.random = "???"; // 新链表的 「 前驱节点 -> 当前节点 」 无法确定
cur = cur.next; // 遍历下一节点
pre = node; // 保存当前新节点
}
return dum.next;
}
}