当前位置: 首页 > news >正文

【数据结构】(C语言):二叉搜索树

二叉搜索树:

  • 树不是线性的,是层级结构。
  • 基本单位是节点,每个节点最多2个子节点。
  • 有序。每个节点,其左子节点都比它小,其右子节点都比它大。
  • 每个子树都是一个二叉搜索树。每个节点及其所有子节点形成子树。
  • 可以是空树。

添加元素:从根节点开始,比对数值。若比它小,往左子树比对;若比它大,往右子树比对;直到找到为空,则为新元素的位置。

删除元素:

  1. 若删除的节点为叶子节点(即无子节点),则直接删除。
  2. 若删除的节点只有左子节点,则左子节点替代删除节点。
  3. 若删除的节点只有右子节点,则右子节点替代删除节点。
  4. 若删除的节点既有左子节点又有右子节点,则找到直接前驱(即删除节点的左子树中的最大值,即删除节点的左子节点的最右节点),直接前驱的值替代删除节点的值,删除直接前驱节点。

遍历元素:(可使用递归)

  • 前序遍历(顺序:根节点、左子节点、右子节点)。
  • 中序遍历(顺序:左子节点、根节点、右子节点)。
  • 后序遍历(顺序:左子节点、右子节点、根节点)。

查找元素:从根节点开始,比对数值。若比它小,往左子树查找;若比它大,往右子树查找;直到找到该元素,则返回1(true),若没有,则返回0(false)。


C语言实现:(使用链表实现)

 创建结构体数据类型(记录二叉搜索树的根节点和数据个数):

typedef struct Link
{LinkNode *root;			// 根节点int length;			    // 统计有多少数据
} LinkBST;                  // 别名

创建二叉搜索树,并初始化:

LinkBST bst;
bst.root = NULL;    // 根节点,初始化为NULL
bst.length = 0;     // 数据个数,初始化为0

创建节点(结构体数据类型),并创建具体节点实例的函数:

// 节点(结构体数据类型)
typedef struct Node
{int value;			    // 数据类型为整型struct Node *left;		// 左子节点struct Node *right;		// 右子节点
}LinkNode;                  // 别名
// 函数:创建节点
LinkNode *createNode(int data)
{LinkNode *node = (LinkNode *)malloc(sizeof(LinkNode));    // 分配节点内存空间if(node == NULL){perror("Memory allocation failed");exit(-1);}node->value = data;    // 数据node->left = NULL;     // 左子节点,初始化为NULLnode->right = NULL;    // 右子节点,初始化为NULLreturn node;
}

添加元素:

void add(LinkBST *bst, int data)	// add element
{// 函数:往二叉搜索树中添加元素	LinkNode *addNode(LinkNode *node, int data){if(node == NULL){LinkNode *newnode = createNode(data);node = newnode;bst->length++;    // 每添加一个元素,length+1return node;}if(data < node->value) node->left = addNode(node->left, data);else if(data > node->value) node->right = addNode(node->right, data);return node;}// 从根节点开始比对,root指针始终指向二叉搜索树的根节点bst->root = addNode(bst->root, data);	
}

删除元素:

void delete(LinkBST *bst, int data)	// delete element
{// 函数:删除节点	LinkNode *del(LinkNode *node){   // 若只有右子节点,则右子节点替代删除节点if(node->left == NULL){bst->length--;        // 每删除一个元素,length-1return node->right;}// 若只有左子节点,则左子节点替代删除节点else if(node->right == NULL){bst->length--;        // 每删除一个元素,length-1return node->left;}// 左右子节点都有,则直接前驱(左子节点的最右节点)替代删除节点,并删除直接前驱else if(node->left && node->right){LinkNode *tmp = node, *cur = node->left;while(cur->right){tmp = cur;cur = cur->right;}node->value = cur->value;if(tmp != node) tmp->right = cur->left;else tmp->left = cur->left;bst->length--;        // 每删除一个元素,length-1return node;}}// 函数:找到将要删除的节点LinkNode *delNode(LinkNode *node, int data){if(node == NULL) return node;if(data == node->value) node = del(node);else if(data < node->value) node->left = delNode(node->left, data);else if(data > node->value) node->right = delNode(node->right, data);return node;}	// 从根节点开始比对。root指针始终指向二叉搜索树的根节点bst->root = delNode(bst->root, data);	
}

遍历元素:(使用递归)

// 前序遍历(根,左,右)
void pretravel(LinkNode *node)
{if(node == NULL) return ;printf("%d  ", node->value);pretravel(node->left);pretravel(node->right);
}
// 中序遍历(左,根,右)
void midtravel(LinkNode *node)
{if(node == NULL) return ;midtravel(node->left);printf("%d  ", node->value);midtravel(node->right);
}
// 后序遍历(左,右,根)
void posttravel(LinkNode *node)
{if(node == NULL) return ;posttravel(node->left);posttravel(node->right);printf("%d  ", node->value);
}

查找元素:

找到元素,返回1(true);没找到,返回0(false)。

int find(LinkNode *node, int data)
{if(node ==  NULL) return 0;if(data == node->value) return 1;if(data < node->value) find(node->left, data);else if(data > node->value) find(node->right, data);	
}


完整代码:(bst.c)

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>/* structure */
typedef struct Node			// linkedlist node
{int value;			// value type is integerstruct Node *left;		// left child nodestruct Node *right;		// right child node
}LinkNode;typedef struct Link			// binary search tree
{LinkNode *root;			// root node of the treeint length;			// the number of the tree
} LinkBST;/* function prototype */
void add(LinkBST *, int);		// add element to the tree
void delete(LinkBST *, int);		// delete element from the tree
void pretravel(LinkNode *);		// show element one by one,(root,left,right)
void midtravel(LinkNode *);		// show element one by one,(left,root,right)
void posttravel(LinkNode *);		// show element one by one,(left,right,root)
int find(LinkNode *, int);		// if find data,return 1(true),or return 0(false)/* main function */
int main(void)
{// create binary search tree and initializationLinkBST bst;bst.root = NULL;bst.length = 0;printf("isempty(1:true, 0:false): %d, length is %d\n",  bst.root==NULL, bst.length);add(&bst, 15);add(&bst, 8);add(&bst, 23);add(&bst, 10);add(&bst, 12);add(&bst, 19);add(&bst, 6);printf("isempty(1:true, 0:false): %d, length is %d\n",  bst.root==NULL, bst.length);printf("midtravel: ");midtravel(bst.root);printf("\n");printf("pretravel: ");pretravel(bst.root);printf("\n");printf("posttravel: ");posttravel(bst.root);printf("\n");printf("find 10 (1:true, 0:false): %d\n", find(bst.root, 10));printf("find 9 (1:true, 0:false): %d\n", find(bst.root, 9));delete(&bst, 23);delete(&bst, 15);delete(&bst, 6);printf("isempty(1:true, 0:false): %d, length is %d\n",  bst.root==NULL, bst.length);printf("midtravel: ");midtravel(bst.root);printf("\n");printf("pretravel: ");pretravel(bst.root);printf("\n");printf("posttravel: ");posttravel(bst.root);printf("\n");return 0;
}/* subfunction */
LinkNode *createNode(int data)		// create a node
{LinkNode *node = (LinkNode *)malloc(sizeof(LinkNode));if(node == NULL){perror("Memory allocation failed");exit(-1);}node->value = data;node->left = NULL;node->right = NULL;return node;
}void add(LinkBST *bst, int data)	// add element
{// subfunction(recursion): add element to the binary search tree	LinkNode *addNode(LinkNode *node, int data){if(node == NULL){LinkNode *newnode = createNode(data);node = newnode;bst->length++;return node;}if(data < node->value) node->left = addNode(node->left, data);else if(data > node->value) node->right = addNode(node->right, data);return node;}// root node receive the resultbst->root = addNode(bst->root, data);	
}void delete(LinkBST *bst, int data)	// delete element
{// subfunction(recursion): delete element from the binary search tree	LinkNode *del(LinkNode *node){if(node->left == NULL){bst->length--;return node->right;}else if(node->right == NULL){bst->length--;return node->left;}else if(node->left && node->right){LinkNode *tmp = node, *cur = node->left;while(cur->right){tmp = cur;cur = cur->right;}node->value = cur->value;if(tmp != node) tmp->right = cur->left;else tmp->left = cur->left;bst->length--;return node;}}// subfunction: find delete node,return nodeLinkNode *delNode(LinkNode *node, int data){if(node == NULL) return node;if(data == node->value) node = del(node);else if(data < node->value) node->left = delNode(node->left, data);else if(data > node->value) node->right = delNode(node->right, data);return node;}	// root node receive the resultbst->root = delNode(bst->root, data);	
}void pretravel(LinkNode *node)		// show element one by one,(root,left,right)
{if(node == NULL) return ;printf("%d  ", node->value);pretravel(node->left);pretravel(node->right);
}void midtravel(LinkNode *node)		// show element one by one,(left,root,right)
{if(node == NULL) return ;midtravel(node->left);printf("%d  ", node->value);midtravel(node->right);
}void posttravel(LinkNode *node)		// show element one by one,(left,right,root)
{if(node == NULL) return ;posttravel(node->left);posttravel(node->right);printf("%d  ", node->value);
}int find(LinkNode *node, int data)	// if find data,return 1(true),or return 0(false)
{if(node ==  NULL) return 0;if(data == node->value) return 1;if(data < node->value) find(node->left, data);else if(data > node->value) find(node->right, data);	
}

编译链接: gcc -o bst bst.c

执行可执行文件: ./bst

相关文章:

【数据结构】(C语言):二叉搜索树

二叉搜索树&#xff1a; 树不是线性的&#xff0c;是层级结构。基本单位是节点&#xff0c;每个节点最多2个子节点。有序。每个节点&#xff0c;其左子节点都比它小&#xff0c;其右子节点都比它大。每个子树都是一个二叉搜索树。每个节点及其所有子节点形成子树。可以是空树。…...

泛微开发修炼之旅--23基于ecology自研的数据库分页组件(分页组件支持mysql、sqlserver、oracle、达梦等)

一、使用场景 ecology二开开发过程中&#xff0c;经常要使用到分页查询&#xff0c;随着信创项目的到来&#xff0c;各种国产数据库的出现&#xff0c;对于数据库分页查询兼容何种数据库&#xff0c;就迫在眉睫。 于是&#xff0c;我自己基于ecology开发了一个分页插件&#…...

《昇思25天学习打卡营第4天 | mindspore Transforms 数据变换常见用法》

1. 背景&#xff1a; 使用 mindspore 学习神经网络&#xff0c;打卡第四天&#xff1b; 2. 训练的内容&#xff1a; 使用 mindspore 的常见的数据变换 Transforms 的使用方法&#xff1b; 3. 常见的用法小节&#xff1a; 支持一系列常用的 Transforms 的操作 3.1 Vision …...

【Python时序预测系列】基于LSTM实现多输入多输出单步预测(案例+源码)

这是我的第312篇原创文章。 一、引言 单站点多变量输入多变量输出单步预测问题----基于LSTM实现。 多输入就是输入多个特征变量 多输出就是同时预测出多个标签的结果 单步就是利用过去N天预测未来1天的结果 二、实现过程 2.1 读取数据集 dfpd.read_csv("data.csv&qu…...

git客户端工具之Github,适用于windows和mac

对于我本人&#xff0c;我已经习惯了使用Github Desktop,不同的公司使用的代码管理平台不一样&#xff0c;就好奇Github Desktop是不是也适用于其他平台&#xff0c;结果是可以的。 一、克隆代码 File --> Clone repository… 选择第三种URL方式&#xff0c;输入url &…...

ai除安卓手机版APP软件一键操作自动渲染去擦消稀缺资源下载

安卓手机版&#xff1a;点击下载 苹果手机版&#xff1a;点击下载 电脑版&#xff08;支持Mac和Windows&#xff09;&#xff1a;点击下载 一款全新的AI除安卓手机版APP&#xff0c;一键操作&#xff0c;轻松实现自动渲染和去擦消效果&#xff0c;稀缺资源下载 1、一键操作&…...

Unity获取剪切板内容粘贴板图片文件文字

最近做了一个发送消息的unity项目&#xff0c;需要访问剪切板里面的图片文字文件等&#xff0c;翻遍了网上的东西&#xff0c;看了不是需要导入System.Windows.Forms&#xff08;关键导入了unity还不好用&#xff0c;只能用在纯c#项目中&#xff09;&#xff0c;所以我看了下py…...

利用谷歌云serverless代码托管服务Cloud Functions构建Gemini Pro API

谷歌在2024年4月发布了全新一代的多模态模型Gemini 1.5 Pro&#xff0c;Gemini 1.5 Pro不仅能够生成创意文本和代码&#xff0c;还能理解、总结上传的图片、视频和音频内容&#xff0c;并且支持高达100万tokens的上下文。在多个基准测试中表现优异&#xff0c;性能超越了ChatGP…...

极狐GitLab 17.0 重磅发布,100+ DevSecOps功能更新来啦~【一】

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab &#xff1a;https://gitlab.cn/install?channelcontent&utm_sourcecsdn 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署…...

python实现符文加、解密

在历史悠久的加密技术中&#xff0c;恺撒密码以其简单却有效的原理闻名。通过固定的字母位移&#xff0c;明文可以被转换成密文&#xff0c;而解密则是逆向操作。这种技术不仅适用于英文字母&#xff0c;还可以扩展到其他语言的字符体系&#xff0c;如日语的平假名或汉语的拼音…...

【解释】i.MX6ULL_IO_电气属性说明

【解释】i.MX6ULL_IO_电气属性说明 文章目录 1 Hyst1.1 迟滞&#xff08;Hysteresis&#xff09;是什么&#xff1f;1.2 GPIO的Hyst. Enable Field 参数1.3 应用场景 2 Pull / Keep Select Field2.1 PUE_0_Keeper — Keeper2.2 PUE_1_Pull — Pull2.3 选择Keeper还是Pull 3 Dr…...

02-《石莲》

石 莲 石莲&#xff08;学名&#xff1a;Sinocrassula indica A.Berger&#xff09;&#xff0c;别名因地卡&#xff0c;为二年生草本植物&#xff0c;全株无毛&#xff0c;具须根。花茎高15-60厘米&#xff0c;直立&#xff0c;常被微乳头状突起。茎生叶互生&#xff0c;宽倒披…...

MySQL之聚簇索引和非聚簇索引

1、什么是聚簇索引和非聚簇索引&#xff1f; 聚簇索引&#xff0c;通常也叫聚集索引。 非聚簇索引&#xff0c;指的是二级索引。 下面看一下它们的含义&#xff1a; 1.1、聚集索引选取规则 如果存在主键&#xff0c;主键索引就是聚集索引。如果不存在主键&#xff0c;将使…...

Web后端开发之前后端交互

http协议 http ● 超文本传输协议 &#xff08;HyperText Transfer Protocol&#xff09;服务器传输超文本到本地浏览器的传送协议 是互联网上应用最为流行的一种网络协议,用于定义客户端浏览器和服务器之间交换数据的过程。 HTTP是一个基于TCP/IP通信协议来传递数据. HTT…...

520. 检测大写字母 Easy

我们定义&#xff0c;在以下情况时&#xff0c;单词的大写用法是正确的&#xff1a; 全部字母都是大写&#xff0c;比如 "USA" 。 单词中所有字母都不是大写&#xff0c;比如 "leetcode" 。 如果单词不只含有一个字母&#xff0c;只有首字母大写&#xff0…...

vue的跳转传参

1、接收参数使用route,route包含路由信息&#xff0c;接收参数有两种方式,params和query path跳转只能使用query传参,name跳转都可以 params&#xff1a;获取来自动态路由的参数 query&#xff1a;获取来自search部分的参数 写法 path跳,query传 传参数 import { useRout…...

docker配置镜像源

1&#xff09;打开 docker配置文件 sudo nano /etc/docker/daemon.json 2&#xff09;添加 国内镜像源 {"registry-mirrors": ["https://akchsmlh.mirror.aliyuncs.com","https://registry.docker-cn.com","https://docker.mirrors.ustc…...

MySQL高级-SQL优化-insert优化-批量插入-手动提交事务-主键顺序插入

文章目录 1、批量插入1.1、大批量插入数据1.2、启动Linux中的mysql服务1.3、客户端连接到mysql数据库&#xff0c;加上参数 --local-infile1.4、查询当前会话中 local_infile 系统变量的值。1.5、开启从本地文件加载数据到服务器的功能1.6、创建表 tb_user 结构1.7、上传文件到…...

认识100种电路之振荡电路

在电子电路领域&#xff0c;振荡是一项至关重要的功能。那么&#xff0c;为什么电路中需要振荡&#xff1f;其背后的原理是什么&#xff1f;让我们一同深入探究。 【为什么需要振荡电路】 简单来说&#xff0c;振荡电路的存在是为了产生周期性的信号。在众多电子设备中&#…...

SSH 无密登录配置流程

一、免密登录原理 非对称加密&#xff1a; 由于对称加密的存在弊端&#xff0c;就产生了非对称加密&#xff0c;非对称加密中有两个密钥&#xff1a;公钥和私钥。公钥由私钥产生&#xff0c;但却无法推算出私钥&#xff1b;公钥加密后的密文&#xff0c;只能通过对应的私钥来解…...

基于分布式模型预测控制的多智能体点对点转换轨迹生成Matlab程序

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。&#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室&#x1f447; 关注我领取海量matlab电子书和…...

变压器匝间短路这玩意儿仿真起来是真刺激。今儿拿COMSOL折腾了个5%短路模型,从电磁场到噪声一条龙全流程,咱们边撸代码边唠嗑

comsol仿真&#xff0c;变压器匝间短路5%的电磁振动噪声模型 包括电磁场分布&#xff0c;磁密分布&#xff0c;振动形变&#xff0c;噪声分布等结果建模第一步得先让线圈支棱起来。在组件里用参数化曲线画线圈特别实用&#xff1a; # 参数化螺旋线 r 0.5 # 半径(m) pitch 0.…...

别再死记硬背BPSK公式了!用Python+NumPy手把手带你仿真2PSK信号生成与解调全过程

用Python实战BPSK&#xff1a;从信号生成到误码率分析的完整指南 通信工程专业的学生常常被各种调制公式搞得晕头转向&#xff0c;尤其是BPSK&#xff08;二进制相移键控&#xff09;这类基础但抽象的概念。今天&#xff0c;我们将彻底改变这种学习方式——通过Python代码和可视…...

不止于安装:将Helowin Oracle 11g Docker镜像改造为可持续使用的开发数据库

从临时容器到生产级服务&#xff1a;Helowin Oracle 11g Docker镜像深度定制指南 当开发团队决定采用Docker化的Oracle数据库作为开发测试环境时&#xff0c;往往会遇到一个尴尬的现实&#xff1a;大多数现成镜像要么过于臃肿&#xff0c;要么配置不符合项目规范。Helowin的Ora…...

【PostgreSQL】生态工具箱:从核心插件到企业级扩展的实战指南

1. PostgreSQL生态工具箱全景图 第一次接触PostgreSQL时&#xff0c;很多人会惊讶于它丰富的扩展生态。就像一位老木匠的工具箱&#xff0c;PostgreSQL提供了从螺丝刀到电锯的全套工具。我在实际项目中最深刻的体会是&#xff1a;选对工具比盲目编码更重要。比如曾经有个项目需…...

Materials Studio8.0在CentOS7.9环境下的安装与配置指南

1. 环境准备与系统检查 在CentOS 7.9上安装Materials Studio 8.0之前&#xff0c;我们需要确保系统环境满足最低要求。我遇到过不少因为环境配置不当导致的安装失败案例&#xff0c;这里分享几个关键检查点&#xff1a; 首先检查主机名是否包含特殊字符。Materials Studio对主机…...

开源像素艺术生成工具上手指南:像素幻梦2.0-Stable镜像免配置部署

开源像素艺术生成工具上手指南&#xff1a;像素幻梦2.0-Stable镜像免配置部署 1. 像素幻梦简介 像素幻梦(Pixel Dream Workshop)是一款基于FLUX.1-dev扩散模型构建的下一代像素艺术生成工具。它采用16-bit像素工坊风格的视觉设计&#xff0c;为创作者提供沉浸式的AI绘图体验。…...

dynamic-datasource JVM调优:提升多数据源性能的7个实用技巧

dynamic-datasource JVM调优&#xff1a;提升多数据源性能的7个实用技巧 【免费下载链接】dynamic-datasource dynamic datasource for springboot 多数据源 动态数据源 主从分离 读写分离 分布式事务 项目地址: https://gitcode.com/gh_mirrors/dy/dynamic-datasource …...

AOP 代理对象的诞生时刻:Bean 生命周期中的“夺舍”瞬间

各位大佬&#xff0c;欢迎来到 Spring 容器最神秘、最惊心动魄的现场&#xff01;很多人以为 AOP 是“天生”的&#xff0c; Bean 一出生就带着光环。大错特错&#xff01;不过是前人在负重前行&#xff1a;Spring 先造出一个“纯净的肉身”&#xff08;原始对象&#xff09;&a…...

ESP32烧录全攻略:从命令行到GUI工具,新手也能轻松搞定

ESP32烧录全攻略&#xff1a;从命令行到GUI工具&#xff0c;新手也能轻松搞定 第一次接触ESP32开发板时&#xff0c;那块小小的芯片里蕴藏着无限可能&#xff0c;但如何将自己的代码"装进"这个硬件大脑却成了拦路虎。记得我最初尝试烧录时&#xff0c;面对各种专业术…...