数据结构入门学习(全是干货)——树(中)

数据结构入门学习(全是干货)——树(中)

1 二叉搜索树(Binary Search Tree,简称 BST)

1.1 二叉搜索树及查找

二叉搜索树(Binary Search Tree, BST) 是一种特殊的二叉树,它满足以下性质:

  • 对于每一个节点,其左子树上所有节点的值都小于该节点的值。
  • 右子树上所有节点的值都大于该节点的值。
  • 每棵子树也是一棵二叉搜索树。

二叉搜索树的基本操作:
  1. 查找元素(Find)

    查找从根结点开始,如果树为空,返回NULL若搜索树非空,则根结点关键字和X进行比较,并进行不同处理:1.若X小于根结点赋值,只需在左子树中继续搜索;2.如果X大于根结点的键值,在右子树中进行继续搜索;3.若两者比较结果是相等,搜索完成,返回指向此结点的指针
    
    Position Find(ElementType X,BinTree BST)
    {if(!BST) return NULL;//查找失败if( X > BST -> Data)//这是尾递归,下面的两个Find的也是同理return Find(X,BST->Right);//在右子树中继续查找Else if(X < BST -> Data)return Find(X,BST->Left);//在左子树中继续查找else//X == BST->Datareturn BST;//查找成功,返回结点的找到结点的地址
    }//由于非递归函数的执行效率高,可将"尾递归"函数改为迭代函数
    Position IterFind(ElementType X,BinTree BST)
    {while(BST){if(X > BST->Data)BST = BST -> Right;//向右子树中移动,继续查找else if(X < BST->Data)BST = BST ->Left;//向左子树中移动,继续查找else//X == BST ->Datareturn BST;//查找成功,返回结点的找到结点的地址}return NULL;//查找失败
    }//查找的效率决定于树的高度
    
  2. 插入元素

  3. 删除元素

查找最大和最小元素
  • 查找最小元素:从根节点开始,沿左子树一直往下找到最左端的叶子节点。
  • 查找最大元素:从根节点开始,沿右子树一直往下找到最右端的叶子节点。
查找最小元素的递归函数示例:
Node* findMin(Node* root) {if (root == nullptr || root->left == nullptr)return root;return findMin(root->left);
}
查找最大元素的迭代函数示例:
Node* findMax(Node* root) {while (root->right != nullptr)root = root->right;return root;
}

1.2 二叉搜索树的插入

插入操作的关键是要找到元素应该插入的位置,这与查找操作类似。插入时,我们从根节点开始,与节点的值进行比较:

  • 如果插入的值小于当前节点的值,则递归到左子树。
  • 如果插入的值大于当前节点的值,则递归到右子树。
  • 如果找到了空节点,则插入该元素。
插入元素的算法:

BinTree Insert(ElementType X,BinTree BST)
{if(!BST){//若原树为空,生成并返回一个结点的二叉搜索树BST = malloc(sizeof(struct TreeNode));BST -> Data = X;BST -> Left = BST -> Right = NULL;}else //开始找要插入元素的位置if(X < BST->Data )BST -> Left = Insert(X,BST->Left);//递归插入左子树else if(X > BST->Data)BST->Right = Insert(X,BST->Right);//递归插入右子树//else X已经存在,什么都不做return BST;
}

1.3 二叉搜索树的删除

删除一个节点需要考虑三种情况:

  1. 删除的是叶结点:直接删除,并修改其父节点的指针为 NULL

  2. 删除的节点只有一个子节点:

    • 将其父节点的指针指向要删除节点的唯一孩子。

  3. 删除的节点有两个子节点:

    • 用右子树的最小元素或左子树的最大元素替代被删除的节点,然后删除这个替代节点。

删除元素的代码实现:
BinTree Delete (ElementType X,BinTree BST)
{Position Tmp;   if(!BST) printf("要删除的元素未找到");else if(X < BST ->Data)BST->Left = Delete(X,BST->Left);//左子树递归删除,返回左子树删除了x这个结点之后,新的左子树根结点的地址else if(X > BST->Data)BST->Right = Delete( X,BST->Right);//右子树递归删除else//找到要删除的结点if(BST->Left && BST->Right ){//被删除结点有左右两个子节点Tmp = FindMin(BST->Right);//在右子树中找最小的元素填充删除结点BST->Data = Tmp->Data;BST->Right = Delete(BST->Data,BST->Right);//在删除结点的右子树中删除最小元素}else{//被删除结点有一个或无子结点Tmp = BST;if(!BST->Left)//有右孩子或无子结点BST = BST->Right;else if(!BST->Left)//有左孩子或无子结点BST = BST->Left;free(Tmp);}
}
return BST;

2 平衡二叉树(Balanced Binary Tree)

2.1 什么是平衡二叉树

平衡二叉树是一种特殊的二叉树,其左子树和右子树的高度差不超过1(即左右子树的高度差最多为1)。如果一棵树的每个子树也都满足这个条件,则该树为平衡二叉树。

平衡因子:

平衡因子是某个节点左右子树的高度差。平衡因子计算公式:


平衡因子 = 左子树高度 - 右子树高度

对于平衡二叉树,所有节点的平衡因子绝对值都小于或等于1。

举例:

至少需要 7 个结点才能构造出一棵高度为 3 的平衡二叉树。


2.2 平衡二叉树的调整

在二叉搜索树的插入或删除操作中,如果树的平衡被打破,就需要进行调整,使其重新成为平衡二叉树。调整的方法是旋转,常见的四种旋转操作有:

1. RR旋转(右右旋转)

当插入点位于节点的右子树的右子树时,执行RR旋转。通过一次左旋,使树重新平衡。

2. LL旋转(左左旋转)

当插入点位于节点的左子树的左子树时,执行LL旋转。通过一次右旋,使树重新平衡。

3. LR旋转(左右旋转)

当插入点位于节点的左子树的右子树时,执行LR旋转。首先对左子树进行RR旋转,然后对整个树进行LL旋转。

4. RL旋转(右左旋转)

当插入点位于节点的右子树的左子树时,执行RL旋转。首先对右子树进行LL旋转,然后对整个树进行RR旋转。


3 链表逆转

3.1 链表基本概念

链表是一种线性数据结构,每个节点包含两部分:

  1. 数据域:存储数据。
  2. 指针域:存储指向下一个节点的指针。

3.2 单链表逆转算法

链表逆转的核心思想是逐个反转节点的指针方向,以下是链表逆转的伪代码实现:

Ptr Reverse(Ptr head) {Ptr newHead = nullptr;Ptr oldHead = head;while (oldHead != nullptr) {Ptr temp = oldHead->next;oldHead->next = newHead;newHead = oldHead;oldHead = temp;}return newHead;
}

边界测试:

  1. 链表长度为 0 或 1 的情况。
  2. 链表长度恰好为反转单位长度的整数倍。
  3. 逆转链表的其他边界情况。

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

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

相关文章

【Delphi】实现接收系统拖动文件

在 Delphi 中&#xff0c;可以通过以下步骤来实现将文件夹中的文件拖动到 Form 上&#xff0c;并在拖动时显示文件类型的光标。我们可以利用 VCL 中的 Drag and Drop 机制来处理拖动操作&#xff0c;以及自定义光标显示。 以下是详细的步骤和代码示例&#xff1a; 实现步骤&a…

力扣之181.超过经理收入的员工

文章目录 1. 181.超过经理收入的员工1.1 题干1.2 准备数据1.3 题解1.4 结果截图 1. 181.超过经理收入的员工 1.1 题干 表&#xff1a;Employee -------------------- | Column Name | Type | -------------------- | id | int | | name | varchar | | salary | int | | mana…

在设计开发中,如何提高网站的用户体验?

在网站设计开发中&#xff0c;提高用户体验是至关重要的。良好的用户体验不仅能提升用户的满意度和忠诚度&#xff0c;还能增加转化率和用户留存率。以下是一些有效的方法和策略&#xff1a; 优化页面加载速度 减少HTTP请求&#xff1a;合并CSS和JavaScript文件以减少HTTP请求…

『 Linux 』HTTP(一)

文章目录 域名URLURLEncode和URLDecodeHTTP的请求HTTP的响应请求与响应的获取简单的Web服务器 域名 任何客户端在需要访问一个服务端时都需要一个IP和端口号,而当一个浏览器去访问一个网页时通常更多使用的是域名而不是IP:port的方式, www.baidu.com这是百度的域名; 实际上当浏…

MySQL高阶1777-每家商店的产品价格

题目 找出每种产品在各个商店中的价格。 可以以 任何顺序 输出结果。 准备数据 create database csdn; use csdn;Create table If Not Exists Products (product_id int, store ENUM(store1, store2, store3), price int); Truncate table Products; insert into Products …

音视频入门基础:AAC专题(8)——FFmpeg源码中计算AAC裸流AVStream的time_base的实现

一、引言 本文讲解FFmpeg源码对AAC裸流行解复用&#xff08;解封装&#xff09;时&#xff0c;其AVStream的time_base是怎样被计算出来的。 二、FFmpeg源码中计算AAC裸流AVStream的time_base的实现 FFmpeg对AAC裸流进行解复用&#xff08;解封装&#xff09;时&#xff0c;其…

通过FUXA在ARMxy边缘计算网关上实现生产优化

在当今工业4.0时代&#xff0c;智能制造的需求日益增长&#xff0c;企业迫切需要通过数字化转型来提高生产效率、降低成本并增强市场竞争力。ARMxy系列的BL340工业级ARM控制器&#xff0c;凭借其强大的处理能力和灵活的配置选项&#xff0c;成为实现生产优化的重要基础。 一、…

io多路复用:epoll水平触发(LT)和边沿触发(ET)的区别和优缺点

在进行ET模式的正式分析之前&#xff0c;我们来举个例子简单地了解下ET和LT: 假设我们通过fork函数创建了父子两个进程&#xff0c;并通过匿名管道来通信&#xff0c;在子进程中&#xff0c;我们一次向管道写入10个字符数据&#xff0c;为"aaaa\nbbbb\n";每隔5s写入…

SmartX 分布式存储产品全新升级,支持文件存储能力与纠删码机制

近日&#xff0c;SmartX 正式发布了 SMTX ZBS 5.6 版本&#xff0c;通过引入对文件存储的支持能力&#xff0c;可作为企业统一存储平台&#xff0c;为大规模虚拟化、私有云、容器等环境提供高可靠、高可用、高性能、易扩展的企业级分布式块存储和分布式文件存储服务。该版本还引…

2024 年至今回顾:The Sandbox 创作者的历程及下一步展望

2024 年上半年是 The Sandbox 令人振奋的旅程&#xff01;从激动人心的里程碑、丰厚的奖励到创新的功能&#xff0c;我们见证了来自充满活力的社区的惊人创造力。 作为平台的生命线&#xff0c;我们致力于帮助创作者发光发热。让我们深入了解过去六个月中最激动人心的时刻和更…

OpenHarmony(鸿蒙南向开发)——标准系统方案之瑞芯微RK3566移植案例(下)

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ OpenHarmony&#xff08;鸿蒙南向开发&#xff09;——轻量系统STM32F407芯片移植案…

MySQL聚合统计和内置函数

【数据库】MySQL聚合统计 王笃笃-CSDN博客https://blog.csdn.net/wangduduniubi?typeblog显示平均工资低于2000的部门和它的平均工资 mysql> select deptno,avg(sal) deptavg from emp group by deptno; --------------------- | deptno | deptavg | --------------…

基于树表的查找

二叉排序树 相关概念 存储结构 查找 具体实现 算法分析 插入 创建 删除 无孩子 有一个孩子 有左右孩子 示例 平衡二叉树 概念 示例 插入调整 类型 由插入结点在失衡结点的位置来定&#xff1a;插入结点C为失衡结点A的左子树的左孩子&#xff0c;因此为LL型。 原则 即选择中…

10.第二阶段x86游戏实战2-反编译自己的程序加深堆栈的理解

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 工具下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1rEEJnt85npn7N38Ai0_F2Q?pwd6tw3 提…

[C++进阶[六]]list的相关接口模拟实现

1.前言 本章重点 在list模拟实现的过程中&#xff0c;主要是感受list的迭代器的相关实现&#xff0c;这是本节的重点和难点。 2.list接口的大致框架 list是一个双向循环链表&#xff0c;所以在实现list之前&#xff0c;要先构建一个节点类 template <class T> struct L…

Java 中 List 常用类和数据结构详解及案例示范

1. 引言 在 Java 开发中&#xff0c;List 是最常用的数据结构接口之一&#xff0c;它用于存储有序的元素集合&#xff0c;并允许通过索引进行随机访问。电商系统中&#xff0c;如购物车、订单列表和商品目录等功能都依赖 List 进行数据管理。选择适当的 List 实现类能够显著提…

C++STL~~priority_queue

文章目录 容器适配器一、priority_queue的概念二、priority_queue的使用三、priority_queue的练习四、仿函数五、总结 容器适配器 什么是适配器 适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结)&#xff0c;该种模式是将…

交流电力控制电路之交流调功电路、交流电力电子开关

目录 一、交流调功电路 二、交流电力电子开关 交流调压电路可看&#xff1a;交流调压电路 交流调压电路、交流调功电路和交流电力开关的异同点&#xff1a; 一、交流调功电路 交流调功电路用于调节电力设备的功率输出&#xff0c;通过改变电路中电压、电流的有效值&#xff…

STL,智能指针和线程安全,线程安全的单例模式和懒汉饿汉的实现,以及读者写者问题

&#x1f351;个人主页&#xff1a;Jupiter. &#x1f680; 所属专栏&#xff1a;Linux从入门到进阶 欢迎大家点赞收藏评论&#x1f60a; 目录 &#x1f4da;STL&#xff0c;智能指针和线程安全 &#x1f4d5;STL中的容器是否是线程安全的?&#x1f4a1;智能指针是否是线程安全…