备战蓝桥杯Day25 - 二叉搜索树

一、基本概念

二叉搜索树(Binary Search Tree),又称为二叉查找树或二叉排序树,是一种具有特定性质的二叉树。

  1. 定义:二叉搜索树可以是一棵空树,也可以是具有以下特性的非空二叉树:

    • 若其左子树不空,则左子树上所有结点的值均小于其根结点的值。
    • 若其右子树不空,则右子树上所有结点的值均大于其根结点的值。
    • 它的左、右子树也分别为二叉排序树。
  2. 结构:二叉搜索树是以二叉树的形式组织的,通常可以使用链表数据结构来表示。每个结点除了包含关键字(key)和可能的其他数据外,还包含指向其左孩子(lchild)和右孩子(rchild)的指针,以及指向其父结点(parent)的指针(如果需要的话)。如果某个孩子结点或父结点不存在,则相应属性的值为空(NIL)。

  3. 元素特性:二叉搜索树中存储的元素必须具备可比较性,例如整数(int)或浮点数(double)等。如果是自定义类型,需要指定比较方式。

  4. 应用:二叉搜索树作为一种经典的数据结构,具有链表快速插入与删除操作的特点和数组快速查找的优势。因此,它在许多场合下都有广泛的应用,如在文件系统和数据库系统中用于高效的排序与检索操作。

二叉搜索树是一种非常有效的数据结构,它能够保持数据的有序性,同时提供快速的查找、插入和删除操作。

二、插入操作实现

代码实现

# 定义树的节点
class BiTreeNode:def __init__(self, data):self.data = dataself.lchild = Noneself.rchild = Noneself.parent = Noneclass BST:def __init__(self):  # 初始化二叉搜索树self.root = Nonedef insert(self, node, val):  # 递归定义插入if not node:node = BiTreeNode(val)  # 如果是空树,那么直接创建新的节点插入elif val < node.data:  # 当插入的值小于根节点,就向左子树插入node.lchild = self.insert(node.lchild, val)  # 调用递归函数实现插入节点node.lchild.parent = node   # 并与父节点链接起来elif val > node.data: # 当插入的值大于根节点,就向右子树插入node.rchild = self.insert(node.rchild, val)  # 调用递归函数实现插入节点node.rchild.parent = node  # 并与父节点链接起来return nodedef insert_no_rec(self, val):  # 非递归定义插入  在下面详细解释p = self.rootif not p:   # 空树self.root = BiTreeNode(val)  # 空树时直接新建节点插入即可returnwhile True:if val < p.data:if p.lchild:  # 左孩子存在p = p.lchildelse:   # 左孩子不存在时直接创建节点插入p.lchild = BiTreeNode(val)p.lchild.parent = pelif val > p.data:if p.rchild:  # 右孩子存在p = p.rchildelse:  # 右孩子不存在时直接创建节点插入p.rchild = BiTreeNode(val)p.rchild.parent = preturnelse:return

非递归插入详细过程 

使用非递归函数插入数据详细过程

1、随便定义一颗二叉搜索树(非空),将val = 12 插入到树中 。通过循环比较来实现数值的插入。

先将定义的 p 指针指向根节点,然后开始 val 与 根节点数值的比较。

2、 根据图中数值可知, val = 12 < p.data = 17,且 p点的左孩子 (p.lchild)存在,那么 p 指针向下移动,只执行 if val < p.data: 这块代码,变为如下图所示。

 while True:if val < p.data:if p.lchild:p = p.lchildelse:p.lchild = BiTreeNode(val)p.lchild.parent = p

 

 3.此时, val = 12 < p.data = 13,且 p点的左孩子 (p.lchild)存在,执行 p = p.lchild 语句,那么 p 指针向下移动,变为如下图所示。

4.此时, val = 12 > p.data = 7, 那么他要往右子树进行插入,且p.data 的右孩子不存在,就直接创建新的节点进行插入即可。

 elif val > p.data:if p.rchild:  # 右孩子存在p = p.rchildelse:  # 右孩子不存在时直接创建节点插入p.rchild = BiTreeNode(val)p.rchild.parent = preturn

最后插入结果为:

测试结果

对定义的函数进行测试,分别以先序,中序,后序输出。中序遍历都是从小到大输出,可以用作一种排序。

import random
class BiTreeNode:def __init__(self, data):self.data = dataself.lchild = Noneself.rchild = Noneself.parent = Noneclass BST:def __init__(self, li=None):self.root = Noneif li:for val in li:self.insert_no_rec(val)def insert(self, node, val):  # 递归定义插入if not node:node = BiTreeNode(val)elif val < node.data:node.lchild = self.insert(node.lchild, val)node.lchild.parent = nodeelif val > node.data:node.rchild = self.insert(node.rchild, val)node.rchild.parent = nodereturn nodedef insert_no_rec(self, val):p = self.rootif not p:   # 空树self.root = BiTreeNode(val)returnwhile True:if val < p.data:if p.lchild:p = p.lchildelse:p.lchild = BiTreeNode(val)p.lchild.parent = pelif val > p.data:if p.rchild:p = p.rchildelse:p.rchild = BiTreeNode(val)p.rchild.parent = preturnelse:returndef pre_order(self, root):if root:print(root.data, end=",")self.pre_order(root.lchild)self.pre_order(root.rchild)def in_order(self, root):if root:self.in_order(root.lchild)print(root.data, end=",")self.in_order(root.rchild)def post_order(self, root):if root:self.post_order(root.lchild)self.post_order(root.rchild)print(root.data, end=",")li = list(range(0, 10))
random.shuffle(li)tree = BST(li)
tree.pre_order(tree.root)  # 先序
print(" ")
tree.in_order(tree.root)   # 中序
print(" ")
tree.post_order(tree.root) # 后序

 输出结果

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

denied: requested access to the resource is denied报错解决

Docker 镜像在文件中包含一组指令&#xff0c;可在 Docker 容器中执行代码。大多数情况下&#xff0c;在创建 docker 镜像之后&#xff0c;当尝试将镜像推送到远程仓库时&#xff0c;会发生这种类型的报错“Docker denied: requested access to the resource is denied” 由于错…

Glip模型

Yolos 完全使用Transformer做目标检测 Detr 先使用CNN提取特征然后再使用transformerDetr和Yolos共同的缺点&#xff1a;需要事先知道所有的类别 Glip Zero-shot, 目标检测的类别可以不在训练类别中 目标框进行视觉编码&#xff0c;然后和文本进行匹配文本和视觉特征是通…

【MySQL | 第四篇】区分SQL语句的书写和执行顺序

文章目录 4.区分SQL语句的书写和执行顺序4.1书写顺序4.2执行顺序4.3总结4.4扩充&#xff1a;辨别having与where的异同&#xff1f;4.5聚合查询 4.区分SQL语句的书写和执行顺序 注意&#xff1a;SQL 语句的书写顺序与执行顺序不是一致的 4.1书写顺序 SELECT <字段名> …

️ IP代理实操指南:如何在爬虫项目中避免封禁和限制 ️‍♂️

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

【C++】三大特性之继承

1 继承的概念及定义 1.1 继承的概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许程序员在保持原有类特性的基础上进行扩展、增加功能&#xff0c;这样产生新的类&#xff0c;称派生类&#xff08;或子类&#xff09;。而被继承的…

力扣--深度优先算法/回溯算法216.组合总和 Ⅲ

思路分析&#xff1a; 深度优先搜索 (DFS)&#xff1a; 通过递归实现&#xff0c;尝试从数字 1 到 9 中选择可能的数字&#xff0c;构建和为 n&#xff0c;长度为 k 的组合。递归函数 dfs&#xff1a; 接收参数&#xff1a;result 为最终结果集&#xff0c;path 为当前正在生成…

STM32---IIC通信协议(含源码,小白进)

写在前面&#xff1a;在前面的学习过程中&#xff0c;我们学习了串口通信的USART&#xff08;通用同步异步收发器&#xff09;&#xff0c;本节我们将继续学习一种串行通信协议——IIC通信协议。之前我使用51单片机也分享过相关的IIC通信的知识&#xff0c;其实本质的知识是相通…

一. 并行处理与GPU体系架构-并行处理简介

目录 前言0. 简述1. 串行处理与并行处理的区别2. 并行执行3. 容易混淆的几个概念4. 常见的并行处理总结参考 前言 自动驾驶之心推出的 《CUDA与TensorRT部署实战课程》&#xff0c;链接。记录下个人学习笔记&#xff0c;仅供自己参考 本次课程我们来学习下课程第一章——并行处…

开发程序员转金融finance、量化quant的解决方案(含CPA、CFA、CQF等证书要求)

开发程序员转金融finance、量化quant的解决方案&#xff08;含CPA、CFA、CQF等证书要求&#xff09; 文章目录 一、开发程序员转金融 & 量化二、金融行业相关证书&#xff08;CPA、CFA等&#xff09;三、量化分析相关证书&#xff08;CQF等&#xff09;1、量化行业准入门槛…

AI代码加速器即将发布!傅盛:程序员会写某种代码就能找到工作的时代一去不复返了

在产品介绍视频的最后&#xff0c;代码加速器运行了Prompt生成的代码&#xff0c;是一个为傅盛庆生的祝福“彩蛋”。不得不说&#xff0c;猎户星空的程序员就做到了傅盛说的不止写代码&#xff0c;真是有点浪漫小心机在身上的。 3月6日&#xff0c;猎豹移动董事长兼CEO、猎户星…

芯片工程系列(2)传统封装(引线键合与裸片贴装)

英文缩写 Die&#xff1a;即为wafer上切割出来的芯片Wire Bonding&#xff1a;引线键合Dicing&#xff1a;晶圆切割Bias voltage&#xff1a;偏压lead frame&#xff1a;引线框架First Bond&#xff1a;一次键合Second Bond&#xff1a;二次键合PCB&#xff1a;印制电路板&…

怎么在运行框执行脚本和软件?

1.新建一个文件夹&#xff08;随便命名&#xff09; 2.右击此电脑点击属性 3.点击高级系统设置 4.点击环境变量 5.选中Path,点击编辑 6.点击编辑&#xff0c;粘贴你刚刚文件夹的地址 7.所有窗口全部点击确定 8.你可以把常用的软件快捷方式复制到文件夹里&#xff08;比如微…