📜  C++程序将链表的子列表从位置M到N向右旋转K位(1)

📅  最后修改于: 2023-12-03 14:59:52.254000             🧑  作者: Mango

C++程序实现链表子列表从位置M到N向右旋转K位

本篇文章将介绍一种C++实现链表子列表从位置M到N向右旋转K位的方法。本文首先会介绍链表的基础知识,其次会详细介绍本算法的实现步骤,并提供详细的代码实现。最后,我们将对代码进行分析和测试。

链表的基础知识

链表是一种动态的数据结构,可以根据实际需要动态分配存储空间,而不需要预先分配空间。链表由节点组成,每个节点包括一个数据域和一个指向下一个节点的指针域。

链表有很多种类型。单向链表是指每个节点只有一个指针域,指向下一个节点。双向链表是指每个节点有两个指针域,一个指向前一个节点,一个指向后一个节点。环形链表是指链表中最后一个节点指向第一个节点,形成一个环。

实现步骤

本算法实现链表子列表从位置M到N向右旋转K位的操作,实现步骤如下:

  1. 找到链表中第M个节点和第N个节点,并记录M节点的前一个节点指针P,以便后面断开M节点和前一个节点的链接。
  2. 将M节点的前一个节点指针P指向N节点的后一个节点,即:P -> next = N -> next。
  3. 将N节点的后一个节点指针指向M节点,即:N -> next = M。
  4. 将M节点的后一个节点指针指向N节点的后一个节点,即:M -> next = temp。
  5. 重复步骤2到4 K次,完成旋转。
代码实现

给出C++代码如下:

#include <iostream>
using namespace std;

struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};

ListNode* rotateBetween(ListNode* head, int m, int n, int k) {
    ListNode *dummy = new ListNode(-1);
    dummy->next = head;

    ListNode *prev = dummy;
    for (int i = 1; i < m; i++) {
        prev = prev->next;
    }

    ListNode *start = prev->next;
    ListNode *end = start;

    for (int i = m; i < n; i++) {
        end = end->next;
    }

    for (int i = 0; i < k; i++) {
        ListNode *temp = start->next;
        start->next = end->next;
        prev->next = end;
        end->next = temp;
        end = prev->next;
    }

    return dummy->next;
}

int main() {
    ListNode *node1 = new ListNode(1);
    ListNode *node2 = new ListNode(2);
    ListNode *node3 = new ListNode(3);
    ListNode *node4 = new ListNode(4);
    ListNode *node5 = new ListNode(5);

    node1->next = node2;
    node2->next = node3;
    node3->next = node4;
    node4->next = node5;

    ListNode *newHead = rotateBetween(node1, 2, 4, 1);

    while (newHead != NULL) {
        cout << newHead->val << " ";
        newHead = newHead->next;
    }

    return 0;
}
代码分析与测试

上述代码实现了链表子列表从位置M到N向右旋转K位的功能。我们可以将代码进一步拆分成以下几个步骤:

  • 定义结构体ListNode,表示链表中的一个节点。
  • 在函数rotateBetween中,输入参数head表示链表的头指针,m表示要旋转的子列表的起始节点,n表示要旋转的子列表的结尾节点,k表示要旋转的次数。
  • 在链表中找到第m个节点和第n个节点,并记录其前一个节点的指针prev。
  • 重复k次,将m节点的前一个节点指针P指向N节点的后一个节点,即P -> next = N -> next,将N节点的后一个节点指针指向M节点,即N -> next = M,将M节点的后一个节点指针指向N节点的后一个节点,即M -> next = temp,完成旋转。
  • 返回旋转后的链表头指针。

我们可以用一组示例数据进行测试,链表1 -> 2 -> 3 -> 4 -> 5,将子列表2 -> 3 -> 4向右旋转1位,即rotateBetween(node1, 2, 4, 1),得到新的链表1 -> 4 -> 2 -> 3 -> 5,符合预期输出结果。

在代码的实现中,我们注意到采用了虚拟头节点技巧,使得代码逻辑更加清晰。同时,链表旋转操作的时间复杂度为O(n),空间复杂度为O(1)。