📅  最后修改于: 2023-12-03 15:16:37.748000             🧑  作者: Mango
双向链表是一种常见的数据结构,它和单向链表相比,除了每个节点有一个指向下一个节点的指针,还多了一个指向上一个节点的指针。双向链表可以支持双向遍历,因此在某些场景下使用更加方便。
本文介绍如何编写Java程序将双向链表旋转N个节点。
在Java中,定义双向链表节点通常使用以下代码:
class ListNode {
int val;
ListNode next, prev;
ListNode(int val) {
this.val = val;
}
}
其中,val
是节点的值,next
是指向下一个节点的指针,prev
是指向上一个节点的指针。
为了方便起见,我们可以先写一个构建双向链表的函数。这个函数接收一个数组,返回链表的头节点。例如,如果数组为 [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;
}
接下来,我们需要编写旋转链表的函数。这个函数接收一个链表的头节点 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;
}
下面是完整的程序代码:
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
。
以上就是本文的全部内容。如果您有任何疑问或建议,欢迎在评论区留言!