【数据结构7-2】-二叉排序树(建立、遍历、查找、增加、删除)

目录

  • 1 基础说明
  • 2 基本思路-二叉树的创建和插入
    • 2.1 节点存储结构的建立
    • 2.2 二叉树创建函数的设计
    • 2.3 二叉树插入函数的设计
    • 2.4 简单的进行二叉树的检测看看插入的对不对:
    • 2.5 整体代码:
  • 3 二叉树的遍历
    • 3.1 中序遍历
    • 3.2 程序代码:
    • 3.3 程序结果:
  • 4 二叉树的查找
    • 4.1 改进中序递归查找
    • 4.2 程序结果
  • 5 二叉树节点中序增加

主要是进行代码的书写,原理部分不过多介绍,原理部分应该是优先掌握的,不会原理写代码事倍功半,知道了原理再去理解程序事半功倍

1 基础说明

  在进行二叉树的建立、查找和修改时,要具备一些基本的知识。

  • 首先对于结构体要熟悉,知道结构体的定义和使用,以及结构体常用的别名的使用
  • 其次就是对malloc函数比较熟悉,能熟练的使用malloc进行动态数组的建立
  • 然后就是最重要的就是对链表要很熟悉,至少单链表要能进行建立和查找,删除
  • 然后就是要对二叉树要熟悉,如果二叉树是什么都不知道,怎么进行建立?,要知道其原理,其次要知道二叉树的遍历的三种方式,一般就是有先序、中序、后序,这些遍历的原理至少要掌握
  • 最后就是二叉树的建立要用到一个比较重要的知识点就是递归,其中插入节点要用到地址的递归回溯过程,其他的就跟单链表建立差不多的;

2 基本思路-二叉树的创建和插入

2.1 节点存储结构的建立

  有了上面的基础后,其实内心对于二叉树的建立应该有了一个大致的轮廓,不至于一窍不通,肯定要进行数据的输入,那么就要创建一个能存储数据的结构体:如下

// 创建树的节点结构体
typedef struct tree
{int data;struct tree *Lchildren;struct tree *Rchildren;/* data */
} BinTree;

2.2 二叉树创建函数的设计

  有了能存储的结构体,那么下一步就是要创建二叉树,可以分为两个大步骤,第一个就是二叉树的建立,第二个就是进行而叉树的建立;
  第一步进行二叉树的创建函数的设计:这里,先不管插入函数,就先认为已经把插入的功能实现了,进行创建一个二叉树要有一个根节点,这里选用手动进行数据的输入,还要定义一个key,因此每次输入一个数据就要用malloc动态的申请一个节点,(由于这个节点是由malloc函数申请的,数据是放在了堆上,因此这个函数调用完毕,数据也不会清空),并对这个节点进行初始化,然后进行插入,最后执行完这个函数只需要把根节点给返回就行,因此创建函数可以定义为指针函数;

BinTree *CreatNode()
{int key;BinTree *NewNode;BinTree *root = NULL; // 二叉树的根节点,会作为地址返回给主函数// 二叉树的根节点,必须设置为空,不然第一次进行插入时,无法正确的插入while (1){scanf("%d", &key);if (key != -1) // 如果key为-1就停止{NewNode = (BinTree *)malloc(sizeof(BinTree));NewNode->data = key;NewNode->Lchildren = NULL;NewNode->Rchildren = NULL;root = InsertTree(root, NewNode); // 调用插入函数}else{break;}}return root;
}

2.3 二叉树插入函数的设计

  可以简单考虑一下,对于插入函数要有根节点和新节点的地址,这样方便进行插入,而且每次插入完毕可以把根节点地址给返回回来,这里假设中序插入,思考一下树的定义,以及如何能在我插入完新节点后,地址能一层一层的返回,也就是地址回溯,这样我就递归的寻找到顶点,到顶点后,再依次进行地址回溯,这样就能完成新节点的插入,而对于是中序插入,还是先序插入,完全取决于你写的顺序;插入函数如下:

// 插入函数,递归调用,root是根地址,但是随着递归的调用
//  地址在进行回溯
BinTree *InsertTree(BinTree *root, BinTree *newnode)
{if (root == NULL) // 递归的终止条件,终止后把新节点的地址传给上一层,// 上一层继续执行下面的函数(条件都不满足实际上就是直接跳到了return)// ,并把地址传给上上一层,以此类推进行地址的回溯{root = newnode;}else{if (root->data > newnode->data){root->Lchildren = InsertTree(root->Lchildren, newnode);// 这一点比较难以理解// 要理解回溯的思想}if (root->data < newnode->data){root->Rchildren = InsertTree(root->Rchildren, newnode);}}return root;
}

2.4 简单的进行二叉树的检测看看插入的对不对:

  例如插入 7 4 5;如下图:

int main()
{BinTree *root;root = CreatNode();return 0;
}

  输入和打印结果:

2.5 整体代码:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>// 创建树的节点结构体
typedef struct tree
{int data;struct tree *Lchildren;struct tree *Rchildren;/* data */
} BinTree;// 插入函数,按照中序插入
BinTree *InsertTree(BinTree *root, BinTree *newnode);
// 二叉树的创建函数
BinTree *CreatNode();BinTree *CreatNode()
{int key;BinTree *NewNode;BinTree *root = NULL; // 二叉树的根节点,会作为地址返回给主函数// 二叉树的根节点,必须设置为空,不然第一次进行插入时,无法正确的插入while (1){scanf("%d", &key);if (key != -1) // 如果key为-1就停止{NewNode = (BinTree *)malloc(sizeof(BinTree));NewNode->data = key;NewNode->Lchildren = NULL;NewNode->Rchildren = NULL;root = InsertTree(root, NewNode); // 调用插入函数}else{break;}}return root;
}
// 插入函数,递归调用,root是根地址,但是随着递归的调用
//  地址在进行回溯
BinTree *InsertTree(BinTree *root, BinTree *newnode)
{if (root == NULL) // 递归的终止条件,终止后把新节点的地址传给上一层,// 上一层继续执行下面的函数(条件都不满足实际上就是直接跳到了return)// 并把地址传给上上一层,以此类推进行地址的回溯{root = newnode;}else{if (root->data > newnode->data){root->Lchildren = InsertTree(root->Lchildren, newnode);// 这一点比较难以理解// 要理解递归的思想}if (root->data < newnode->data){root->Rchildren = InsertTree(root->Rchildren, newnode);}}return root;// 要理解回溯的思想
}
int main()
{BinTree *root;root = CreatNode();printf("%d,%d,%d", root->data, (root->Lchildren)->data, ((root->Lchildren)->Rchildren)->data);return 0;
}

3 二叉树的遍历

3.1 中序遍历

  继续对上述的代码进行补充,即进行中序遍历输出:中序这里采用递归的方法,其实对于先序和中序,后序都可以采用递归的方法,同时也可以采用堆栈的的方法进行遍历,但是这里就先利用递归的方法进行编写:递归中难以理解就是函数的运行过程,具体理解可以参考下图,其中紫色的箭头就是其程序的运行过程: 尤其注意的是到顶点后不会立刻返回上一个节点,而是会进行两次判断后再次进入上一个顶点:

3.2 程序代码:

// 中序递归遍历,可以这个比较难以理解
void InOrder(BinTree *root)
{if (root == NULL){return;}InOrder(root->Lchildren);printf("%d,", root->data);InOrder(root->Rchildren);
}
int main()
{BinTree *root, *find;int key;root = CreatNode();printf("%d,%d,%d", root->data, (root->Lchildren)->data, ((root->Lchildren)->Rchildren)->data);InOrder(root);//中序遍历return 0;
}

3.3 程序结果:

4 二叉树的查找

  上面已经得到二叉树的中序遍历,那么接下来就是对元素进行查找,其中查找可以把中序的函数修改一下,让其每次与目标值的比较,如果掌握了前面的内容,那么查找函数就是比较好写的:

4.1 改进中序递归查找

  由中序遍历改进而来,其他保持不变

// 改进 中序递归查找
BinTree *InOrderSerach(BinTree *root, int val)
{if (root == NULL){return NULL;}BinTree *Find = InOrderSerach(root->Lchildren, val);if (Find != NULL){return Find; // 如果找了值就一直递归返回,直到返回原函数,后面递归就不执行了}if (root->data == val){return root;}Find = InOrderSerach(root->Rchildren, val);return Find; // 这个不能删除,作为最后,同时返回右子树为空的情况函数的返回值
}
int main()
{BinTree *root, *find;int key;root = CreatNode();InOrder(root);printf("\n");while (1){if (key != -1)//key==-1结束{scanf("%d", &key);find = InOrderSerach(root, key);printf("\nYES:%d\n", find->data);}else{break;}}return 0;
}

4.2 程序结果

5 二叉树节点中序增加

  到目前为止,我们从一个结构体起步,进行了了二叉树的建立,中序遍历,中序递归查找,那么接下来就是增删的内容了,上面的内容可以保持不变;简单想一下,对于二叉树的增加,首先就是要用到插入函数,其次就是左右子树的指针指向要改变一下,弄完后要一直递归返回就行了,剩下的不用管了;
  所以主线就是,先找到插入的位置,然后改变指针指向,最后一直return返回就行了;剩下待补充…

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

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

相关文章

网络安全之文件上传漏洞(上篇)(技术进阶)

目录 一&#xff0c;什么是文件上传漏洞&#xff1f;文件上传漏洞会造成什么危害&#xff1f; 二&#xff0c;文件上传靶场upload-labs闯关 Pass-01 Pass-02 Pass-03 Pass-04 Pass-05 Pass-06 Pass-07 ​Pass-08 Pass-09 Pass-10 总结 一&#xff0c;什么是文件上传漏洞&…

基于Ubuntu-base构建根文件系统

Ubuntu是一个非常常见的发行版系统&#xff0c;具有丰富的软件功能&#xff0c;可以方便的进行各类开发&#xff0c;系统的apt工具更是搭建各种开发环境的神器。当我们在基于X86的电脑Ubuntu完成功能开发后&#xff0c;想要将功能移植到arm板上&#xff0c;使用Ubuntu可以大大节…

Python实现自动化的服务器部署和配置管理库之pyinfra使用详解

概要 在现代软件开发中,自动化部署和配置管理变得越来越重要。Python pyinfra库是一个强大的工具,可以帮助开发者实现自动化的服务器部署和配置管理。本文将介绍pyinfra库的安装、特性、基本功能、高级功能、实际应用场景以及总结。 安装 首先,来看一下如何安装pyinfra库。…

线上剧本杀小程序:创新玩法下带来的市场活力

近几年来&#xff0c;剧本杀作为一种新型的游戏娱乐模式&#xff0c;深受年轻人的喜欢&#xff0c;成为了当下年轻人娱乐休闲的主要方式之一。剧本杀行业在经历过一段时间的“野蛮生长”后&#xff0c;游戏内容和服务得到的升级发展&#xff0c;游戏的趣味性和体验感也逐渐增强…

线性代数 --- 计算斐波那契数列第n项的快速算法(矩阵的n次幂)

计算斐波那契数列第n项的快速算法(矩阵的n次幂) The n-th term of Fibonacci Numbers&#xff1a; 斐波那契数列的是一个古老而又经典的数学数列&#xff0c;距今已经有800多年了。关于斐波那契数列的计算方法不难&#xff0c;只是当我们希望快速求出其数列中的第100&#xff0…

电影交流|基于SprinBoot+vue的电影交流平台小程序系统(源码+数据库+文档)

电影交流平台目录 目录 基于SprinBootvue的电影交流平台小程序系统 一、前言 二、系统设计 三、系统功能设计 1用户信息管理 2 电影信息管理 3公告信息管理 4论坛信息管理 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取…

笔记:编写程序,绘制一个展示 2013~2019 财年阿里巴 巴淘宝+天猫平台的 GMV 的柱形图,实现过程如下:

文章目录 前言一、GMV 的柱形图是什么&#xff1f;二、编写代码总结 前言 编写程序。根据实例 2 的要求&#xff0c;绘制一个展示 2013~2019 财年阿里巴 巴淘宝天猫平台的 GMV 的柱形图&#xff0c;实现过程如下&#xff1a; &#xff08;1&#xff09; 导入 matplotlib.pypl…

LMDeploy高效部署Llama-3-8B,1.8倍vLLM推理效率

Llama 3 近期重磅发布&#xff0c;发布了 8B 和 70B 参数量的模型&#xff0c;LMDeploy 对 Llama 3 部署进行了光速支持&#xff0c;同时对 LMDeploy 推理 Llama 3 进行了测试&#xff0c;在公平比较的条件下推理效率是 vLLM 的 1.8 倍。 书生浦语和机智流社区同学光速投稿了 L…

全志ARM-修改开发板内核启动日志

修改开发板内核日志输出级别&#xff1a; 默认输出级别为1&#xff0c;需要用超级用户权限修改 sudo vi /boot/orangepiEvn.txt 把第一行内核启动输出权限改为7&#xff0c;第二行把输出方式该为“serial”串口输出

TCP关闭连接时的一些思考

TCP协议是TCP/IP栈中最复杂的协议&#xff0c;它最大的优点是传输的可靠性&#xff0c;这通过面向连接、按序传输、超时重传、流量控制等机制保证其传输的可靠性。但这并不是我们今天要讨论的重点&#xff01; TCP通信的过程分别是三个阶段&#xff1a;建立连接、传输数据、关…

科蓝尔环保 | 成都2024全国水科技大会暨技术装备成果展览会

2024年5月13日一15日中华环保联合会、福州大学、上海大学在四川省成都市联合举办“2024全国水科技大会暨技术装备成果展览会”。 大会主题&#xff1a;加快形成新质生产力 增强水业发展新动能 大会亮点&#xff1a;邀请6位院士&#xff0c;100余位行业专家&#xff0c;15场专…

Spark 基础

/* Why Spark一、MapReduce编程模型的局限性1、繁杂&#xff1a;只有Map和Reduce两个操作&#xff0c;复杂的逻辑需要大量的样板代码2、处理效率低&#xff1a;2.1、Map中间结果写磁盘&#xff0c;Reduce写HDFS&#xff0c;多个Map通过HDFS交换数据2.2、任务调度与启动开销大3、…