C++程序 单链表中交替K节点翻转

C++程序 单链表中交替K节点翻转

给定一个链表,请写一个函数来高效地翻转每个交替的K(K是函数的输入值)个节点。请给出您的算法的复杂度。

示例:

输入:1->2->3->4->5->6->7->8->9->NULL 和 k = 3
输出:3->2->1->4->5->6->9->8->7->NULL。

方法1(处理前2k个节点,然后递归调用剩下的列表):

这种方法实际上是在此文章中讨论的方法的扩展。

kAltReverse(struct node *head, int k)
1) 反转前k个节点。
2) 在修改后的列表中,头指向第k个节点。因此,将头的下一个改为第(k+1)个节点。
3) 移动当前指针以跳过接下来的k个节点。
4) 递归调用kAltReverse()来处理其余的n – 2k个节点。
5) 返回列表的新头。

// C++ program to reverse alternate
// k nodes in a linked list
#include <bits/stdc++.h>
using namespace std;
 
// Link list node
class Node
{
    public:
    int data;
    Node* next;
};
 
/* Reverses alternate k nodes and
   returns the pointer to the new
   head node */
Node *kAltReverse(Node *head, int k)
{
    Node* current = head;
    Node* next;
    Node* prev = NULL;
    int count = 0;
 
    /* 1) reverse first k nodes of the
       linked list */
    while (current != NULL && count < k)
    {
    next = current->next;
    current->next = prev;
    prev = current;
    current = next;
    count++;
    }
     
    /* 2) Now head points to the kth node.
       So change next  of head to (k+1)th node*/
    if(head != NULL)
    head->next = current;
 
    /* 3) We do not want to reverse next k
       nodes. So move the current
       pointer to skip next k nodes */
    count = 0;
    while(count < k-1 &&
          current != NULL )
    {
    current = current->next;
    count++;
    }
 
    /* 4) Recursively call for the list
       starting from current->next. And make
       rest of the list as next of first node */
    if(current != NULL)
    current->next = kAltReverse(current->next, k);
 
    /* 5) prev is new head of the input list */
    return prev;
}
 
// UTILITY FUNCTIONS
// Function to push a node
void push(Node** head_ref,
          int new_data)
{
    // Allocate node
    Node* new_node = new Node();
 
    //  Put in the data
    new_node->data = new_data;
 
    // Link the old list of the
    // new node
    new_node->next = (*head_ref);    
 
    // Move the head to point to the
    // new node
    (*head_ref) = new_node;
}
 
// Function to print linked list
void printList(Node *node)
{
    int count = 0;
    while(node != NULL)
    {
        cout<<node->data<<" ";
        node = node->next;
        count++;
    }
}
 
// Driver code
int main(void)
{
    // Start with the empty list
    Node* head = NULL;
    int i;
     
    // Create a list
    // 1->2->3->4->5...... ->20
    for(i = 20; i > 0; i--)
    push(&head, i);
 
    cout << "Given linked list ";
    printList(head);
    head = kAltReverse(head, 3);
 
    cout << "Modified Linked list ";
    printList(head);
    return(0);
}
// This code is contributed by rathbhupendra```  

输出:

给定链表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
修改后的链表
3 2 1 4 5 6 9 8 7 10 11 12 15 14 13 16 17 18 20 19

时间复杂度: O(n)

辅助空间: O(1)

方法2(处理k个节点并递归调用列表的其余部分):

方法1将前k个节点反转,然后将指针移到k个节点之后。因此,方法1使用两个 while 循环,在一个递归调用中处理2k个节点。

此方法每次递归调用只处理k个节点。它使用第三个 bool 参数 b,该参数决定是否反转k个元素或仅移动指针。

_kAltReverse(struct node *head, int k, bool b)
1) 如果 b 为 true,则反转前 k 个节点。
2) 如果 b 是 false,则将指针向前移动 k 个节点。
3) 对 n-k 节点的其余部分递归调用 kAltReverse(),并将修改后的列表的其余部分连接到前 k 个节点的末尾。
4) 返回列表的新头。

// C++ 程序实现
// 上述方法
#include <bits/stdc++.h>
using namespace std;
 
// 链表节点
class node
{
    public:
    int data;
    node* next;
};
 
// kAltReverse() 的辅助函数
node * _kAltReverse(node *node,
                    int k, bool b);
 
// 改用组大小为k的传统方法翻转链表。
node *kAltReverse(node *head, int k)
{
    return _kAltReverse(head, k, true);
}
 
/* kAltReverse() 的辅助函数。
   如果传入第三个参数 b 为 true,则仅翻转列表的 k 个节点,
   否则将指针向前移动 k 个节点,并调用自身进行递归。*/
node * _kAltReverse(node *Node, int k, bool b)
{
    if(Node == NULL)
        return NULL;
     
    int count = 1;
    node *prev = NULL;
    node *current = Node;
    node *next;
     
    /* 该循环有两个作用
        1) 如果 b 为 true,则翻转 k 个节点
        2) 如果 b 是 false,则移动当前指针 */
    while(current != NULL && count <= k)
    {
        next = current->next;
     
        // 只有在 b 为 true 时才反转节点
        if(b == true)
            current->next = prev;
                 
        prev = current;
        current = next;
        count++;
    }
         
    /* 3) 如果 b 为 true,则该节点是第 k 个节点。
        因此,将剩余的列表附加到该节点后。
        4) 附加后,返回新的头节点*/
    if(b == true)
    {
        Node->next = _kAltReverse(current, k, !b);
        return prev;        
    }
         
    /* 如果 b 不为 true,则将
       剩余的列表附加到 prev 后。
       因此,将剩余的列表附加到 prev后*/
    else
    {
        prev->next =
            _kAltReverse(current, k, !b);
        return Node;    
    }
}
 
// 实用函数
// 将节点推入链表
void push(node** head_ref,
          int new_data)
{
    // 分配节点
    node* new_node = new node();
 
    // 加入数据
    new_node->data = new_data;
 
    // 将新节点的旧链表链接起来
    new_node->next = (*head_ref);
 
    // 将头部移动到新节点
    (*head_ref) = new_node}
 
// 打印链表的函数
void printList(node *node)
{
    int count = 0;
    while(node != NULL)
    {
        cout << node->data << " ";
        node = node->next;
        count++;
    }
}
 
// 主函数
int main(void)
{
    // 从空列表开始
    node* head = NULL;
    int i;
 
    // 创建列表
    // 1->2->3->4->5...... ->20
    for(i = 20; i > 0; i--)
    push(&head;, i);
 
    cout << "给定的链表 ";
    printList(head);
    head = kAltReverse(head, 3);
 
    cout << "修改后的链表 ";
    printList(head);
    return(0);
}
// 本代码由 rathbhupendra 提供。```  

输出:

给定链接列表 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 修改后的链接列表 3 2 1 4 5 6 9 8 7 10 11 12 15 14 13 16 17 18 20 19

时间复杂度: O(n)

辅助空间 :由于使用递归,调用堆栈的辅助空间为O(n)

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程

C++ 示例