c++中的递归拷贝(Recursive Copy)和递归反转链表(Recursive Reverse Linked List)

前言

hello大家好啊,这里是文宇,不是文字,是文宇哦。

递归拷贝(Recursive Copy)

C++中的递归拷贝是一种在拷贝对象时使用递归方法的技术。在C++中,为了拷贝一个对象,通常使用拷贝构造函数或拷贝赋值运算符。然而,对于复杂的对象,拷贝构造函数和拷贝赋值运算符可能无法完全拷贝对象的所有成员。这就需要使用递归拷贝来确保所有成员都能被正确地拷贝。

递归拷贝是一种深度拷贝技术,它通过递归地拷贝对象的所有成员,包括成员变量和成员函数。在递归拷贝过程中,每个成员变量都会被递归拷贝,直到所有的成员变量都被拷贝完成。递归拷贝可以确保对象的所有成员都能被正确地拷贝,并且递归拷贝也可以处理动态分配的成员变量,例如指针和容器。

递归拷贝的实现思路是使用递归函数来拷贝对象的成员变量。对于每个成员变量,如果它是一个基本类型,那么直接拷贝它的值;如果它是一个自定义类型,那么递归地调用拷贝构造函数或拷贝赋值运算符来拷贝它。递归拷贝的终止条件是当对象的所有成员变量都被拷贝完成时,递归函数退出。

递归拷贝可以应用于各种复杂的对象,例如嵌套的数据结构和递归定义的数据类型。例如,考虑下面的示例类:

class Node {
public:int data;Node* next;Node(int data = 0, Node* next = nullptr) : data(data), next(next) {}
};

 

上面的类定义了一个链表节点,有一个整数类型的数据和一个指向下一个节点的指针。如果要拷贝一个链表,通常只拷贝头节点是不够的,还需要递归地拷贝整个链表。递归拷贝可以很方便地处理这种情况,代码如下:

Node* copyNode(Node* node) {if (node == nullptr) {return nullptr;}Node* newNode = new Node(node->data);newNode->next = copyNode(node->next);return newNode;
}Node* copyLinkedList(Node* head) {return copyNode(head);
}

 

上面的代码中,copyNode函数用来拷贝一个节点,它首先创建一个新节点,并将原节点的数据拷贝到新节点中。然后,它递归地调用copyNode函数来拷贝下一个节点。最后,它返回新节点的指针。copyLinkedList函数用来拷贝整个链表,它只需要调用copyNode函数来拷贝头节点即可。

递归拷贝除了能够处理嵌套的数据结构外,还可以处理递归定义的数据类型。例如,考虑下面的示例类:

class BinaryTree {
public:int data;BinaryTree* left;BinaryTree* right;BinaryTree(int data = 0, BinaryTree* left = nullptr, BinaryTree* right = nullptr): data(data), left(left), right(right) {}
};

 

上面的类定义了一个二叉树节点,有一个整数类型的数据和左右子树的指针。如果要拷贝一个二叉树,同样需要递归地拷贝整个二叉树。递归拷贝可以很方便地处理这种情况,代码如下:

BinaryTree* copyBinaryTree(BinaryTree* root) {if (root == nullptr) {return nullptr;}BinaryTree* newRoot = new BinaryTree(root->data);newRoot->left = copyBinaryTree(root->left);newRoot->right = copyBinaryTree(root->right);return newRoot;
}

 

上面的代码中,copyBinaryTree函数用来拷贝一个二叉树,它首先创建一个新的根节点,并将原节点的数据拷贝到新节点中。然后,它递归地调用copyBinaryTree函数来拷贝左右子树。最后,它返回新的根节点的指针。

递归拷贝是一种强大而灵活的拷贝技术,可以处理各种复杂的对象,并且可以应用于各种数据结构和数据类型。然而,递归拷贝也有一些缺点,例如可能会导致性能问题和内存泄漏。因此,在使用递归拷贝时需要注意合理使用,并确保资源的正确释放。

 

递归反转链表(Recursive Reverse Linked List)

递归反转链表是一种常见的链表操作,它通过递归的方式将链表中的节点顺序进行反转。在C++中,可以使用递归的方法来实现链表的反转,这种方法简洁而且易于理解。

在开始之前,让我们先定义一个链表的节点结构,以及一个链表的类:

struct ListNode {int val;ListNode* next;ListNode(int x) : val(x), next(NULL) {}
};class LinkedList {
public:ListNode* head;LinkedList() : head(NULL) {}void insert(int val) {ListNode* newNode = new ListNode(val);if (head == NULL) {head = newNode;} else {ListNode* curr = head;while (curr->next != NULL) {curr = curr->next;}curr->next = newNode;}}
};

 

接下来,我们可以实现递归的反转函数。该函数将使用两个指针,一个指向当前节点,另一个指向前一个节点。通过递归地反转链表的剩余部分,我们可以将当前节点的next指针指向前一个节点。

ListNode* reverse(ListNode* curr, ListNode* prev) {// 如果当前节点为空,表示链表已经反转完成if (curr == NULL) {return prev;}// 保存下一个节点的指针ListNode* nextNode = curr->next;// 将当前节点的next指针指向前一个节点curr->next = prev;// 递归地反转剩余的链表部分return reverse(nextNode, curr);
}

 

最后,我们可以在链表类中添加一个公有的逆转函数,它将把链表头节点传递给递归函数,并更新链表的头指针:

void reverseList() {head = reverse(head, NULL);
}

 

现在,我们可以通过以下示例来测试递归反转链表的功能:

int main() {LinkedList linkedList;// 在链表中插入一些节点linkedList.insert(1);linkedList.insert(2);linkedList.insert(3);linkedList.insert(4);// 打印反转前的链表ListNode* curr = linkedList.head;while (curr != NULL) {cout << curr->val << " ";curr = curr->next;}cout << endl;// 反转链表linkedList.reverseList();// 打印反转后的链表curr = linkedList.head;while (curr != NULL) {cout << curr->val << " ";curr = curr->next;}cout << endl;return 0;
}

 

运行以上代码,我们将得到以下输出:

1 2 3 4
4 3 2 1

 

可以看到,链表中的节点顺序已经被成功地反转了。

递归反转链表的时间复杂度为O(n),其中n是链表的长度。空间复杂度为O(n),因为在递归过程中,系统需要保存每个递归调用的状态。

结语

今日二更结束,睡觉。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/49714.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue大屏展示组件库datav

主要用于构建大屏数据展示页面&#xff0c;具有多种类型组件可供使用。详情参考 datav官网 一、安装 npm 安装 npm install jiaminghi/data-viewyarn安装 yarn add jiaminghi/data-view二、使用 在main.js中注册为全局组件 import dataV from jiaminghi/data-view Vue.us…

GD32 MCU电源复位和系统复位有什么区别

GD32 MCU的复位分为电源复位和系统复位&#xff0c;电源复位又称为冷复位&#xff0c;相较于系统复位&#xff0c;上电复位更彻底&#xff0c;下面为大家详细介绍上电复位和系统复位的实现以及区别。 电源复位包括上电/掉电复位或者从standby模式唤醒产生的复位&#xff0c;电…

【进阶篇-Day12:JAVA中stream流、File类的介绍】

目录 1、stream流1.1 stream流的作用1.2 stream流的思想1.3 获取stream流对象1.4 stream流中间操作方法1.5 stream流终结操作方法1.6 stream收集操作1.7 stream的综合案例 2、File类2.1 File类创建文件对象2.2 File类的常用方法2.3 File类的创建和删除方法2.4 File类的遍历方法…

埃文科技受邀出席2024年河南省工业领域网络和数据安全政策宣贯会

2024年7月18日&#xff0c;由河南省工业和信息化厅主办&#xff0c;河南省工业信息安全产业发展联盟、河南省信息安全产业协会承办的2024年河南省工业领域网络和数据安全政策宣贯会在郑州召开&#xff0c;活动旨在提升河南省工业领域网络和数据安全保护能力&#xff0c;助力企业…

Fetch请求的取消

在实际开发中&#xff0c;我们常常会遇到根据输入框输入的内容&#xff0c;实时去请求接口并将拿到的数据渲染到页面上&#xff0c;但是由于接口响应时间不可控&#xff0c;简单来说就是请求的顺序和响应的顺序不一致&#xff0c;就会导致你可能输入了12&#xff0c;但实际返回…

PMOS、NMOS 驱动电路和使用方法

下图就是 PMOS 和 NMOS 的简单使用方法。D2 是指示灯&#xff0c;NMOS 的 G 连接单片机 IO&#xff0c;PMOS 的 D 连接 24V 继电器&#xff0c;PMOS 的体二极管作为继电器的反向电动势的吸收二极管 PMOS 和 NMOS 不一样&#xff0c;在远超单片机电压下控制 PMOS 必须依靠一个 N…

CSS相关记录

文章目录 backgroundposition文字displayflexjustify-contentalign-itemsflex-directionflex-wrap gridimportant transformtranslate&#xff08;位移&#xff09;scale&#xff08;缩放&#xff09;rotate&#xff08;旋转&#xff09;origin (旋转中心点)skew (倾斜 ) borde…

C# 知识点总结

入门 C#程序在.NET上运行&#xff0c;.NET framework包含两个部分&#xff1a; ①&#xff1a;.NET framework类库 ②&#xff1a;公共语言运行库CLR&#xff08;.NET虚拟机&#xff09; CLS&#xff08;公共语言规范&#xff09; CTS&#xff08;通用类型系统&#xff09; .N…

【分布式系统】 单机架构 | 分布式架构 | 集群 | 主从架构 | 分库分表 | 冷热分离 | 微服务

文章目录 [toc] 分布式系统一、单机架构二、分布式系统三、应用服务器集群四、读写分离 / 主从分离架构五、引入缓存/冷热分离架构六、垂直分库七、微服务架构——业务拆分代价优势 八、名词解释1.应用&#xff08;Application&#xff09;/系统(System)2.模块&#xff08;Mode…

Java 项目如何快速接入AI大模型ChatGPT

Spring AI 简介 定义&#xff1a;与Spring生态系统集成的项目&#xff0c;简化在Spring应用中使用AI技术。特点&#xff1a;提供工具和接口&#xff0c;简化集成AI功能&#xff0c;避免底层细节复杂性。 Spring AI 主要功能 跨AI提供商API&#xff1a;聊天、文本到图像、嵌入…

k8s学习——安装istio之dns卡壳

我准备使用istio来替代原来的traefic网关和consul服务注册发现的方案&#xff0c;但在安装istio过程中遇到了一些问题&#xff0c;把解决的过程记录下来&#xff0c;便于今后遇到类似问题做个参考。 istio安装的中文文档地址&#xff1a;Istio Prelim 1.23 / 文档 参照Istio …

Perl中的时间机器:探索文件系统同步机制

Perl中的时间机器&#xff1a;探索文件系统同步机制 在Perl编程中&#xff0c;文件系统同步是一个重要的功能&#xff0c;它允许开发者在不同时间点对文件或目录的状态进行备份、更新和同步。Perl提供了多种内置的模块和函数&#xff0c;使得文件系统同步变得简单而高效。本文…

Mysql9安装

目录 一、下载mysql 二、安装 三、配置mysql环境变量 四、mysql初始化和启动 1.以管理员身份运行cmd 2.cd到mysql的安装目录 3.初始化mysql的数据库 4.为Windows系统安装MySQL服务 5.查看一下名为mysql的服务&#xff1a; 6.启动MySQL服务 五、附录 1.系统变量还在&…

CentOS 8中 更新或下载时报错:为仓库 ‘appstream‘ 下载元数据失败 : Cannot prepare internal mirrorlist

一、错误重现 CentOS Stream 8 - AppStream 0.0 B/s | 0 B 00:00 Errors during downloading metadata for repository appstream: - Curl error (6): Couldnt resolve host name for http://mirrorlis…

Python 之 os、open、json、pickle 模块的“疯狂”探险记

1.open函数的使用 Python 中的 open() 函数是处理文件的标准方法。它允许你打开一个文件&#xff0c;并对其进行读取、写入或追加操作 open(file,mode,encoding)函数的格式&#xff1a;file&#xff1a;文件路径 mode&#xff1a;打开方式&#xff08;读&#xff1a; r写&…

昇思25天学习打卡营第18天|生成式-GAN图像生成

打卡 目录 打卡 GAN 博弈函数 博弈过程 GAN 案例 数据集 数据加载与可视化 隐码构造 模型构建 生成器 判别器 损失函数和优化器 模型训练 输出展示-1w张训练样本 输出展示-6w张训练样本 输出展示-6w张-100 epoch 效果展示 部分展示如图-12epoch-6w张 部分展…

Windows系统上Git详细图文安装及使用教程

Git 是一种高效、分布式的版本控制系统&#xff0c;用于代码的跟踪、分支管理和协同工作&#xff0c;支持快速提交、合并和回滚操作。它是开发者工具箱中必不可少的工具之一&#xff0c;广泛应用于软件开发和其他需要版本控制的领域。 1. Git的安装 1.1 Git下载 可以通过以下…

WEB渗透信息收集篇--IP和端口信息

WEB渗透信息收集篇--域名信息-CSDN博客 WEB渗透信息收集篇--网站架构和指纹识别-CSDN博客 ​​​​​​​​​​​​​​WEB渗透信息收集篇--人员信息-CSDN博客​​​​​​​ WEB渗透信息收集篇--其他信息-CSDN博客 一、ASN ASN Tool - MxToolBox ASN通常指的是"自…

Qt SQLite数据库学习总结

到此为止&#xff0c;就使用Qt进行SQLite数据库的操作&#xff0c;做一次总结 1. Qt中数据库操作的相关概念和类 Qt 数据库编程相关基本概念https://blog.csdn.net/castlooo/article/details/140497177 2.表的只读查询--QSqlQueryModel QSqlQueryModel单表查询的使用总结htt…

JDK、JRE、JVM之间的关系

JDK是Java的开发环境&#xff0c;用JDK开发了JAVA程序后&#xff0c;通过JDK中的编译程序&#xff08;javac&#xff09;将java文件编译成字节码文件&#xff0c;作为运行环境的JRE&#xff0c;字节码文件在JRE上运行&#xff0c;作为虚拟机的JVM解析这些字节码&#xff0c;映射…