📜  Java程序将双向链表旋转N个节点(1)

📅  最后修改于: 2023-12-03 15:16:37.748000             🧑  作者: Mango

Java程序将双向链表旋转N个节点

双向链表是一种常见的数据结构,它和单向链表相比,除了每个节点有一个指向下一个节点的指针,还多了一个指向上一个节点的指针。双向链表可以支持双向遍历,因此在某些场景下使用更加方便。

本文介绍如何编写Java程序将双向链表旋转N个节点。

1. 定义双向链表节点

在Java中,定义双向链表节点通常使用以下代码:

class ListNode {
    int val;
    ListNode next, prev;
    ListNode(int val) {
        this.val = val;
    }
}

其中,val 是节点的值,next 是指向下一个节点的指针,prev 是指向上一个节点的指针。

2. 构建双向链表

为了方便起见,我们可以先写一个构建双向链表的函数。这个函数接收一个数组,返回链表的头节点。例如,如果数组为 [1,2,3,4,5],则返回的链表应该是 1 -> 2 -> 3 -> 4 -> 5。

static ListNode buildList(int[] nums) {
    ListNode head = null, tail = null; // 头节点和尾节点指针
    for (int num : nums) {
        ListNode node = new ListNode(num);
        if (head == null) { // 如果还没有头节点,当前节点就是头节点
            head = node;
        } else { // 如果已经有头节点,就把当前节点添加到尾节点之后
            tail.next = node;
            node.prev = tail;
        }
        tail = node; // 当前节点永远都是尾节点
    }
    return head;
}
3. 旋转链表

接下来,我们需要编写旋转链表的函数。这个函数接收一个链表的头节点 head 和一个整数 n,返回旋转后的链表的头节点。

例如,如果链表为 1 -> 2 -> 3 -> 4 -> 5,n 为 2,则返回的链表应该是 4 -> 5 -> 1 -> 2 -> 3。

static ListNode rotateList(ListNode head, int n) {
    if (head == null || n == 0) {
        // 如果链表为空或者 n 为 0,直接返回原链表头节点
        return head;
    }
    ListNode tail = head;
    int len = 1;
    // 找到链表的尾节点和长度
    while (tail.next != null) {
        tail = tail.next;
        len++;
    }
    // 计算实际需要旋转的节点数
    n %= len;
    if (n == 0) {
        // 如果实际需要旋转的节点数为 0,直接返回原链表头节点
        return head;
    }
    // 找到倒数第 n + 1 个节点,将其后面的所有节点插入到链表头节点之前
    ListNode p = head;
    for (int i = 1; i < len - n; i++) {
        p = p.next;
    }
    tail.next = head; // 将尾节点指向原链表头节点
    head.prev = tail; // 将原链表头节点指向尾节点
    ListNode newHead = p.next;
    newHead.prev = null; // 将新链表头节点的 prev 置为 null
    p.next = null; // 将倒数第 n + 1 个节点的 next 置为 null
    return newHead;
}
4. 整体代码

下面是完整的程序代码:

class ListNode {
    int val;
    ListNode next, prev;
    ListNode(int val) {
        this.val = val;
    }
}

public class Main {
    static ListNode buildList(int[] nums) {
        ListNode head = null, tail = null; // 头节点和尾节点指针
        for (int num : nums) {
            ListNode node = new ListNode(num);
            if (head == null) { // 如果还没有头节点,当前节点就是头节点
                head = node;
            } else { // 如果已经有头节点,就把当前节点添加到尾节点之后
                tail.next = node;
                node.prev = tail;
            }
            tail = node; // 当前节点永远都是尾节点
        }
        return head;
    }

    static ListNode rotateList(ListNode head, int n) {
        if (head == null || n == 0) {
            // 如果链表为空或者 n 为 0,直接返回原链表头节点
            return head;
        }
        ListNode tail = head;
        int len = 1;
        // 找到链表的尾节点和长度
        while (tail.next != null) {
            tail = tail.next;
            len++;
        }
        // 计算实际需要旋转的节点数
        n %= len;
        if (n == 0) {
            // 如果实际需要旋转的节点数为 0,直接返回原链表头节点
            return head;
        }
        // 找到倒数第 n + 1 个节点,将其后面的所有节点插入到链表头节点之前
        ListNode p = head;
        for (int i = 1; i < len - n; i++) {
            p = p.next;
        }
        tail.next = head; // 将尾节点指向原链表头节点
        head.prev = tail; // 将原链表头节点指向尾节点
        ListNode newHead = p.next;
        newHead.prev = null; // 将新链表头节点的 prev 置为 null
        p.next = null; // 将倒数第 n + 1 个节点的 next 置为 null
        return newHead;
    }

    public static void main(String[] args) {
        int[] nums = new int[]{1, 2, 3, 4, 5};
        ListNode list = buildList(nums);
        ListNode newHead = rotateList(list, 2);
        while (newHead != null) {
            System.out.print(newHead.val + " ");
            newHead = newHead.next;
        }
    }
}

运行结果是:4 5 1 2 3

以上就是本文的全部内容。如果您有任何疑问或建议,欢迎在评论区留言!