【数据结构】二叉排序树(查找+插入+删除+效率分析)完整代码+解析

news2025/7/17 14:39:05

3.1 二叉排序树

3.1.1 定义
  • 二叉排序树的定义

    又称二叉查找树(BST,Binary Search Tree)

    二叉排序树是具有以下性质的二叉树:

    左子树结点值<根结点值<右子树结点值

    • 进行中序遍历,可以得到一个递增的有序序列。

    在这里插入图片描述

3.1.2 查找操作
  • 步骤

    1.若树非空,目标值与根结点的值比较;

    2.若相等,则查找成功;

    若小于根结点,则在左子树上查找;

    否则在右子树上查找;

    3.查找成功返回结点指针;查找失败返回NULL。

  • 代码

    //二叉排序树结点
    typedef struct BSTree{
        int key;
        struct BSTNode *lchild,*rchild;
    }BSTNode,*BSTree;
    
    //在二叉排序树中查找值为key的结点
    BSTNode *BST_search(BSTree T,int key){
        //若树为空或等于根结点值,则结束循环
        while(T!=NULL&&key!=T->key){
            if(key<T->key)
                T=T->lchild; //key小,则在左子树上找
            else
                T=T->rchild; //key大,则在右子树上找
        }
        return T;
    }
    
  • 用递归方式实现

    BSTNode *BSTSearch(BSTree T,int key){
        if(T==NULL)
            return NULL;
        if(key==T->key)
            return T;
        else if(key<T->key)
            return BSTSearch(T->lchild,key); //递归在左树中找
        else
            return BSTSearch(T->rchild,key); //递归在右子树中找
    }
    
    • 递归的最坏空间复杂度 O ( h ) O(h) O(h),非递归是 O ( 1 ) O(1) O(1),所以非递归效率更加好。
3.1.3 插入操作
  • 思路

    若原二叉树为空,则直接插入结点;

    否则,若关键字k小于根结点值,则插入到左子树;

    若关键字k大于根结点值,则插入到右子树。

  • 代码

    //在二叉排序树插入关键字为k的新结点(递归实现)
    int BST_Insert(BSTree &T,int k){
        //原树为空,新插入的结点为根结点
        if(T==NULL){
            T=(BSTree)malloc(sizeof(BSTNode));
            T->key=k;
            T->lchild=T->rchild=NULL;
            return 1;
        }
        else if(k==T->key) //树中存在相同关键字的结点,插入失败
            return 0;
        else if(k<T->key) //插入到T的左子树
            return BST_Insert(T->lchild,k);
        else //插入到T的右子树
            return BST_Insert(T->rchild,k);
    }
    
  • 最坏空间复杂度: O ( h ) O(h) O(h)

  • 二叉排序树的构造

    //按str[]中的关键字序列建立二叉树
    void Creat_BST(BSTree &T,int str[],int n){
        T=NULL;
        int i=0;
        //依次将每个关键字插入到二叉排序树中
        while(i<n){
            BST_Insert(T,str[i]);
            i++;
        }
    }
    
    • 注:不同的关键字序列可能得到同款二叉排序树,也可能不同。
3.1.4 删除操作
  • 步骤

    先搜索找到目标结点:

    1.若被删结点z是叶子结点,

    ​ 则直接删除,不会破坏二叉排序树的性质。

    2.若结点z只有一棵左子树或右子树,

    ​ 则让z的子树成为z的子树成为z父节点的子树,代替z的位置。

    3.若z既有左子树又有右子树,

    ​ 方法一:则令z的直接后继(中序遍历z子树后的第一个结点)代替z,然后从二叉排序树中删去这个直接后继。

    ​ z的后继:z的右子树中最左下结点(该结点一定没有左子树)。

    ​ 方法二:用直接前驱替换直接后继,其他方法不变。

    ​ z的前驱:z的左子树中最右下结点(该结点一定没有右子树)。

3.1.5 效率分析
  • 查找长度

    在查找运算中,需要对比关键字的次数称为查找长度,反映了查找操作时间复杂度。

在这里插入图片描述

  • 时间复杂度

    最差情况下 O ( h ) O(h) O(h),即为树高

*完整代码 二叉排序树
#include <iostream>
using namespace std;

//二叉排序树结点
typedef struct BSTNode{
    int key;
    struct BSTNode *lchild,*rchild;
}BSTNode,*BSTree;

// 在二叉排序树中搜索关键字为key的结点
BSTNode* BSTSearch(BSTree T, int key) {
    if (T == NULL || T->key == key)
        return T;
    if (key < T->key)
        return BSTSearch(T->lchild, key);
    else
        return BSTSearch(T->rchild, key);
}

// 在二叉排序树中查找最小值结点
BSTNode* findMin(BSTree T) {
    if (T == NULL)
        return NULL;
    else if (T->lchild == NULL)
        return T;
    else
        return findMin(T->lchild);
}

// 删除结点z
void BST_Delete(BSTree &T, int key) {
    if (T == NULL)
        return;
    else if (key < T->key)
        BST_Delete(T->lchild, key);
    else if (key > T->key)
        BST_Delete(T->rchild, key);
    else {
        // 找到了要删除的结点
        if (T->lchild && T->rchild) {
            // 如果有两个子节点
            BSTNode* minRight = findMin(T->rchild); // 找到右子树的最小值结点
            T->key = minRight->key; // 用右子树的最小值替换当前结点
            BST_Delete(T->rchild, minRight->key); // 删除右子树的最小值结点
        } else {
            // 如果只有一个子节点或者是叶子结点
            BSTNode* temp = T;
            if (T->lchild == NULL) // 如果只有右子树或者是叶子结点
                T = T->rchild;
            else if (T->rchild == NULL) // 如果只有左子树
                T = T->lchild;
            free(temp); // 释放删除结点的内存
        }
    }
}

//在二叉排序树插入关键字为k的新结点(递归实现)
int BST_Insert(BSTree &T,int k){
    //原树为空,新插入的结点为根结点
    if(T==NULL){
        T=(BSTree)malloc(sizeof(BSTNode));
        T->key=k;
        T->lchild=T->rchild=NULL;
        return 1;
    }
    else if(k==T->key) //树中存在相同关键字的结点,插入失败
        return 0;
    else if(k<T->key) //插入到T的左子树
        return BST_Insert(T->lchild,k);
    else //插入到T的右子树
        return BST_Insert(T->rchild,k);
}

//按str[]中的关键字序列建立二叉树
void Creat_BST(BSTree &T,int str[],int n){
    T=NULL;
    int i=0;
    //依次将每个关键字插入到二叉排序树中
    while(i<n){
        BST_Insert(T,str[i]);
        i++;
    }
}

// 中序遍历打印二叉排序树
void InOrder(BSTree T) {
    if (T != NULL) {
        InOrder(T->lchild);
        cout << T->key << " ";
        InOrder(T->rchild);
    }
}

int main() {
    BSTree T = NULL;

    // 插入操作测试
    int arr[] = {50, 30, 70, 20, 40, 60, 80};
    int n = sizeof(arr) / sizeof(arr[0]);
    Creat_BST(T, arr, n);

    cout << "Binary Search Tree (Inorder): ";
    InOrder(T);
    cout << endl;

    // 搜索操作测试
    int searchKey = 40;
    BSTNode* searchResult = BSTSearch(T, searchKey);
    if (searchResult != NULL)
        cout << "Key " << searchKey << " found in the tree." << endl;
    else
        cout << "Key " << searchKey << " not found in the tree." << endl;

    // 删除操作测试
    int deleteKey = 30;
    cout << "Deleting key " << deleteKey << endl;
    BST_Delete(T, deleteKey);

    cout << "Binary Search Tree after deletion: ";
    InOrder(T);
    cout << endl;

    return 0;
}

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

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

相关文章

代码随想录算法训练营Day 38| 动态规划part01 | 理论基础、509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯

代码随想录算法训练营Day 38| 动态规划part01 | 理论基础、509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯 文章目录 代码随想录算法训练营Day 38| 动态规划part01 | 理论基础、509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯理论基础一、常规题目二、解题步骤…

JWT token demo

1、pom依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.9.RELEASE</version> </parent><dependencies><dependency><groupId>…

【JavaWeb】Day74.Spring——AOP进阶(连接点)

连接点 连接点可以简单理解为可以被AOP控制的方法。我们目标对象当中所有的方法不是都是可以被AOP控制的方法。而在SpringAOP当中&#xff0c;连接点又特指方法的执行。 在Spring中用JoinPoint抽象了连接点&#xff0c;用它可以获得方法执行时的相关信息&#xff0c;如目标类名…

【树】简要理解树的概念

P. S.&#xff1a;以下代码均在VS2019环境下测试&#xff0c;不代表所有编译器均可通过。 P. S.&#xff1a;测试代码均未展示头文件stdio.h的声明&#xff0c;使用时请自行添加。 目录 1、树的概念2、树的相关概念3、结语 1、树的概念 树是一种非线性的数据结构&#xff0c;它…

为什么大家都说it行业要死了?

年后开始找工作开始还不敢投简历怕准备不充分。怕错过了心仪的公司。 花了2周自己死磕了一下自我介绍&#xff0c;和工作经历。然后信心满满就开始投了&#xff0c;结果发现一堆人打招呼一阵欣喜的。可是一查全是外包公司。于是开始了自我怀疑。难道是我能力不行&#xff1f;难…

SQL Server服务启动缓慢或崩溃问题分析

关键词&#xff1a;SQL Server故障解决、服务启动缓慢、服务崩溃、日志文件清理 阅读建议&#xff1a;如果您遇到的是SQL Server服务启动缓慢或无法响应的问题&#xff0c;可以重点阅读文章的第一部分&#xff1b;如果是服务崩溃或重启的问题&#xff0c;可以重点关注第二部分。…

【其他学习参考文档记录】

交叉编译学习参考 nodejs 交叉编译-cliff工作室

经典文献阅读之--D-Map(无需射线投射的高分辨率激光雷达传感器的占据栅格地图)

0. 简介 占用地图是机器人系统中推理环境未知和已知区域的基本组成部分。《Occupancy Grid Mapping without Ray-Casting for High-resolution LiDAR Sensors》介绍了一种高分辨率LiDAR传感器的高效占用地图框架&#xff0c;称为D-Map。该框架引入了三个主要创新来解决占用地图…

UE4_照亮环境_光束light beam

学习笔记&#xff0c;不喜勿喷&#xff0c;侵权立删&#xff01;祝愿生活越来越好&#xff01; 光束&#xff1a;模拟大气中散射的光线。利用定向光源模拟真实曙暮光效果或大气散射的阴影&#xff0c;即可生成 光束 。这些光线为场景添加深度和真实度。 一&#xff1a;一些参数…

(四十一)第 6 章 树和二叉树(包含双亲的树的孩子链表存储)

1. 背景说明 2. 示例代码 1) errorRecord.h // 记录错误宏定义头文件#ifndef ERROR_RECORD_H #define ERROR_RECORD_H#include <stdio.h> #include <string.h> #include <stdint.h>// 从文件路径中提取文件名 #define FILE_NAME(X) strrchr(X, \\) ? strrch…

中学数学研究杂志中学数学研究杂志社中学数学研究编辑部2024年第4期目录

教学纵横 高中数学选择性必修课程函数主线分析 柳双;吴立宝; 1-4 贯彻新课程理念 促学习能力提升——以“三角函数诱导公式”教学为例 陆雨轩; 4-6《中学数学研究》投稿&#xff1a;cn7kantougao163.com 对高中数学新课标教材新增知识点的价值分析 钱伟风;刘瑞美; …

每个开发者都应该拥有的-云服务器!

每个开发者都应该拥有的-云服务器&#xff01; 第一台云服务器ECS言归正传云服务器妙用 每个开发者都该拥有一台云服务器 作为开发者&#xff0c;总是会时不时的跟服务器打交道&#xff0c;不管你是部署应用程序&#xff0c;还是在服务器上面搭建安装基础环境&#xff0c;比如J…

品牌设计理念和logo设计方法

一 品牌设计的目的 设计是为了传播&#xff0c;让传播速度更快&#xff0c;传播效率更高&#xff0c;减少宣传成本 二 什么是好的品牌设计 好的设计是为了让消费者更容易看懂、记住的设计&#xff0c; 从而辅助传播&#xff0c; 即 看得懂、记得住。 1 看得懂 就是让别人看懂…

vue3中使用cherry-markdown

附cherry-markdown官网及api使用示例 官网:https://github.com/Tencent/cherry-markdown/blob/main/README.CN.md api:Cherry Markdown API 考虑到复用性,我在插件的基础上做了二次封装,步骤如下: 1.下载 (一定要指定版本0.8.22,否则会报错: [vitel Internal server e…

AI仿站源码教程

AI仿站源码教程 随着AI技术的不断发展&#xff0c;仿站技术已经越来越成熟&#xff0c;通过AI一键仿站&#xff0c;开发者们可以更快速、更高效地搭建网站。传统的前端开发过程中&#xff0c;需要大量的手工编码和设计&#xff0c;而AI仿站技术可以通过截图或视频&#xff0c;…

RK3568/RK3588智慧校园AI盒子方案,电子班牌,出入口管制,数字化校园等,支持鸿蒙,支持免费定制

智慧校园解决方案基于物联网、人工智能等新兴技术&#xff0c;为师生构建智能化校园环境&#xff0c;涵盖了校园安全、智慧教室、考勤管理、智慧食堂等多个场景&#xff0c;从工作、学习到生活&#xff0c;带来更人性化、更便捷、更高效的服务。 方案架构 方案特点 全面感知校园…

信创应用软件之协同办公(OA)

信创应用软件之协同办公&#xff08;OA&#xff09; 概述 办公 “办公”一词源于历史上对公事、公务处理的简称&#xff0c;现代办公有了更先进的诠释&#xff0c;指在特定时间、特定空间中人互相协作、共同运作的过程&#xff0c; 即围绕以“人”为主的办公主体与其关联的一…

Web APIs 第一天( Dom获取属性操作)

Web API 基本认知 变量声明 1.变量声明有三个 var let 和 constl 我们应该用那个呢&#xff1f;首先var 先排除&#xff0c;老派写法&#xff0c;问题很多&#xff0c;可以淘汰掉…2. let or const ? 建议&#xff1a; const 优先&#xff0c;尽量使用const&#xff0c;原因…

html5的一些新特性

最近总是碰到html5特性这种问题,虽然简单,但是也是自己平时不关注的东西,趁今天时间充裕,那就来总结一下吧 HTML5新特性包括新增了部分标签、表单元素增强、支持视频和音频、支持canvas绘图、提供web存储、提供地理定位功能、提供web workers机制、提供web socket协议、提供CS…

NPDP|传统行业产品经理如何跨越鸿沟,从用户角度审视产品

随着科技的飞速发展和互联网的普及&#xff0c;产品经理的角色已经从单纯的产品规划者逐渐转变为全方位的用户体验设计者。对于传统行业的产品经理来说&#xff0c;这是一个挑战与机遇并存的时代。他们不仅要面对激烈的市场竞争&#xff0c;还要学会如何跨越与新兴科技行业之间…