二叉排序树(二叉查找树)基本操作_20230417

news2024/10/5 14:03:32

二叉排序树(二叉查找树)基本操作_20230417

  1. 前言

二叉排序树首先是一颗二叉树,它不同于常规二叉树的地方在于,如果左子树不为空,那么左子树上所有结点的值都不大于根节点的值,如果右子树不为空,那么右子树上所有的值不小于根节点的值,而且它的左右子树本身也属于二叉排序树。

二叉排序树的形式和元素的输入顺序相关,它最坏的情况下可能退化为有序线性表。大多数条件下,二叉排序树既具备二叉树的折半查找行者,又采用了链表作为储存结构,加强了数据储存的灵活性,不失为一种优秀的数据储存结构。

下面的二叉排序树通过中序遍历,就得到一组有序表。

在这里插入图片描述

  1. 二叉排序树的基本操作

2.1 查找操作

二叉排序树的查找操作操作可通过递归实现,由于二叉排序树当中的每个元素都包含有数据域、左孩子指针和右孩子指针,通过递归可以定位到是在左孩子还是右孩子区域进行查找。如果元素比对成功,则返回 true;如果查找失败,则返回false. 如果查找成功,其中的某个递归变量保留查找成功的结点,如果没有找到目标元素,则某个递归变量保留此元素的根节点(父节点)的位置。

查找的实际上是沿着根节点往下遍历的过程,它会形成一颗合适的遍历路径,如果配对成功,路径上的结点都是目标结点的父节点。

看一个具体的例子。给点上述二叉排序树,要求查找元素的值为30,那么遍历形成路径用绿色虚线表示,遍历经过了左–>左–>右的路径。

在这里插入图片描述

元素查找的实现, 如果发现递归结点已经为NULL,意识是查询失败,此二叉排序树当中不含有目标元素,此时查找目标赋值为待查找元素的父节点,同时返回查询失败标记false, false会在退栈过程中不断传递给当前的栈,最终查找函数返回false.

同时,如果当前结点的值和待查找的值相等,意味着本次查询成功,递归可以结束(不再入函数栈),同时返回查询成功的标记true,true会在退栈过程中不断传递给上一级函数栈,最终查找函数返回true。

typedef struct BiTNode
{
    SElemType data;
    struct BiTNode *lchild;
    struct BiTNode *rchild;
} BiTNode, *BiTree;


bool find_bst(BiTree T, KeyType key, BiTree parent, BiTree *target_ptr)
{
    if(T==NULL)
    {
        *target_ptr=parent;
        return false; //one of termination conditions, traveling with parent
    }
    else
    {
        //another condition of termination conditions
        //traveling with parent
        if(EQ(key,T->data.key)) 
        {
            *target_ptr=T;
            return true;
        }
        else if (LT(key, T->data.key))
        {
            return find_bst(T->lchild,key,T,target_ptr);
        }
        else
        {
            return find_bst(T->rchild,key,T,target_ptr);
        }
    }
}

2.2 插入和创建树操作

二叉排序树是一类动态表,其原因在于,如果树中不含有待插入元素,那么二叉排序树会执行插入操作,从而达到动态更新表的目的。插入和创建实际上可以共用一个过程,插入的过程也是创建树的过程。利用上面的查找函数,可以实现插入的过程。正如前面所述,插入过程需要先判断待插入元素是否在现有的表当中,如果不包含在目前的表当中,则需要执行插入操作,并返回插入成功的标记true,否则则直接返回未执行插入的标记false.

bool insert_bst(BiTree *bt, KeyType key)
{
    BiTree ptr;
    BiTree new_node;

    if(!find_bst(*bt,key,NULL,&ptr))
    {
        new_node=(BiTree)malloc(sizeof(BiTNode));
        new_node->data.key=key;
        new_node->data.value=NULL;
        new_node->lchild=NULL;
        new_node->rchild=NULL;

        if(ptr==NULL) // don't leave this condition behind
        {
            *bt=new_node;
        }
        else if(LT(key,ptr->data.key))
        {
            ptr->lchild=new_node;
        }
        else
        {
            ptr->rchild=new_node;
        }

        return true;
    }

    return false;
}

2.3 二叉排序树删除操作

二叉排序树的结点删除分3种情况讨论,

a.) 若P为叶子结点,既PL和PR均为空树,由于删除叶子结点不破坏树的结点,只需要修改P结点的指针即可,也就是*p=NULL即可。

在这里插入图片描述

b.) 上述图,若 P结点只有左子树或只有右子树,此时只要令PL或PR称为父节点的左子树即可(也即是把指针赋值为结点P即可)

c.) 若P结点的左右子树均不为空,如果删除元素P后,需要保持二拆排序树仍然有序,那么就有两种途径,①-a途径,称之为替代法,用p元素的直接前驱元素S里面的值替代P里面的值,P的左右孩子指针保持不变,同时删除S结点,把S结点的左孩子赋值给其双亲结点的右孩子;②-b途径是利用待删除元素的左子树根节点来替代P所在结点,同时把P结点原有的右子树赋值给左子树的最右端元素。

两种类型不同在于①-a利用原有结点的左右孩子指针,只是替代元素;②-b则是直接修改替换原有结点,并更新现有结点的对应指针。

在这里插入图片描述

c) 删除的代码实现

二叉排序树的删除过程仍然采用递归函数,如果找到待删除元素,则执行删除操作,并返回删除成功标记,否则返回删除失败标记。

bool delete_bst(BiTree *T, KeyType key)
{
    //if deletion is succesfful, it will return true;
    //if deletion is not successful, it will return false
    if(*T==NULL)
    {
        return false;  // one termination condition
    }
    else
    {
        if(EQ(key,(*T)->data.key))
        {
            delete_action_b(T); //propagate the return value
            return true; //the second termination condition
        }
        else if (LT(key, (*T)->data.key))
        {
            return delete_bst(&((*T)->lchild),key);
        }
        else
        {
            return delete_bst(&((*T)->rchild), key);
        }
    }
}

分别用两个函数实现不同的删除模式,

//①-a implementation code
void delete_action_a(BiTree *node)
{
    //p;
    //s;
    //list three scenarios of node
    BiTree p;
    BiTree s;

    if((*node)->lchild==NULL)
    {
        p=*node;
        (*node)=(*node)->rchild;
        free(p);
    }
    else if ((*node)->rchild == NULL)
    {
        p = *node;
        (*node) = (*node)->lchild;
        free(p);
    }
    else
    {
        p= *node;
        s=(*node)->lchild; //next one
        while(s->rchild!=NULL)
        {
            p=s;
            s=s->rchild;
        }

        (*node)->data=s->data;

        if(p!=(*node))
        {
            p->rchild=s->lchild;
        }
        else
        {
            p->lchild=s->lchild; //no right child and jumpt one node
        }

        free(s);
    }

    return;
}

//②-b implementation code
void delete_action_b(BiTree *node)
{
    BiTree p;
    BiTree s;


    if ((*node)->lchild == NULL)
    {
        p = *node;
        (*node) = (*node)->rchild;
        free(p);
    }
    else if ((*node)->rchild == NULL)
    {
        p = *node;
        (*node) = (*node)->lchild;
        free(p);
    }
    else
    {
        p = *node;
        s = (*node)->lchild;
      

        while (s->rchild != NULL)
        {
            s = s->rchild;
        }

        s->rchild=(*node)->rchild; // 先后顺序非常重要
        (*node)=(*node)->lchild;  // 先后顺序非常重要

        free(p);
    }

    return;
}
  1. 二叉查找树的形式

与静态二叉搜索树不同,静态二叉搜索树的形式是唯一的;对于相同的元素集合,二叉查找树的形式会随着不同的排列顺序呈现不同的树的形态。由于树的形态不同,造成树的深度不同,导致平均查找长度不同(Average Search Length),如果输入有序元素,二叉查找树就退化为有序线性表,导致极端的情况发生。

在这里插入图片描述

这就为后面平衡二叉查找树的引入提供了应用场景,本文仅针对二叉排序树,不会对AVL树进一步阐述。

  1. 小结

本文学习了二叉排序树的不同操作,包括插入、建树和删除等操作,同时阐述了不同形态的二叉查找树会影响查找效率,极端情况下,有序输入会导致二叉排序树蜕变为线性表,严重影查询效率。

参考资料:

《数据结构》严蔚敏,清华大学

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

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

相关文章

从GPT-4、文心一言再到Copilot,AIGC卷出新赛道?

业内人都知道,上一周是戏剧性的,每一天,都是颠覆各个行业,不断 AI 化的新闻。 OpenAI发布GPT-4、百度发布文心一言、微软发布Microsoft 365 Copilot 三重buff叠加,打工人的命运可以说是跌宕起伏,命途多舛了…

pmp证书报考流程+pmp备考+pmp学习干货+pmp指南汇总

2023年共有4次PMP考试,分别是3月、5月、8月、11月,由于3月份考试不开放新报名,所以第一次备考PMP的同学可以选择参加5月份考试。那么,现在备考5月份PMP考试还来得及吗? 现在开始备考5月PMP考试,时间是非常…

Scrum

目录 1、Scrum: 敏捷里的3355: 什么是Scrum: Scrum的优点: Scrum的理论: Scrum的三大支柱: 透明性: 检视: 调整: 2、Scrum的角色简介: Scrum各角色…

【数据结构学习笔记 之 栈和队列】——上

前言:栈和队列是常用的数据结构之一,本文主要介绍有关栈的基本特性以及基本操作和一些经典的OJ题目,关于队列的介绍放到下篇。那么话不多说,让我们开始吧。 一、栈的基本知识 1. 栈的基本概念 栈是一种特殊的线性表&#xff0c…

同学在外包干了两年的点点点,24岁人就快废了

前言 简单的说下,我大学的一个同学,毕业后我自己去了自研的公司,他去了外包,快两年了我薪资、技术各个方面都有了很大的提升,他在外包干的这两年人都要废了,技术没一点提升,学不到任何东西&…

JavaScript 的学习

文章目录一、简介总结一、简介 JavaScript 是互联网上最流行的脚本语言,这门语言可用于 HTML 和 web,更可广泛用于服务器、PC、笔记本电脑、平板电脑和智能手机等设备。 JavaScript 是脚本语言 JavaScript 是一种轻量级的编程语言。 JavaScript 是可插入…

如果要向“硅谷精神之父”提一道问题,你会问什么?| CSDN 访谈世界互联网教父 Kevin Kelly

ChatGPT 的问世不禁让人遐想,接下来的 5000 天,将会发生什么事? 硅谷精神之父、世界互联网教父、《失控》作者凯文凯利(Kevin Kelly,以下简称 K.K.)是这样预测的: 未来将会是一切都与 AI 相连的…

Vue3通知提醒框(Notification)

Vue3相关组件项目依赖版本信息 可自定义设置以下属性: 消息的标题(title),默认温馨提示自动关闭的延时时长(duration),单位ms,默认4500ms消息从顶部弹出时,距离顶部的位…

【问题】开发遇到的小问题

文章目录使用糊涂工具,将时间字符串转化为LocalDateTime类型Date类型转换LocalDate类型jdk8 LocalDateTime获取当前时间和前后推时间echarts图中显示表格是需要添加宽高前端往后端传值时,需要转一下对象再往后端传使用 value-format"yyyy-MM-dd HH:…

jwt授权

JWT格式 由header、payload、signature三部分组成,中间用圆点(.)连接: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJpYW0uYXBpLm1hcm1vdGVkdS5jb20iLCJleHAiOjE2NDI4NTY2MzcsImlkZW50aXR5IjoiYWRtaW4iLCJpc3MiOiJpYW0tYXBpc2VydmVyIiwib3JpZ19pYXQiOjE2MzUw…

拼团系统开发|全民拼购商业模式解读

拼团系统开发|拼团模式在市场上已经屡见不鲜,某夕夕就是这方面的典范。不过现在市场上又出现一种升级版的拼团商业模式,也就是全民拼购,它除了可以帮助商家提升销量,还有引流裂变获客的效果,因此受到了许多企业商家的热…

chatgpt教你练习前端算法

今天想试试chatgpt关于代码算法这一块儿是否好用。 判断质数 上面的代码有一点小问题,当num为2时,返回的结果是错误的,我改进了一下,并优化了一点性能 // 判断是否是素数(质数) function isprime(number)…

【Linux】用LCD文字祝愿(Framebuffer+Freetype)

目录 前言 一、LCD操作原理 (1)LCD和Framebuffer。 (2)LCD的操作: (3)核心函数(后续也会经常用到) ①open函数 ②ioctl函数 ③mmap函数 二、字符的点阵显示 &a…

4K高清修复,模糊视频4k修复是怎么实现的?

在当今数字时代,高分辨率视频已成为大众观影的标配。4K分辨率作为其中高端的选项,提供了比传统1080p高出四倍的细节和清晰度,使得观众们能够更加身临其境地享受影视作品。然而,有时候我们可能会遇到4K视频质量不佳的问题&#xff…

Chapter3-用适合的方式发送和接收消息

3.1 不同类型的消费者 消费者可分为两种类型。 一个是DefaultMQPushConsumer ,由系统控制读取操作,收到消息后自动调用传人的处理方法来处理;另 一个是 DefaultMlConsumer ,读取操作中的大部分功能由使用者自主控制 。 3.1.1 Def…

uni-app:登录与支付--用户信息

用户信息 实现用户头像昵称区域的基本布局 在 my-userinfo 组件中&#xff0c;定义如下的 UI 结构&#xff1a; <template><view class"my-userinfo-container"><!-- 头像昵称区域 --><view class"top-box"><image src"…

如何通过小程序容器技术实现App的灰度发布

在当今移动应用市场竞争激烈的环境下&#xff0c;如何更快地发布新版本、更精确地测试和调整、更好地了解用户需求和行为&#xff0c;成为了每个App开发者面临的重要挑战。在这个背景下&#xff0c;灰度发布和小程序容器技术成为了越来越受欢迎的解决方案。 灰度发布是指将新版…

【Linux高性能服务器编程】I/O复用的高级应用

文章目录一、基于 select 的非阻塞 connect二、基于 poll 的聊天室程序2.1 客户端2.2 服务器三、基于 epoll 实现同时处理 TCP 和 UDP 服务一、基于 select 的非阻塞 connect connect系统调用的 man 手册中有如下一段内容&#xff1a; EINPROGERESS The socket is nonblocking…

ChatGPT既然这么火,有没有弊端呢?

介绍 在现代社会中&#xff0c;人们越来越依赖技术来解决问题。聊天机器人是一种最新的技术趋势&#xff0c;这种技术可以为人们带来很多便利。而ChatGPT聊天机器人则是其中的一种&#xff0c;它使用了大型的语言模型GPT&#xff08;Generative Pre-trained Transformer&#…

实操干货丨ChatGPT+XMind,效率爆炸,天下无敌

日常办公中&#xff0c;常用工具我们最熟悉的莫过于office铁三角&#xff1a;Word/Excel/PPT&#xff0c;除了这哥仨&#xff0c;再让你推荐一个。 XMind&#xff0c;绝对位列其中。 今天给大家分享一个 ChatGPTXMind的绝佳玩法&#xff0c;不需要下载安装任何额外的工具。 …