【数据结构】树与二叉树(十三):递归复制二叉树(算法CopyTree)

news2024/11/16 3:30:56

文章目录

5.2.1 二叉树

  二叉树是一种常见的树状数据结构,它由结点的有限集合组成。一个二叉树要么是空集,被称为空二叉树,要么由一个根结点和两棵不相交的子树组成,分别称为左子树右子树。每个结点最多有两个子结点,分别称为左子结点和右子结点。
在这里插入图片描述

二叉树性质

引理5.1:二叉树中层数为i的结点至多有 2 i 2^i 2i个,其中 i ≥ 0 i \geq 0 i0

引理5.2:高度为k的二叉树中至多有 2 k + 1 − 1 2^{k+1}-1 2k+11个结点,其中 k ≥ 0 k \geq 0 k0

引理5.3:设T是由n个结点构成的二叉树,其中叶结点个数为 n 0 n_0 n0,度数为2的结点个数为 n 2 n_2 n2,则有 n 0 = n 2 + 1 n_0 = n_2 + 1 n0=n2+1

  • 详细证明过程见前文:【数据结构】树与二叉树(三):二叉树的定义、特点、性质及相关证明

满二叉树、完全二叉树定义、特点及相关证明

  • 详细证明过程见前文:【数据结构】树与二叉树(四):满二叉树、完全二叉树及其性质

5.2.2 二叉树顺序存储

  二叉树的顺序存储是指将二叉树中所有结点按层次顺序存放在一块地址连续的存储空间中,详见:
【数据结构】树与二叉树(五):二叉树的顺序存储(初始化,插入结点,获取父节点、左右子节点等)

5.2.3 二叉树链接存储

  二叉树的链接存储系指二叉树诸结点被随机存放在内存空间中,结点之间的关系用指针说明。在链式存储中,每个二叉树结点都包含三个域:数据域(Data)、左指针域(Left)和右指针域(Right),用于存储结点的信息和指向子结点的指针,详见:
【数据结构】树与二叉树(六):二叉树的链式存储

5.2.4 二叉树的遍历

  • 遍历(Traversal)是对二叉树中所有节点按照一定顺序进行访问的过程。
  • 通过遍历,可以访问树中的每个节点,并按照特定的顺序对它们进行处理。
  • 对二叉树的一次完整遍历,可给出树中结点的一种线性排序。
    • 在二叉树中,常用的遍历方式有三种:先序遍历中序遍历后序遍历
    • 这三种遍历方式都可以递归地进行,它们的区别在于节点的访问顺序
      • 在实现遍历算法时,需要考虑递归终止条件和递归调用的顺序。
    • 还可以使用迭代的方式来实现遍历算法,使用栈或队列等数据结构来辅助实现。
  • 遍历是二叉树中基础而重要的操作,它为其他许多操作提供了基础,如搜索、插入、删除等。
    在这里插入图片描述

1-3 先序、中序、后序遍历递归实现及相关练习

【数据结构】树与二叉树(七):二叉树的遍历(先序、中序、后序及其C语言实现)

4. 中序遍历非递归

【数据结构】树与二叉树(八):二叉树的中序遍历(非递归算法NIO)

5. 后序遍历非递归

【数据结构】树与二叉树(九):二叉树的后序遍历(非递归算法NPO)

6. 先序遍历非递归

【数据结构】树与二叉树(十):二叉树的先序遍历(非递归算法NPO)

7. 层次遍历

【数据结构】树与二叉树(十一):二叉树的层次遍历(算法LevelOrder)

5.2.5 二叉树的创建

  • 先序遍历
    • a b d e f g c
  • 中序遍历
    • d b f e g a c
  • 后序遍历
    • d f g e b c a
  • 层次遍历
    • a b c d e f g

先序创建

  由二叉树的遍历,很容易想到用遍历方法去创建二叉树,我们考虑从先根遍历思想出发来构造二叉树。
  方法:输入当前被创建结点的数据域的值,如果不空,申请空间用指针指向,然后对数据域进行赋值,再递归对该结点的左右指针域进行赋值,这就是先根创建过程。当输入为空,则算法返回一个空指针(即空树。递归出口)。
【数据结构】树与二叉树(十二):二叉树的递归创建(算法CBT)

复制二叉树

  考虑用后根遍历思想递归复制二叉树的算法CopyTree
在这里插入图片描述

a. 算法CopyTree

![在这里插入图片

b. 时间复杂度

  设二叉树有n个结点,算法CopyTree中,每个结点都要进行1次复制,即复制操作要执行n次,每次复制都是常数级的操作,因此算法CopyTree的时间复杂度为O(n)。

c. 代码实现

struct Node* CopyTree(struct Node* t) {
    if (t == NULL) {
        return NULL;
    }

    struct Node* p = createNode('\0');  // 创建新结点
    struct Node* newlptr = NULL;  // 初始化左指针
    struct Node* newrptr = NULL;  // 初始化右指针

    // 复制左子树
    if (t->left != NULL) {
        newlptr = CopyTree(t->left);
    }

    // 复制右子树
    if (t->right != NULL) {
        newrptr = CopyTree(t->right);
    }

    // 复制数据和指针
    p->data = t->data;
    p->left = newlptr;
    p->right = newrptr;

    return p;
}

代码整合

#include <stdio.h>
#include <stdlib.h>

// 二叉树结点的定义
struct Node {
    char data;
    struct Node* left;
    struct Node* right;
};

// 创建新结点
struct Node* createNode(char data) {
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    if (newNode == NULL) {
        printf("Memory allocation failed!\n");
        exit(1);
    }
    newNode->data = data;
    newNode->left = NULL;
    newNode->right = NULL;
    return newNode;
}

// 复制二叉树
struct Node* CopyTree(struct Node* t) {
    if (t == NULL) {
        return NULL;
    }

    struct Node* p = createNode('\0');  // 创建新结点
    struct Node* newlptr = NULL;  // 初始化左指针
    struct Node* newrptr = NULL;  // 初始化右指针

    // 复制左子树
    if (t->left != NULL) {
        newlptr = CopyTree(t->left);
    }

    // 复制右子树
    if (t->right != NULL) {
        newrptr = CopyTree(t->right);
    }

    // 复制数据和指针
    p->data = t->data;
    p->left = newlptr;
    p->right = newrptr;

    return p;
}

// 中序遍历二叉树
void inorderTraversal(struct Node* root) {
    if (root != NULL) {
        inorderTraversal(root->left);
        printf("%c ", root->data);
        inorderTraversal(root->right);
    }
}
struct Node* CBT(char data[], int* index, char tostop) {
    char ch = data[(*index)++];
    if (ch == tostop) {
        return NULL;
    } else {
        struct Node* t = createNode(ch);
        t->left = CBT(data, index, tostop);
        t->right = CBT(data, index, tostop);
        return t;
    }
}

int main() {
    // 创建一棵二叉树
    char tostop = '#';
    char input_data[] = {'a', 'b', 'd', '#', '#', 'e', 'f', '#', '#', 'g', '#', '#', 'c', '#', '#'};
    int index = 0;

    struct Node* original = CBT(input_data, &index, tostop);

    // 复制二叉树
    struct Node* copy = CopyTree(original);

    // 中序遍历并输出原始二叉树
    printf("Original Inorder Traversal: ");
    inorderTraversal(original);
    printf("\n");

    // 中序遍历并输出复制后的二叉树
    printf("  Copied Inorder Traversal: ");
    inorderTraversal(copy);
    printf("\n");

    return 0;
}

在这里插入图片描述

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

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

相关文章

【Spring Boot 源码学习】初识 SpringApplication

Spring Boot 源码学习系列 初识 SpringApplication 引言往期内容主要内容1. Spring Boot 应用程序的启动2. SpringApplication 的实例化2.1 构造方法参数2.2 Web 应用类型推断2.3 加载 BootstrapRegistryInitializer2.4 加载 ApplicationContextInitializer2.5 加载 Applicatio…

解决删除QT后Qt VS Tools中Qt Options中未删除的错误

在Qt VS Tools的Qt Options已经配置好Qt Versions后如果删除QT程序之后会出现Default Qt/Win version任然存在&#xff0c;这是如果再添加一个话就不能出现重名了&#xff0c;如果新建一个其他名字的话其实在vs中还是不能正常运行qt&#xff0c;会出现点击ui文件vs会无故重启或…

RK3568平台开发系列讲解(Linux系统篇)Linux 目录结构

🚀返回专栏总目录 文章目录 一、VFS二、分区结构三、挂载 mount四、目录结构沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇我们从目录管理入手,会更直观的理解 linux 的目录结构。 一、VFS Linux 所有的文件都建立在虚拟文件系统(Virtual File System ,VFS…

Please No More Sigma(构造矩阵)

Please No More Sigma 给f(n)定义如下&#xff1a; f(n)1 n1,2; f(n)f(n-1)f(n-2) n>2; 给定n&#xff0c;求下式模1e97后的值 Input 第一行一个数字T&#xff0c;表示样例数 以下有T行&#xff0c;每行一个数&#xff0c;表示n。 保证T<100&#xff0c;n<100000…

Linux yum,vim详解

yum是什么 yum是一个Linux系统预装的指令&#xff0c;yum的功能是可以对app进行搜索&#xff0c;下载&#xff0c;相当于Linux下的应用商店。 yum是读取Linux中镜像文件中的网页地址&#xff0c;下载用户所输入的命令。 如何使用yum下载软件 yum install -y(所有选项都yes) …

MyBatis研究

入门级使用 参照MyBatis官网的简介与入门部分&#xff0c;尝试使用MyBatis&#xff0c;可创建新的Maven项目&#xff0c;引入以下依赖&#xff1a; <dependencies> <dependency><groupId>org.mybatis</groupId><artifactId>mybatis</…

Java15新增特性

前言 前面的文章&#xff0c;我们对Java9、Java10、Java11、Java12 、Java13、Java14 的特性进行了介绍&#xff0c;对应的文章如下 Java9新增特性 Java10新增特性 Java11新增特性 Java12新增特性 Java13新增特性 Java14新增特性 今天我们来一起看一下Java15这个版本的一些重要…

交叉编译 openssl

要在 x86 平台上编译适用于 aarch64 架构的 OpenSSL 动态库&#xff0c;你需要使用交叉编译工具链。可以按照以下步骤进行&#xff1a; 安装 aarch64 交叉编译工具链&#xff1a; $ sudo apt-get install gcc-aarch64-linux-gnu g-aarch64-linux-gnu 这将安装 aarch64 交叉编…

74HC165 并入串出

/******************************************************** 程序名&#xff1a;main.C 版 本&#xff1a;Ver1.0 芯 片&#xff1a;AT89C51或STC89C51 晶 体&#xff1a;片外12MHz 编 程: Joey 日 期&#xff1a;2023-11-13 描 述&#xff1a;通过 74HC165 对 16 按键…

登顶request模块

华子目录 Requests介绍安装requests模块常用方法常用属性实例引入各种请求方式基于get请求带参数的get请求推荐写法 基于post请求添加headers信息content获取二进制数据bytes类型获取json数据第一种方式第二种方式 response响应状态码判断 高级操作会话维持通过cookie维持会话通…

初探地理编码(2023.11.12)

地理编码相识 2023.11.12 引言1、地理编码简介2、地理编码API和服务&#xff08;解决方案供应商 / 厂商&#xff09;2.1 高德2.2 百度2.3 超图2.4 天地图2.5 ArcGIS2.6 MapBox2.7 Cesium2.8 MapLocation 3、python实例3.1 pip安装依赖库&#xff08;python 3.6&#xff09;3.2 …

11/12总结

项目进度&#xff1a; 界面画了搜索机票&#xff0c;预定机票&#xff0c;搜索酒店&#xff0c;预定酒店&#xff0c; 然后是开始写这些功能的后端逻辑

基于springboot实现沁园健身房预约管理系统【项目源码】

基于springboot实现沁园健身房预约管理系统演示 B/S架构 B/S结构是目前使用最多的结构模式&#xff0c;它可以使得系统的开发更加的简单&#xff0c;好操作&#xff0c;而且还可以对其进行维护。使用该结构时只需要在计算机中安装数据库&#xff0c;和一些很常用的浏览器就可以…

android 10车载桌面ActivityView触摸事件源码详解分析

hi&#xff0c;粉丝朋友们&#xff1a; 背景 大家好&#xff01;近来居然有好几个粉丝朋友居然问到了一个虚拟屏幕触摸相关的问题&#xff0c;还有老版本android 10上面有个车载桌面使用的ActivityView可以正常触摸的问题。 其实这个ActivityView在最新的版本已经没有了&…

04-详解SpringBoot自动装配的原理,依赖属性配置的实现,源码分析

自动装配原理 依赖属性配置 提供Bean用来封装配置文件中对应属性的值 Data public class Cat {private String name;private Integer age; }Data public class Mouse {private String name;private Integer age; }cartoon:cat:name: "图多盖洛"age: 5mouse:name: …

11.12总结

这一周主要写了个人中心的几个功能&#xff0c;资料修改&#xff0c;收货地址的创建和修改删除&#xff0c;还有主页界面和商品界面

ZYNQ_project:ram_dual_port

伪双端口ram&#xff1a;写端口&#xff1a;clk_w,en_A,we_A,addr_A,din_A;读端口:clk_r,en_B,addr_B;dout_B. 设计读写模块&#xff0c;写入256个数据&#xff0c;再读出256个数据。 输入时钟100Mhz&#xff0c;输出时钟50Mhz。 多bit数据&#xff0c;高速时钟域到低速时钟…

Excel中使用数据验证、OFFSET实现自动更新式下拉选项

在excel工作簿中&#xff0c;有两个Sheet工作表。 Sheet1&#xff1a; Sheet2&#xff08;数据源表&#xff09;&#xff1a; 要实现Sheet1中的“班级”内容&#xff0c;从数据源Sheet2中获取并形成下拉选项&#xff0c;且Sheet2中“班级”内容更新后&#xff0c;Sheet1中“班…

小黑子—springMVC:第二章

springMVC入门2.0 4、小黑子的springMVC拦截器4.1 Interceptor简介4.2 拦截器快速入门4.3 拦截器执行顺序4.4 拦截器执行原理 5、小黑子的springMVC全注解开发5.1 spring-mvc.xml中组件转化为注解形式5.1.1 消除spring-mvc.xml一二三 5.1.2 消除web.xml 6、小黑子的springMVC组…

SpringBoot之手写starter

SpringBoot之手写starter 在开始之前呢&#xff0c;我们需要了解一些概念 1、starter介绍 spring boot 在配置上相比spring要简单许多, 其核心在于spring-boot-starter, 在使用spring boot来搭建一个项目时, 只需要引入官方提供的starter, 就可以直接使用, 免去了各种配置。…