数据结构单链表之旋转链表 | 第十五套

简介: 数据结构单链表之旋转链表 | 第十五套

给定一个单链表,将链表逆时针旋转 k 个节点。其中 k 是给定的正整数。例如,如果给定的链表是 10->20->30->40->50->60 且 k 为 4,则该链表应修改为 50->60->10->20->30- > 40。假设 k 小于链表中的节点数。

方法一:

要旋转链表,我们需要将第k个节点的next改为NULL,将最后一个节点的next改为上一个头节点,最后将head改为第(k+1)个节点。所以我们需要掌握三个节点:第k个节点、第(k+1)个节点和最后一个节点。

从头开始遍历列表并在第 k 个节点处停止。存储指向第 k 个节点的指针。我们可以使用 kthNode->next 得到第 (k+1) 个节点。继续遍历直到最后并存储指向最后一个节点的指针。最后,如上所述更改指针。


#include <bits/stdc++.h>
using namespace std;
class Node {
public:
  int data;
  Node* next;
};
void rotate(Node** head_ref, int k)
{
  if (k == 0)
    return;
  Node* current = *head_ref;
  int count = 1;
  while (count < k && current != NULL) {
    current = current->next;
    count++;
  }
  if (current == NULL)
    return;
  Node* kthNode = current;
  while (current->next != NULL)
    current = current->next;
  current->next = *head_ref;
  *head_ref = kthNode->next;
  kthNode->next = NULL;
}
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)
{
  while (node != NULL) {
    cout << node->data << " ";
    node = node->next;
  }
}
int main(void)
{
  Node* head = NULL;
  for (int i = 60; i > 0; i -= 10)
    push(&head, i);
  cout << "Given linked list \n";
  printList(head);
  rotate(&head, 4);
  cout << "\nRotated Linked list \n";
  printList(head);
  return (0);
}

输出:

Given linked list
10  20  30  40  50  60
Rotated Linked list
50  60  10  20  30  40

时间复杂度:O(n),其中 n 是链表中的节点数。代码只遍历链表一次。

如果您发现任何不正确的内容,或者您想分享有关上述主题的更多信息,请发表评论。

方法2:

将链表旋转k,我们可以先使链表循环,然后从头节点向前移动k-1步,使第(k-1)个节点紧挨着空,并以第k个节点为头。

#include <bits/stdc++.h>
using namespace std;
class Node {
public:
  int data;
  Node* next;
};
void rotate(Node** head_ref, int k)
{
  if (k == 0)
    return;
  Node* current = *head_ref;
  while (current->next != NULL)
    current = current->next;
  current->next = *head_ref;
  current = *head_ref;
  for (int i = 0; i < k - 1; i++)
    current = current->next;
  *head_ref = current->next;
  current->next = NULL;
}
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)
{
  while (node != NULL) {
    cout << node->data << " ";
    node = node->next;
  }
}
int main(void)
{
  Node* head = NULL;
  for (int i = 60; i > 0; i -= 10)
    push(&head, i);
  cout << "Given linked list \n";
  printList(head);
  rotate(&head, 4);
  cout << "\nRotated Linked list \n";
  printList(head);
  return (0);
}

输出:

Given linked list 
10 20 30 40 50 60 
Rotated Linked list 
50 60 10 20 30 40


目录
相关文章
|
1天前
|
Java
java数据结构,双向链表的实现
文章介绍了双向链表的实现,包括数据结构定义、插入和删除操作的代码实现,以及双向链表的其他操作方法,并提供了完整的Java代码实现。
java数据结构,双向链表的实现
|
1天前
|
存储 Java
java数据结构,线性表链式存储(单链表)的实现
文章讲解了单链表的基本概念和Java实现,包括头指针、尾节点和节点结构。提供了实现代码,包括数据结构、接口定义和具体实现类。通过测试代码演示了单链表的基本操作,如添加、删除、更新和查找元素,并总结了操作的时间复杂度。
java数据结构,线性表链式存储(单链表)的实现
|
23天前
|
存储 Java 索引
【数据结构】链表从实现到应用,保姆级攻略
本文详细介绍了链表这一重要数据结构。链表与数组不同,其元素在内存中非连续分布,通过指针连接。Java中链表常用于需动态添加或删除元素的场景。文章首先解释了单向链表的基本概念,包括节点定义及各种操作如插入、删除等的实现方法。随后介绍了双向链表,说明了其拥有前后两个指针的特点,并展示了相关操作的代码实现。最后,对比了ArrayList与LinkedList的不同之处,包括它们底层实现、时间复杂度以及适用场景等方面。
41 10
【数据结构】链表从实现到应用,保姆级攻略
|
19天前
|
存储 算法 C语言
数据结构基础详解(C语言):单链表_定义_初始化_插入_删除_查找_建立操作_纯c语言代码注释讲解
本文详细介绍了单链表的理论知识,涵盖单链表的定义、优点与缺点,并通过示例代码讲解了单链表的初始化、插入、删除、查找等核心操作。文中还具体分析了按位序插入、指定节点前后插入、按位序删除及按值查找等算法实现,并提供了尾插法和头插法建立单链表的方法,帮助读者深入理解单链表的基本原理与应用技巧。
|
19天前
|
存储 算法 C语言
C语言手撕实战代码_循环单链表和循环双链表
本文档详细介绍了用C语言实现循环单链表和循环双链表的相关算法。包括循环单链表的建立、逆转、左移、拆分及合并等操作;以及双链表的建立、遍历、排序和循环双链表的重组。通过具体示例和代码片段,展示了每种算法的实现思路与步骤,帮助读者深入理解并掌握这些数据结构的基本操作方法。
|
1月前
|
存储 Java 程序员
"揭秘HashMap底层实现:从数组到链表,再到红黑树,掌握高效数据结构的秘密武器!"
【8月更文挑战第21天】HashMap是Java中重要的数据结构,采用数组+链表/红黑树实现,确保高效查询与更新。构造方法初始化数组,默认容量16,负载因子0.75触发扩容。`put`操作通过计算`hashCode`定位元素,利用链表或红黑树处理冲突。`get`和`remove`操作类似地定位并返回或移除元素。JDK 1.8优化了链表转红黑树机制,提升性能。理解这些原理能帮助我们更高效地应用HashMap。
32 0
|
1月前
|
算法 索引
【初阶数据结构篇】单链表算法题进阶
深拷贝应该正好由 n 个全新节点组成,其中每个新节点的值都设为其对应的原节点的值。
|
1月前
|
存储 算法
【初阶数据结构篇】顺序表和链表算法题
此题可以先找到中间节点,然后把后半部分逆置,最近前后两部分一一比对,如果节点的值全部相同,则即为回文。
|
1月前
|
存储 测试技术
【初阶数据结构篇】双向链表的实现(赋源码)
因为头结点的存在,plist指针始终指向头结点,不会改变。
|
1月前
|
存储 测试技术
【初阶数据结构篇】单链表的实现(附源码)
在尾插/尾删中,都需要依据链表是否为空/链表是否多于一个节点来分情况讨论,目的是避免对空指针进行解引用造成的错误。