package com.again.common.arithmetic.LinkedList;
import com.again.common.arithmetic.Node;
import com.google.common.base.Preconditions;
/**
* 单向链表
*
* 删除链表中指定的节点
*
*/
public class SinglyLinkedList {
/**
* 删除链表中指定的节点
*
* 说明:首先将targetNode的后继节点的值复制到targetNode中,然后将targetNode的后继节点删除掉,最终的效果与删除targetNode等价,但是时间复杂度为O(1)。
*
* 注意:
* 1)前提是targetNode一定存在于链表中。
* 2)若要删除的节点是尾节点,则我们只能通过遍历链表来删除尾节点,时间复杂度为O(n)。
* 3)所以平均时间复杂度为[(n-1)*O(1) + O(n)]/n ,即平均时间复杂度仍然为O(1)。
*
* @param head 头节点
* @param targetNode 要删除的节点
*/
public static void deleteNode(Node head, Node targetNode) {
Preconditions.checkArgument(null != head && null != targetNode);
// 要删除的节点是尾节点
if (null == targetNode.next) {
Node currentNode = head;
if (currentNode == targetNode) { // 链表中只有一个节点,删除该节点时应该同时将指向它的引用都置为null。
targetNode = null;
head = null;
currentNode = null;
} else { // 链表中节点数大于1
while (currentNode!= null && currentNode.next != targetNode) {
currentNode = currentNode.next;
}
if (null != currentNode) {
currentNode.next = currentNode.next.next;
targetNode.next = null;
} else { // 要删除的节点在链表中不存在
}
}
}
// 要删除的节点不是尾节点
else {
// targetNode的后继节点
Node nextOfTargetNode = targetNode.next;
// 将targetNode的后继节点的值复制到targetNode中,
// 此时targetNode的值和它的后继节点的值相等,故删除掉targetNode的后继节点等价于删除targetNode
targetNode.value = nextOfTargetNode.value;
// 删除targetNode的后继节点
targetNode.next = nextOfTargetNode.next;
nextOfTargetNode.next = null;
}
}
public static void main(String[] args) {
Node head = LinkedListUtil.init();
Node node3 = head.next.next.next;
LinkedListUtil.print(head);
deleteNode(head,node3);
LinkedListUtil.print(head);
}
}