二叉排序树(二叉查找树)
二叉排序树(二叉查找树)的性质:
- 若它的左子树不为空,则左子树上所有结点的值均小于它的根结点的值。
- 若它的右子树不为空,则右子树上所有结点的值均大于它的根将诶点的值。
- 它的左、右子树也分别为二叉排序树。
对二叉排序树进行中序遍历时,变可得到一个有序的序列。
构建二叉排序树不是为了排序,而是为了查找,也有利于插入和删除的实现。
代码
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>typedef struct Node
{int data;struct Node *left, *right;
} Node;// returns true on success with ret set to found node.
// returns false on failure with ret set to last accessed node.
// parent passed is NULL at the first call.
bool
search_v2 (Node *tree, int key, Node *parent, Node **ret)
{if (tree == NULL){*ret = parent;return false;}if (key == tree->data){*ret = tree;return true;}else if (key < tree->data)return search_v2 (tree->left, key, tree, ret);elsereturn search_v2 (tree->right, key, tree, ret);}// Returns pointer to the searched node on success, or 0 on failure.
Node *
search (Node *tree, int key)
{if (tree == NULL)return NULL;if (key == tree->data)return tree;else if (key < tree->data)return search (tree->left, key);//search at left childelsereturn search (tree->right, key);//search at right child
}bool
insert_node (Node **ptree, int key)
{Node *result, *new_node;if (search_v2 (*ptree, key, NULL, &result) == false) //not found{new_node = malloc (sizeof (Node));*new_node = (Node){.data = key,.left = NULL,.right = NULL};if (result == NULL)*ptree = new_node; // insert as new rootelse if (key < result->data)result->left = new_node; //insert as lchildelseresult->right = new_node; //insert as rchildreturn true;}elsereturn false;//there is already such value, refuses to insert.
}bool
delete_node_impl (Node **ptree)
{Node *prev;if ( (*ptree)->right == NULL) //if right is NULL, reset it to its left child{prev = *ptree;*ptree = (*ptree)->left;free (prev);}else if ( (*ptree)->left == NULL) //if left is NULL, reset it to its right{prev = *ptree;*ptree = (*ptree)->right;free (prev);}else//both left and right are not NULL{prev = *ptree;Node *s = (*ptree)->left;while (s->right != NULL) //turn left, then turn to right for ever{prev = s;s = s->right;}//找到了左子树中的最大结点(直接前驱),这意味者它的right为NULL。(*ptree)->data = s->data;//s points to the direct predecessor of deleted nodeif (prev != *ptree) //如果直接前驱的父结点 != 被删除的treeprev->right = s->left; //reset right tree of prevelse //否则,说明tree的左子树没有右子树,直接替换左子树即可。prev->left = s->left; //reset left tree of prevfree (s);//释放被删除的结点——直接前驱。}return true;
}bool
delete_node (Node **ptree, int key)
{if (ptree == NULL)return false;else{if (key == (*ptree)->data)return delete_node_impl (ptree);else if (key < (*ptree)->data)return delete_node (& (*ptree)->left, key);elsereturn delete_node (& (*ptree)->right, key);}
}void
traverse_LDR (Node *tree)
{if (tree == NULL)return;traverse_LDR (tree->left);printf ("%d\n", tree->data);traverse_LDR (tree->right);
}int main (void)
{Node *tree = NULL;insert_node (&tree, 100);insert_node (&tree, 101);insert_node (&tree, 102);insert_node (&tree, 103);insert_node (&tree, 104);traverse_LDR (tree);}
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>typedef struct Node
{int data;struct Node *left;struct Node *right;
} Node;Node *
create_tree()
{return NULL;
}enum search_result
{NOT_FOUND,};// 成功返回true,同时ret保留找到的结点。
// 失败返回false,同时ret保留最后一个结点(用于插入)。
// parent是辅助参数,第一次传入时应为NULL
bool
search_v2 (Node *tree, int key, Node *parent, Node **result)
{if (tree == NULL){*result = parent;return false;}if (tree->data == key){*result = tree;return true;}if (key < tree->data)return search_v2 (tree->left, key, tree, result);elsereturn search_v2 (tree->right, key, tree, result);
}Node *
search (Node *tree, int key)
{Node *result;if (search_v2 (tree, key, NULL, &result))return result;return NULL;
}bool
insert_node (Node **ptree, int key)
{Node *result;if (search_v2 (*ptree, key, NULL, &result) == false){Node *new_node = malloc (sizeof (Node));*new_node = (Node){.data = key,.left = NULL,.right = NULL};if (result == NULL) //说明树为空,插入为根结点*ptree = new_node;else if (key < result->data)result->left = new_node;elseresult->right = new_node;return true;}elsereturn false;// 已经存在相同值,插入失败
}bool
delete_node_impl (Node **ptree)
{Node *prev;if ( (*ptree)->right == NULL) // 只有左子树,重设左子树即可{prev = *ptree;*ptree = (*ptree)->left;free (prev);}else if ( (*ptree)->left == NULL) //只 有右子树,重设右子树即可{prev = *ptree;*ptree = (*ptree)->right;free (prev);}else// 都不为空{prev = *ptree;Node *predecessor = (*ptree)->left;while (predecessor->right != NULL){prev = predecessor;predecessor = predecessor->right;}(*ptree)->data = predecessor->data;if (*ptree != prev)prev->right = predecessor->left;else(*ptree)->left = predecessor->left;}return true;
}bool
delete_node (Node **ptree, int key)
{if (*ptree == NULL)return false;else{if ( (*ptree)->data == key)return delete_node_impl (ptree);else if (key < (*ptree)->data)return delete_node (& (*ptree)->left, key);elsereturn delete_node (& (*ptree)->right, key);}
}void
traverse_LDR (Node *tree)
{if (tree == NULL)return;traverse_LDR (tree->left);printf ("%d\n", tree->data);traverse_LDR (tree->right);
}int main (void)
{Node *tree = NULL;insert_node (&tree, 100);insert_node (&tree, 101);insert_node (&tree, 102);insert_node (&tree, 103);insert_node (&tree, 104);delete_node (&tree, 100);delete_node (&tree, 101);delete_node (&tree, 102);delete_node (&tree, 103);delete_node (&tree, 104);traverse_LDR (tree);}
经测试没有内存泄露。
参考书籍:大话数据结构
相关文章:
二叉排序树(二叉查找树)
二叉排序树(二叉查找树)的性质: 若它的左子树不为空,则左子树上所有结点的值均小于它的根结点的值。若它的右子树不为空,则右子树上所有结点的值均大于它的根将诶点的值。它的左、右子树也分别为二叉排序树。 对二叉…...
Python简单应用VII
题目 编程实现下述各题。 1.使用异常处理结构捕获多种可能的异常,如列表下标索引越界异常(IndexError)、试 图访问一个系统对象没有的属性所发生的异常(AttributeError)、读一个文件但该文件不存在。 2. 新建并打开文件stud1.txt,如果文件已存在就提示“…...
mysql--InnoDB存储引擎--架构和事务
MySQL进阶篇 文章目录 架构1、逻辑结构InnoDB 逻辑存储单元主层级关系图:1、表空间2、段3、区4、页5、行总结: 2、架构2、1 内存架构2、2 磁盘架构 3、事务3、1事务基础(1)事务(2)特性 架构 1、逻辑结构 I…...
0基础学习VR全景平台篇 第79篇:全景相机-泰科易如何直播推流
泰科易科技是中国的一家研发全景相机的高科技公司,前不久,在2020世界VR产业大会上发布了新一代5G VR直播影像采集终端--360starlight。以其出色的夜景成像效果和一“部”到位的直播方案重新定义了VR慢直播相机,对行业具有高度借鉴意义。 本文…...
代码调试4:实现退化模型的训练
代码调试:实现退化模型的训练 作者:安静到无声 个人主页 目录 代码调试:实现退化模型的训练问题1:如何在coco原始编码的基础上修改原始的文件?**方法1**:修改生成的文件**方法2**:直接修改源文件`instances_train2014.json`和`instances_val2014.json`问题2:构建退化后…...
8.7工作总结
一、我们想自定义一个titileBar出现如下这种情况,发现他原来的titileBar还未隐藏。 后来我尝试修改主题使得他没有主题noActionBar发现也不行,后来我参考原先我看过的项目使用了如下代码 this.getActionBar().hide();发现会报这个错误java.lang.NullPoi…...
数据库的约束 详解
一、约束的概述 1.概念:约束是作用于表中字段上的规则,用于限制存储在表中的数据。 2.目的:保证数据库中数据的正确、有效性和完整性。 3.分类: 约束描述关键字非空约束限制该字段的数据不能为nullNOT NULL唯一约束保证该字段的所有数据都是唯一、不…...
Tomcat 编程式启动 JMX 监控
通过这篇文章,我们可以了解到,利用 JMX 技术可以方便获取 Tomcat 监控情况。但是我们采用自研的框架而非大家常见的 SpringBoot,于是就不能方便地通过设置配置开启 Tomcat 的 JMX,——尽管我们也是基于 Tomcat 的 Web 容器&#x…...
Git rebase和merge区别详解
文章目录 变基的基础用法变基过程中的冲突解决冲突后无法push问题更新变基后的代码更有趣的变基用法变基的风险用变基解决变基变基 vs 合并 此文在阅读前需要有一定的git命令基础,若基础尚未掌握,建议先阅读这篇文章Git命令播报详版 在 Git 中整合来自不…...
JDK动态代理的原理解析、代码实现
代理就像是:买家(客户端)——销售(代理对象)——工厂(目标) 买家不用直接去工厂买,而是直接通过销售就可以购买到,假设工厂生产的是杯子,那么工厂只需要提供杯子,而销售在不改变杯子的生产过程的情况下对杯子进行包装设…...
理解和使用Ansible模块,简化自动化任务
Ansible是一款强大的自动化工具,用于管理和配置IT基础设施。在Ansible的世界中,模块(Module)是至关重要的组成部分。本文将深入探讨Ansible模块,了解它们如何简化自动化任务的执行过程。 Ansible模块是Ansible的核心组…...
Docker 快速安装 MinIO
概述 MinIO 是一款基于Go语言的高性能对象存储服务,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等。 拉取docker镜像 docker pull minio/minio创建宿主机数据目录(共享数据卷) 此…...
【源码分析】Nacos如何使用AP协议完成服务端之间的数据同步?
AP节点的同步使用的是异步任务消息队列的方式来实现的。 取出任务之后将会放入到一个List集合中。 然后会发现任务的执行是由条件的。 首先是当前集群的节点数量等于1000,那么此时会直接开始同步,当然这个条件在小项目中不会成立,所以还有…...
黑客删除服务器数据后,间谍软件制造商 LetMeSpy 关闭
总部位于波兰的间谍软件 LetMeSpy 已不再运行,并表示将在 6 月份的一次数据泄露事件中关闭其服务器,其中包括从数千名受害者手机中窃取的大量数据。 LetMeSpy 在其网站上以英语和波兰语发布的通知中确认该间谍软件服务已“永久关闭”,并将于 …...
ebay儿童书包产品CPC认证
儿童书包是一种能够盛放书本或者文具的包。现在的书包五花八门,以普通的布料或者是帆布等制成,有背带,包内一般分栏。一般分三种,背在身后的,挎在肩上的,轮式(可以拖行)的。 一、美国…...
Debezium系列之:增量快照初始化历史数据实际应用案例
Debezium系列之:增量快照初始化历史数据实际应用案例 一、需求背景二、查看数据库表数据三、使用增量快照采集历史数据四、初始化历史数据一、需求背景 采集数据库数据发送到Kafka Topic,供下游实时开发消费,在采集最新数据的同时,希望把历史数据也发送到Kafka Topic同时采…...
Transformer1.0-预热
一.Encoder encoder:译为编码器,负责将输入序列压缩成指定长度的向量,这个向量就可以堪称是这个序列的语义。然后可进行编码或特征提取等操作 在transformer中encoder由6个相同的层组成,每个层包含 Multi-Head Self-AttentionPosition-Wise …...
【探索Linux】—— 强大的命令行工具 P.2(Linux下基本指令)
前言 前面我们讲了C语言的基础知识,也了解了一些数据结构,并且讲了有关C的一些知识,也相信大家都掌握的不错,今天博主将会新开一个Linux专题,带领大家继续学习有关Linux的内容。今天第一篇文章博主首先带领大家了解一下…...
供应链售后服务自动化,利用软件机器人将数据整合提升效率
随着供应链管理的不断发展,售后服务的重要性也日益凸显。良好的售后服务不仅可以提高客户满意度,还能增强品牌形象和忠诚度。然而,传统的供应链售后服务往往存在繁琐的操作、低效率和易出错的问题。为了解决这一挑战,越来越多的企…...
VIM浅谈
VIM 1. 文件1.1 管理多个文件 仅以此篇纪念VIM作者Bram Moolenaar。 1. 文件 刚刚使用VIM,很多小伙伴疑惑的就是如何退出VIM,一顿乱按结果修改了文件,q又退不出去,还需要保存。这是因为文件是保存在磁盘里的,使用Vim…...
广西大学电气专业课设资料包|短路计算课程设计全套(含源码+实验报告+理论PPT)
温馨提示:文末有联系方式广西大学电气专业课程设计资料合集 专注服务广大学生,精心整理广西大学电气工程及其自动化专业核心课设,覆盖课程设计全流程需求。短路电流计算课程设计全套电子资料 包含完整可编译运行的软件程序(支持主…...
Keil MDK调试时Watch窗口变量不刷新?别急,这3个设置项你检查了吗?
Keil MDK调试时Watch窗口变量不刷新?这3个关键设置项详解 调试嵌入式系统时,Watch窗口就像开发者的"第三只眼",能实时洞察程序运行状态。但当你发现变量值像被冻住一样纹丝不动时,那种抓狂的感觉我太熟悉了——三年前我…...
利用快马AI快速原型:十分钟搭建软件下载站首页与详情页
最近在帮朋友做一个软件下载站的原型,要求能快速上线测试用户反馈。传统开发方式从设计到编码至少需要一周,但这次我用InsCode(快马)平台的AI生成功能,十分钟就搞定了基础框架,分享下具体实现思路。 首页布局设计 首页需要突出展示…...
告别CMake配置地狱:用vcpkg工具链文件一键集成第三方库的保姆级教程
告别CMake配置地狱:用vcpkg工具链文件一键集成第三方库的保姆级教程 每次新建一个C项目,最让你头疼的是什么?是反复修改CMakeLists.txt只为了让编译器找到正确的头文件路径?还是手动添加几十个库文件路径后依然报"找不到符号…...
Flash内容还能复活吗?这款浏览器让你重温经典Flash游戏和课件
Flash内容还能复活吗?这款浏览器让你重温经典Flash游戏和课件 【免费下载链接】CefFlashBrowser Flash浏览器 / Flash Browser 项目地址: https://gitcode.com/gh_mirrors/ce/CefFlashBrowser 还记得那些陪伴我们成长的Flash小游戏和交互课件吗?当…...
ArcMap协同克里金插值实战:从数据导入到范围裁剪的完整流程
ArcMap协同克里金插值实战:从数据准备到成果优化的全流程指南 在空间分析领域,克里金插值因其能够考虑空间自相关性而广受欢迎。而协同克里金作为其进阶版本,通过引入辅助变量进一步提升预测精度,特别适用于环境监测、地质勘探和…...
黑苹果配置自动化:OpCore-Simplify实现EFI智能生成的技术革命
黑苹果配置自动化:OpCore-Simplify实现EFI智能生成的技术革命 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 为什么90%的黑苹果配置失败源…...
好写作AI“查重雷达”:用AI技术为论文“扫雷”,让学术诚信“稳如泰山”
写论文时,最让人心跳加速的瞬间是什么?不是选题时的纠结,也不是数据分析的崩溃,而是查重报告出来的那一刻——如果重复率超过30%,轻则被导师“请喝茶”要求修改,重则被扣上“学术不端”的帽子,影…...
手柄映射的艺术:RetroArch输入系统深度解析与实战指南
手柄映射的艺术:RetroArch输入系统深度解析与实战指南 【免费下载链接】RetroArch Cross-platform, sophisticated frontend for the libretro API. Licensed GPLv3. 项目地址: https://gitcode.com/GitHub_Trending/re/RetroArch 问题发现:当手柄…...
颠覆单机局限:用Nucleus Co-op打造4人同屏游戏空间
颠覆单机局限:用Nucleus Co-op打造4人同屏游戏空间 【免费下载链接】splitscreenme-nucleus Nucleus Co-op is an application that starts multiple instances of a game for split-screen multiplayer gaming! 项目地址: https://gitcode.com/gh_mirrors/spl/sp…...
