【数据结构】二叉排序树;平衡二叉树的知识点学习总结

news2024/11/24 12:25:08

目录

1、二叉排序树

1.1 定义

1.2 查找操作

1.3 插入操作

1.4 删除操作 

1.5 C语言实现二叉排序树的基本操作 

2、平衡二叉树的知识点总结

2.1 定义

2.2 插入操作

2.3 调整“不平衡” 

2.4 删除操作


1、二叉排序树

1.1 定义

二叉排序树(Binary Search Tree,BST)是一种二叉树,具有如下性质:

1.若任意节点的左子树不为空,则左子树上所有节点的值小于它的根节点的值。

2.若任意节点的右子树不为空,则右子树上所有节点的值大于它的根节点的值。

3.任意节点的左、右子树都是二叉排序树。

4.没有键值相等的节点。

5.中序遍历二叉排序树可以得到一个有序的序列。

其中,左子树节点值小于根节点值,右子树节点值大于根节点值的性质,保证了二叉排序树的查找、插入、删除操作的时间复杂度为 O(log n)。

 

1.2 查找操作

在 BST 中查找一个节点,可以按照以下步骤进行:

  1. 从根节点开始遍历二叉排序树。
  2. 如果当前节点为空,则返回 null,表示未找到该节点。
  3. 如果当前节点的值等于目标值,则返回该节点。
  4. 如果当前节点的值大于目标值,则继续遍历左子树。
  5. 如果当前节点的值小于目标值,则继续遍历右子树。
//查找值为key的结点
BSTNode* BST_Search(BSTree T, int key){
    if(T == NULL || T->data == key)
        return T;
    else if(key < T->data)
        return BST_Search(T->lchild, key);
    else
        return BST_Search(T->rchild, key);
}

1.3 插入操作

 找到应该插入的位置(一定是叶子结点),一定要注意修改其父节点指针。

//插入值为key的结点
BSTree BST_Insert(BSTree T, int key){
    if(T == NULL){
        T = (BSTNode*)malloc(sizeof(BSTNode));
        T->data = key;
        T->lchild = NULL;
        T->rchild = NULL;
        return T;
    }
    else if(key < T->data)
        T->lchild = BST_Insert(T->lchild, key);
    else if(key > T->data)
        T->rchild = BST_Insert(T->rchild, key);
    return T;
}

1.4 删除操作 

 二叉排序树的删除操作可以分为以下几个步骤:

  1. 找到要删除的节点,并确定其父节点。

  2. 如果要删除的节点是叶子节点,直接删除即可,在其父节点中将其对应的子节点指针设为 null。

  3. 如果要删除的节点只有一个子节点,将其子节点代替要删除的节点,即在其父节点中将其对应的子节点指针指向其子节点。

  4. 如果要删除的节点有两个子节点,需要找到其右子树中的最小节点或者左子树中的最大节点,用该节点代替要删除的节点,并将其删除。如果选择右子树中的最小节点代替要删除的节点,需要从该节点的父节点开始,一直向左遍历,直到找到最后一个左节点,将其指向右子节点(因为要删除该节点)。如果选择左子树中的最大节点代替要删除的节点,需要从该节点的父节点开始,一直向右遍历,直到找到最后一个右节点,将其指向左子节点。

  5. 删除节点后,需要对二叉排序树进行调整,使其依然满足二叉排序树的性质。

//删除值为key的结点
BSTree BST_Delete(BSTree T, int key){
    BSTNode *temp;
    if(T == NULL)
        return NULL;
    else if(key < T->data)
        T->lchild = BST_Delete(T->lchild, key);
    else if(key > T->data)
        T->rchild = BST_Delete(T->rchild, key);
    else if(T->lchild && T->rchild){
        temp = BST_FindMin(T->rchild);
        T->data = temp->data;
        T->rchild = BST_Delete(T->rchild, T->data);
    }
    else{
        temp = T;
        if(T->lchild == NULL)
            T = T->rchild;
        else if(T->rchild == NULL)
            T = T->lchild;
        free(temp);
    }
    return T;
}

1.5 C语言实现二叉排序树的基本操作 

#include <stdio.h>
#include <stdlib.h>

//二叉排序树结点
typedef struct BSTNode{
    int data;                   //数据域
    struct BSTNode *lchild;     //左子树指针
    struct BSTNode *rchild;     //右子树指针
}BSTNode, *BSTree;

//返回当前二叉树的高度
int GetHeight(BSTree T){
    if(T == NULL)
        return 0;
    int left_height = GetHeight(T->lchild);
    int right_height = GetHeight(T->rchild);
    return left_height > right_height ? left_height+1 : right_height+1;
}

//查找值为key的结点
BSTNode* BST_Search(BSTree T, int key){
    if(T == NULL || T->data == key)
        return T;
    else if(key < T->data)
        return BST_Search(T->lchild, key);
    else
        return BST_Search(T->rchild, key);
}

//插入值为key的结点
BSTree BST_Insert(BSTree T, int key){
    if(T == NULL){
        T = (BSTNode*)malloc(sizeof(BSTNode));
        T->data = key;
        T->lchild = NULL;
        T->rchild = NULL;
        return T;
    }
    else if(key < T->data)
        T->lchild = BST_Insert(T->lchild, key);
    else if(key > T->data)
        T->rchild = BST_Insert(T->rchild, key);
    return T;
}

//找到以p结点为根节点的子树中最小结点
BSTNode* BST_FindMin(BSTNode *p){
    if(p == NULL)
        return NULL;
    else if(p->lchild == NULL)
        return p;
    else
        return BST_FindMin(p->lchild);
}

//删除值为key的结点
BSTree BST_Delete(BSTree T, int key){
    BSTNode *temp;
    if(T == NULL)
        return NULL;
    else if(key < T->data)
        T->lchild = BST_Delete(T->lchild, key);
    else if(key > T->data)
        T->rchild = BST_Delete(T->rchild, key);
    else if(T->lchild && T->rchild){
        temp = BST_FindMin(T->rchild);
        T->data = temp->data;
        T->rchild = BST_Delete(T->rchild, T->data);
    }
    else{
        temp = T;
        if(T->lchild == NULL)
            T = T->rchild;
        else if(T->rchild == NULL)
            T = T->lchild;
        free(temp);
    }
    return T;
}

//中序遍历二叉排序树
void InOrder(BSTree T){
    if(T == NULL)
        return;
    InOrder(T->lchild);
    printf("%d ", T->data);
    InOrder(T->rchild);
}

int main(){
    BSTree T = NULL;
    T = BST_Insert(T, 50);
    T = BST_Insert(T, 20);
    T = BST_Insert(T, 60);
    T = BST_Insert(T, 10);
    T = BST_Insert(T, 30);
    T = BST_Insert(T, 55);
    T = BST_Insert(T, 70);
    printf("原始二叉排序树:");
    InOrder(T);
    printf("\n");

    T = BST_Delete(T, 60);
    printf("删除结点 60 后的二叉排序树:");
    InOrder(T);
    printf("\n");
    return 0;
}
 

        在上面的代码中,我们首先定义了一个二叉排序树结点,包括数据域和左右子树指针。然后实现了查找、插入、删除等操作。具体实现时,我们用了递归的方式来实现这些操作。最后,我们测试了一下二叉排序树的删除操作,输出了删除结点后的二叉排序树。

 

2、平衡二叉树的知识点总结

2.1 定义

        平衡二叉树(Balanced Binary Tree)是一种二叉查找树,其中每个结点的左右子树高度差至多为1。也就是说,对于任意结点,其左右子树高度的差不大于1。在平衡二叉树中,最小的叶子结点离根节点的距离不超过最大叶子结点离根节点的距离的1倍。这样可以保证树的高度始终在logn范围内,查找、插入、删除节点的时间复杂度为O(logn)。平衡二叉树的常见实现有AVL树、红黑树等。 

2.2 插入操作

和二叉树的插入一样,找到合适的位置插入,但是新插入的结点可能导致其祖先们平衡因子改变,导致失衡。

2.3 调整“不平衡” 

当一个节点的左子树高度和右子树高度的差值超过1时,就会导致平衡二叉树不平衡。解决这种不平衡的方法是通过旋转操作来调整平衡,以下是两种常用的旋转操作:

  1. 左旋操作:当某个节点的右子树比左子树高度大时,需要将节点向左旋转,使其右子树的左子树成为该节点的右子树,而该节点成为新的右子树的根节点。

  2. 右旋操作:当某个节点的左子树比右子树高度大时,需要将节点向右旋转,使其左子树的右子树成为该节点的左子树,而该节点成为新的左子树的根节点。

在进行旋转操作时,需要注意保持平衡因子的值正确。旋转操作是平衡二叉树实现自平衡的关键。

 

2.4 删除操作

平衡二叉树的删除可以分为以下几个步骤:

1. 找到要删除的节点。如果要删除的节点是叶子节点或只有一个子节点,直接删除即可。

2. 如果要删除的节点有两个子节点,则需要找到它的后继节点或前驱节点来替换它。后继节点即右子树中最小的节点,前驱节点即左子树中最大的节点。

3. 如果替换节点也有子节点,则将替换节点的子节点与它的父节点相连。

4. 更新被删除节点的父节点的平衡因子,并从该节点开始向根节点遍历,查找是否存在平衡因子为2或-2的节点。如果存在,则进行旋转操作。

5. 最后,删除该节点并返回根节点。

平衡二叉树的删除操作较为复杂,需要保证删除后仍然是一棵平衡二叉树。

 

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

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

相关文章

云计算与大数据——部署Hadoop集群并运行MapReduce集群(超级详细!)

云计算与大数据——部署Hadoop集群并运行MapReduce集群(超级详细&#xff01;) Linux搭建Hadoop集群(CentOS7hadoop3.2.0JDK1.8Mapreduce完全分布式集群) 本文章所用到的版本号&#xff1a; CentOS7 Hadoop3.2.0 JDK1.8 基本概念及重要性 很多小伙伴部署集群用hadoop用mapr…

C++设计模式_06_Decorator 装饰模式

本篇将会介绍Decorator 装饰模式&#xff0c;它是属于一个新的类别&#xff0c;按照C设计模式_03_模板方法Template Method中介绍的划分为“单一职责”模式。 “单一职责”模式讲的是在软件组件的设计中&#xff0c;如果责任划分的不清晰&#xff0c;使用继承得到的结果往往是随…

HT for Web (Hightopo) 使用心得(2)- 2D 图纸、节点、连线 与基本动画

概括来说&#xff0c;用 HT for Web 做可视化主要分为两部分&#xff0c;也就是 2D 和 3D。这两部分需要单独创建。在它们被创建完成后&#xff0c;我们再把它们集成到一起。 HT for Web 的 2D 部分主要是指 ht.graph.GraphView (简称 GraphView&#xff0c;也就是 2D 图纸)。…

Java项目:SSM的食堂点餐系统

作者主页&#xff1a;Java毕设网 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 一、相关文档 系统中的核心用户是系统管理员&#xff0c;管理员登录后&#xff0c;通过管理员菜单来管理后台系统。主要功能有&#xff1a;个人中心、用户管理…

自动发现、zabbix_proxy代理

自动发现&#xff1a;自己去发现被监控的主机 它能够根据用户事先定义的规则自动添加监控的主机或服务等。 优点 加快Zabbix部署&#xff08;agent&#xff09; 简化管理 在快速变化的环境中使用Zabbix&#xff0c;而不需要过度管理 部署自动发现(新机子) rpm -Uvh https://re…

OSI 七层网络协议最全的图

OSI 七层网络协议最全的图 文章出处&#xff1a;https://www.shuzhiduo.com/A/RnJWawowdq/

DINO(ICLR 2023)

DINO&#xff08;ICLR 2023&#xff09; DETR with Improved deNoising anchOr box DINO发展&#xff1a; Conditional DETR->DAB-DETR&#xff08;4D,WH修正&#xff09; DN-DETR&#xff08;去噪训练&#xff0c;deNoising 稳定匹配过程&#xff09; Deformable DETR&…

后端大厂面试-16道面试题

1 java集合类有哪些&#xff1f; List是有序的Collection&#xff0c;使用此接口能够精确的控制每个元素的插入位置&#xff0c;用户能根据索引访问List中元素。常用的实现List的类有LinkedList&#xff0c;ArrayList&#xff0c;Vector&#xff0c;Stack。 ArrayList是容量…

基于同名面片的TLS测站点云配准

1、原理介绍 2、代码介绍 基于C++编写的程序代码如下,其依赖eigen矩阵运算库,在创建工程时包含库目录中使用了相对路径,因此其下载下来直接可以运行,不用单独在设置环境,非常方便。

Java项目:SpringBoot高校宿舍管理系统

作者主页&#xff1a;Java毕设网 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 一、相关文档 宿舍是大学生学习与生活的主要场所之一&#xff0c;宿舍管理是高校学工管理事务中尤为重要的一项。随着我国高校招生规模的进一步扩大&#xff0…

异步回调

Future 设计的初衷&#xff1a;对将来的某个事件的结果进行建模 package com.kuang.future;import com.kuang.pc.C;import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.uti…

ubuntu | 安装NVIDIA套件:驱动、CUDA、cuDNN

CUDA 查看支持最高的cuda版本 nvidia-smiCUDA Version:12.2 区官网下在12.2.x最新的版本即可CUDA Toolkit Archive | NVIDIA Developer 下载安装 wget https://developer.download.nvidia.com/compute/cuda/12.2.2/local_installers/cuda_12.2.2_535.104.05_linux.run sudo…

《开发实战》16 | 缓存设计:缓存可以锦上添花也可以落井下石

不要把 Redis 当作数据库 Redis 的确具有数据持久化功能&#xff0c;可以实现服务重启后数据不丢失。这一点&#xff0c;很容易让我们误认为 Redis 可以作为高性能的 KV 数据库。Redis 的特点是&#xff0c;处理请求很快&#xff0c;但无法保存超过内存大小的数据。第一&#…

leetcode 22. 括号生成

2023.9.24 看到组合两个字&#xff0c;想到了回溯。 大致思路是将所有可能的组合列出来&#xff0c;通过中止条件筛选掉无效的括号。 第一个中止条件&#xff1a;如果右括号数量大于左括号&#xff0c;那括号肯定无效。 第二个中止条件&#xff1a;当左右括号数量相等&#x…

swiper使用

介绍 Swiper&#xff08;swiper master&#xff09;是一个第三方的库&#xff0c;可以用来实现移动端、pc端的滑动操作。&#xff0c;swiper应用广泛&#xff0c;使用频率仅次于jquery, 轮播图类排名第一&#xff0c;是网页设计师必备技能&#xff0c;众多耳熟能详的品牌在使用…

Keil 无法烧写程序

问题描述&#xff1a; Keil MDK V5.38 按 F8 键无法烧录程序&#xff0c;提示: Error: Flash Download failed - "Cortex-M7", No Algorithm found for: 08000000H - 080013D3H 解决办法&#xff1a; Debug 工具改为&#xff1a;ST-Link Debugger Debug 的 Conne…

mac怎么把两张图片拼在一起

mac怎么把两张图片拼在一起&#xff1f;在如今的生活中&#xff0c;喜欢摄影的朋友们越来越多。拍照已经成为我们的一种习惯&#xff0c;因为当我们遇到美景或迷人的人物时&#xff0c;总是忍不住按下快门&#xff0c;将它们定格。随着时间的推移&#xff0c;我们渐渐发现自己的…

[Java | Web] JavaWeb——JSON与AJAX简介

目录 一、JSON 简介 1、什么是 JSON 2、JSON 的定义和访问 3、JSON 在 JS 中两种常用的转换方法 4、JSON 在 Java 中的使用 5、匿名内部类 二、AJAX 简介 1、什么是 AJAX 2、原生 JS 的 AJAX 请求示例 3、JQuery 中的 AJAX 请求 一、JSON 简介 1、什么是 JSON JSON…

Elasticsearch:什么是向量和向量存储数据库,我们为什么关心?

Elasticsearch 从 7.3 版本开始支持向量搜索。从 8.0 开始支持带有 HNSW 的 ANN 向量搜索。目前 Elasticsearch 已经是全球下载量最多的向量数据库。它允许使用密集向量和向量比较来搜索文档。 矢量搜索在人工智能和机器学习领域有许多重要的应用。 有效存储和检索向量的数据库…

马尔可夫链预测举例——钢琴销售的存贮策略

问题概述 一家钢琴专卖店&#xff0c;根据以往的销售经验&#xff0c;平均每周只能售出一架钢琴&#xff0c;现在经理指定的存贮策略是&#xff0c;每周末检查库存存量&#xff0c;仅当库存量为零时&#xff0c;才订购3架供下周销售&#xff1b;否则就不订购。试估计这种策略下…