多写多练没有捷径:5 个常见的链表操作

94 阅读2分钟

5 个常见的链表操作:

(1)单链表反转

(2)链表中环的检测

(3)两个有序的链表合并

(4)删除链表倒数第n个结点

(5)求链表的中间结点

public class LinkedListTest {

  // 单链表反转
  public static Node reverse(Node list) {
    Node curr = list, pre = null; // 初始化当前节点为传入的链表头,前一个节点为null
    while (curr != null) { // 当当前节点不为空时
      Node next = curr.next; // 保存当前节点的下一个节点
      curr.next = pre; // 将当前节点的下一个节点指向前一个节点(反转)
      pre = curr; // 将当前节点设置为下一次迭代的前一个节点
      curr = next; // 移动到下一个节点
    }
    return pre; // 返回反转后的头节点
  }

  // 检测环
  public static boolean checkCircle(Node list) {
    if (list == null) return false; // 如果链表为空,则没有环

    Node fast = list.next; // 快指针
    Node slow = list; // 慢指针

    // 快慢指针法检测环
    while (fast != null && fast.next != null) { 
      fast = fast.next.next; // 快指针每次走两步
      slow = slow.next; // 慢指针每次走一步

      if (slow == fast) return true; // 如果相遇,说明有环
    }

    return false; // 否则没有环
  }

  // 删除倒数第K个结点
  public static Node deleteLastKth(Node list, int k) {
    Node fast = list; // 快指针
    int i = 1;
    while (fast != null && i < k) { // 移动快指针到第k个节点
      fast = fast.next;
      ++i;
    }

    if (fast == null) return list; // 如果k大于链表长度,返回原链表

    Node slow = list; // 慢指针
    Node prev = null; // 慢指针的前一个节点
    while (fast.next != null) { // 当快指针没有到达链表末尾
      fast = fast.next; // 快指针移动
      prev = slow; // 保存慢指针的前一个节点
      slow = slow.next; // 慢指针移动
    }

    if (prev == null) { // 如果删除的是头节点
      list = list.next;
    } else { // 删除慢指针指向的节点
      prev.next = prev.next.next;
    }
    return list; // 返回新链表头节点
  }

  // 求中间结点
  public static Node findMiddleNode(Node list) {
    if (list == null) return null; // 如果链表为空,返回null

    Node fast = list; // 快指针
    Node slow = list; // 慢指针

    // 快慢指针法找中间节点
    while (fast != null && fast.next != null) { 
      fast = fast.next.next; // 快指针每次走两步
      slow = slow.next; // 慢指针每次走一步
    }

    return slow; // 返回中间节点
  }

  // 打印链表
  public static void printAll(Node list) {
    Node p = list; // 从链表头开始
    while (p != null) { // 遍历链表
      System.out.print(p.data + " "); // 打印当前节点数据
      p = p.next; // 移动到下一个节点
    }
    System.out.println(); // 输出换行
  }

  // 创建新节点
  public static Node createNode(int value) {
    return new Node(value, null); // 创建新节点,next为null
  }

  // 节点类定义
  public static class Node {
    private int data; // 节点存储的数据
    private Node next; // 指向下一个节点的指针

    // 节点构造函数
    public Node(int data, Node next) {
      this.data = data; // 初始化数据
      this.next = next; // 初始化下一个节点
    }

    // 获取节点数据
    public int getData() {
      return data; 
    }
  }

}

学习:极客时间《数据结构与算法之美》学习笔记