单链表反转
链表中环的检测
两个有序的链表合并
删除链表倒数第 n 个结点
求链表的中间结点
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author zxh
* @date 2021/5/18 10:08
*/
public class LinkedListTest {
/**
* 递归反转
* head 头节点
*/
public Node reverse1(Node head){
if (head == null || head.next == null){
return head;
}
//rec为尾节点,反转后作为头结点
Node rec = reverse1(head.next);
//将当前节点的下一个节点指向当前节点
head.next.next = head;
//当前节点指针为空
head.next= null;
return rec;
}
/**
* 遍历反转
* head 头节点
*/
public void reverse2(Node head){
//上一节点
Node pre= head;
//当前节点
Node cur = pre.next;
//下一节点(临时节点)
Node temp;
while ( cur != null){
temp = cur.next;
cur.next = pre;
//移动指针(当前节点移向上一节点)
pre = cur;
//移动指针(下一节点移向当前节点)
cur = temp;
}
//单链表的首节点作为尾节点 指向Null
head.next = null;
}
/**
* 中环检测(快慢指针法)
* head 头节点
*/
public boolean isCircle1(Node head){
if (head == null || head.next == null){
return false;
}
//慢指针单次遍历一个
Node slow = head;
//快指针单次遍历两个
Node fast = head;
while (slow.next != null && fast.next != null){
slow = slow.next;
fast = fast.next.next;
//快指针走到头,即没有环
if (fast == null){
return false;
//快慢指针相遇,有环
}else if (fast == slow){
return true;
}
}
return false;
}
/**
* 中环检测(足迹法)
* head 头节点
*/
public boolean isCircle2(Node head){
if (head == null || head.next == null){
return false;
}
Map<Object,Object> map = new HashMap<>();
map.put(head,head.e);
while (head.next != null ){
head = head.next;
//遍历时该节点集合已存在则存在中环
if (map.containsKey(head)){
return true;
}
map.put(head,head.e);
}
return false;
}
/**
* 有序链表合并(递归)
* head1 头节点 head2 头节点
*/
public Node merge1(Node head1,Node head2){
if (head1 == null){
return head2;
}
if (head2 == null){
return head1;
}
Node head ;
if (head1.e < head2.e){
head = head1;
head.next = merge1(head1.next,head2);
}else {
head = head2;
head.next = merge1(head1,head2.next);
}
return head;
}
/**
* 有序链表合并(遍历)
* head1 头节点 head2 头节点
*/
public Node merge2(Node head1,Node head2){
//头节点
Node head ;
if (head1.e < head2.e){
head = new Node(head1.e);
head1 = head1.next;
}else {
head = new Node(head2.e);
head2 = head2.next;
}
//保存头节点
Node temp = head;
while (head1!= null && head2 != null){
if (head1.e < head2.e){
head.next = new Node(head1.e);
head1 = head1.next;
}else {
head.next = new Node(head2.e);
head2 = head2.next;
}
head = head.next;
}
if (head1 == null){
head.next = head2;
}
if (head2 == null){
head.next = head1;
}
return temp;
}
/**
* 删除倒数第n个节点数据
* index n
* head 头节点
*/
public void deleteDesc(int index,Node head){
Node slow = head;
Node fast = head;
//保持快节点与慢节点的距离为index
for (int i = 0; i < index; i++) {
fast = fast.next;
if (fast == null){
return;
}
}
//快节点到尾节点前一个节点,慢节点位置为需要删除节点的前一个节点
while (fast.next != null){
slow = slow.next;
fast = fast.next;
}
slow.next = slow.next.next;
}
/**
* 获取链表中间节点(数组保存)
* head 头节点
*/
public Node getMidNode(Node head){
List<Node> nodeList = new ArrayList<>();
while (head != null){
nodeList.add(head);
head = head.next;
}
Node node = nodeList.get(nodeList.size() / 2);
node.next = null;
return node;
}
public static void main(String[] args) {
Node node0 = new Node(0);
Node node1 = new Node(1);
Node node2 = new Node(2);
Node node3 = new Node(3);
Node node4 = new Node(4);
Node node5 = new Node(5);
node0.next = node1;
node1.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node5;
printResult(node0);
LinkedListTest linkedList = new LinkedListTest();
//递归反转
linkedList.reverse1(node0);
printResult(node5);
//遍历反转
linkedList.reverse2(node5);
printResult(node0);
System.out.println("================================");
//链表中环的检测(创建中环)
System.out.println(linkedList.isCircle1(node0));
System.out.println(linkedList.isCircle2(node0));
Node node6 = new Node(6);
node5.next = node6;
node6.next = node3;
//快慢指针法
System.out.println(linkedList.isCircle1(node0));
//足迹法
System.out.println(linkedList.isCircle2(node0));
System.out.println("================================");
//两个有序链表合并
node0 = new Node(0);
node1 = new Node(1);
node2 = new Node(2);
node3 = new Node(3);
node4 = new Node(4);
node5 = new Node(5);
node6 = new Node(2);
node0.next = node2;
node2.next = node4;
printResult(node0);
node1.next = node6;
node6.next = node3;
node3.next = node5;
printResult(node1);
//递归合并有序链表
Node result1 = linkedList.merge1(node0, node1);
printResult(result1);
node0 = new Node(0);
node1 = new Node(1);
node2 = new Node(2);
node3 = new Node(3);
node4 = new Node(4);
node5 = new Node(5);
node6 = new Node(2);
node0.next = node2;
node2.next = node4;
printResult(node0);
node1.next = node6;
node6.next = node3;
node3.next = node5;
printResult(node1);
//遍历合并有序链表
Node result2 = linkedList.merge2(node0, node1);
printResult(result2);
System.out.println("================================");
//删除倒数第n个节点
linkedList.deleteDesc(3,result2);
printResult(result2);
System.out.println("================================");
//获取链表的中间结点
Node midNode = linkedList.getMidNode(result1);
printResult(midNode);
}
/**
* 输出结果
*/
private static void printResult(Node node){
while (node != null){
System.out.print(node.e+" -> ");
node =node.next;
}
System.out.println("NULL");
}
}
/**
* 节点
* 数据 指向下个数据指针
*/
class Node{
public int e;
public Node next;
public Node(int e) {
this.e = e;
}
}