C++ 中将链表中的元素所有出现移到末尾2025 年 5 月 13 日 | 阅读 7 分钟 链表是计算机科学和编程语言中的一种基本数据结构,几乎存在于所有类型的计算机系统中。它与数组不同,通过将通过指针连接的顺序节点组合成一个序列,动态且高效地利用内存。使用链表时的一个典型问题是如何在保持特定顺序或结构的同时更改其元素的位置。 在这篇博客文章中,我们将讨论一个经典的链表问题:将链表中一个元素的所有出现移到列表的末尾。这个问题是处理链表指针、元素顺序和时间复杂度的常见实现。 假设您有一个链表,其中包含多个您的值实例,并且您希望将它们按升序排序,以部分地将它们放在链表的末尾。问题在于,除了目标元素之外的任何元素都必须保持其在初始排列中的相同顺序。此外,如果目标元素重复出现,它们也必须保持其顺序。这使得该问题与之前提到的简单节点重排不同。 为了使这个想法更具体,我举一个例子。假设您有一个链表 该列表以各种元素开头;事实上,列表中有许多个 2。操作结束后,所有的 2 都被移动到列表的倒数第二个元素之前,所有其他元素保持不变,并保持其顺序 1, 3, 4, 5。被移动的 2 也保持其顺序不变。 这个问题在竞争性编程和技术面试中很受欢迎,因为它考验程序员对链表指针工作特点的理解,以及即使乍一看也能快速正确地解决问题的能力。它在现实生活中也很重要,在现实生活中需要对相互关联的数据执行类似操作,并且需要重新排序,例如,对任务进行排序或重新排列动态数据结构的结构组件。 问题陈述该任务可以正式描述如下 假设您有一个单链表和一个必须放在列表尾部的值 x;以这种方式重新排列列表项。其他元素的位置不应更改,目标值的位置也应保持不变。 例如为了实现这一点,我们必须仔细处理与链表操作相关的几个关键挑战 指针管理: 链表与数组有些不同,因为没有直接的索引指针;必须通过指针遍历链表才能获取数据元素。由于这些指针是作者提供的唯一移动节点的方式,因此正确控制这些指针非常重要,以免丢失存储的数据或甚至导致列表损坏。 顺序保持: 因此,保持非目标和目标的相对顺序也增加了另一个难度。例如,对于输出,1 -> 3 -> 4 -> 4;对于输入,1 -> 4 -> 4 -> 3。1 和 3 不能互换。同样,4 和 4 也不能互换。 效率: 一个可能的简单解决方案是使用另一个列表或重新遍历原始列表以移动目标元素。然而,这会导致在大型列表上性能不佳;因此可能不适用于大型列表。完美的解决方案应该能够只遍历列表一次,或者在最佳解决方案中,最多两次。 主要挑战在链表或一般使用指针交换元素,以将给定值的所有出现都放在后面并不容易。这些挑战主要源于链表类型的特点,其中使用节点指针进行节点操作,而不是像数组那样使用索引。 1. 指针管理链表不支持直接访问元素,因为它只通过指针指向节点。为了移动元素,我们必须更新节点的下一个指针,以使列表保持完整。指针故障会导致链接断裂、循环引用或丢失所需的数据视图。 例如,当节点移动到列表的尾部时,需要首先删除该节点,然后更改前一个节点的指针,并将该节点设为新的尾部。管理此类更改的问题在于,一个级别的任何搅动都可能影响列表的其他方面。 2. 顺序保持保持非目标节点和目标节点的相对顺序也使事情复杂化。例如,如果输入是 1 -> 2 -> 3 -> 2 -> 4 -> 2,则输出必须包含一个序列,其中非目标节点 (1, 3, 4) 必须与目标节点 (2, 2, 2) 保持相同的顺序。这排除了直接解决问题的方法,例如,通过以其流无关紧要的方式对节点进行分组。 3. 效率如果算法效率不高,例如,需要对列表进行一次遍历来查找和重新定位目标节点,则时间复杂度为 O(n^2)。对于更长的链表,这种梳理过程在计算上会变得非常昂贵。解决方案的最优性意味着其实现必须在 O(n) 时间内遍历此列表,每个节点只影响一次。 4. 边缘情况必须解决一些考虑因素,例如当列表为空、列表是单个节点,或者列表等于所有或不等于任何目标值时。这些情况提供了一些额外信息,可用于挑战解决方案并定义其适用性。 编码 输入 输出 List after moving all occurrences of the target (2) to the end: 1 -> 3 -> 4 -> 5 -> 2 -> 2 -> 2 -> nullptr |
为什么我们不能在 C++ 中声明 std::vector<AbstractClass>?概述 C++ 底层标准模板库 (STL) 的几个主要元素之一是动态集合 std::vector,它可以容纳几乎任何类型的结构。它随后提供了一种易于修改且成功的方法...
7 分钟阅读
在 C++ 编程语言中,“替换失败不是错误”(SFINAE)原则表明,编译器不应因为无法替换模板参数而停止处理程序。在处理复杂代码和难以理解的逻辑时,此原则可能很有用,因为它...
阅读 4 分钟
引言:幸运数是与素数分解有特殊关系的整数。究竟是什么使一个数成为幸运数?幸运数是任何数字,在反复去除最小素数因子后,最终变成1。例如,幸运数的集合……
阅读 4 分钟
?在此系列结束时,您将拥有从头开始创建桌面程序的技能,因此让我们开始创建 C++ 桌面程序的有趣之旅。Win32 编程入门:C++ 中的 Win32 编程是指使用 Win32 API 创建 Windows 应用程序,Win32 API 是……
阅读 118 分钟
任务是确定两个给定向量数组的叉积和点积。假设我们有两个向量,向量 A 和向量 B,每个向量都包含 x、y 和方向。在本文中,我们将讨论一个 C++ 程序来查找……
阅读 4 分钟
在 C++ 中,虚函数和内联函数用途不同。虚函数通过允许派生类重写基类函数来支持多态性,从而在运行时产生动态行为。它依赖 vtable 进行函数调用解析,这会引入一些运行时开销。相比之下,内联...
阅读 10 分钟
引言 该算法首先选择一个初始点,通常是最左边的点,作为凸包的起始点。然后,它系统地遍历这些点,根据最逆时针的方向选择凸包上的点。这个过程一直持续到...
阅读 12 分钟
在本文中,我们将通过不同的方法讨论它。在讨论其方法之前,我们必须先了解 C++ 中的 Nicomachus 定理。用一个例子解释 Nicomachus 定理 k 的平方等于从 1 到 k 的奇数的和……
阅读 17 分钟
C++与Python的区别 C++和Python都是流行的编程语言。Python是一种流行的、高级的、面向对象的编程语言。另一方面,C++是一种通用编程语言。在本文中,我们将讨论C++和Python之间的区别。在讨论之前…
阅读 6 分钟
引言 模板和泛型为我们提供了编写灵活且可重用代码的强大能力。然而,当涉及到处理类型时,这些技术可能会变得相当复杂。最常见的问题之一与引用作为变量有关。当面临这种情况时...
7 分钟阅读
我们请求您订阅我们的新闻通讯以获取最新更新。
我们提供所有技术(如 Java 教程、Android、Java 框架)的教程和面试问题
G-13, 2nd Floor, Sec-3, Noida, UP, 201301, India