【数据结构专栏】二叉搜索树(Binary Search Tree)的剖析?
文章目录
- 🧨前言
- 1、二叉搜索树的基本概念?
- 2、二叉搜索树的节点结构组成?
- 3、二叉搜索树的插入操作?
- 4、二叉搜索树的删除操作?
- 5、二叉搜索树的遍历?
- 6、二叉搜索树的性能分析?
- 🎉完整代码如下:
🧨前言
该章节主要就是明确二叉树是什么?二叉树的基本操作等。
1、二叉搜索树的基本概念?
二叉所搜索树
:它是一棵有一定规则的二叉树。它的每个节点的都遵循这两个条件:
①左子树不为空的时候,左子树的所有节点的值都小于当前节点的值。
②右子树不为空的时候,右子树的所有节点的值都大于当前节点的值。
③左右子树也必须是二叉搜索树。
二叉搜索树的性质决定了节点之间的连接方式,也就是说它可能会连接长满二叉树,亦可能为完全二叉树,但是在插入的而数据是有序的时候,那连接形式就会成一棵链表,会导致该树的高度非常高,影响操作效率。但是有一种平衡二叉搜索树,比如AVL树或红黑树,可以解决这个问题,但这里先不考虑平衡,先假设是一棵普通的二叉搜索树进行讲述。
2、二叉搜索树的节点结构组成?
⼆叉搜索树中可以⽀持插⼊相等的值,也可以不⽀持插⼊相等的值,具体看使⽤场景定义,map/set/multimap/multiset系列容器底层是⼆叉搜索树,其中map/set不⽀持插⼊相等
值,multimap/multiset⽀持插⼊相等值。
此文章的前提是使用一个普通二叉搜索树来分析,同时不包含重复值的节点
该树的节点组成有:
_key
:用于存储数据值的变量。
_left
:指向左子树的变量
_right
:指向右子树的变量
代码结构如下:
template<class K>
class BSTNode
{
public://构造函数,初始化列表给变量赋值BSTNode(const K& key):_key(key),_left(nullptr),_right(nullptr){}
public:K _key;BSTNode<K>* _left;BSTNode<K>* _right;
};
3、二叉搜索树的插入操作?
插入
:如果树为空,新节点成为根节点;否则,按照二叉搜索树的性质找到插入位置并插入新节点。
从根节点开始,比较目标值与当前节点的值:
若目标值较小,则移动到左子树;
若目标值较大,则移动到右子树。
重复上述过程,直到找到一个空位置插入新节点。
代码加注释讲解:
//插入数据函数。
bool Insert(const K& key)
{//首先,为空的时候,直接插入到根节点。if (_root == nullptr){_root = new Node(key);return true;}//根节点不为空的时候,那就先从根节点开始。Node* cur = _root;Node* parent = nullptr;//直到为空就插入while (cur){//若插入的数据值 小于 当前节点的数据值,往左走。if (key < cur->_key){//临时记录当前节点的父节点,不然后面链接不上新节点。parent = cur;cur = cur->_left;}//插入的数据值 大于 当前节点的数据值,往右走。else if (key > cur->_key){parent = cur;cur = cur->_right;}else{//走到此处说明找到一个空位置,跳出循环进行链接。return false;}}//找到cur==nullptr,此时parent节点就是最后一个节点,在插入key时候,//还需要判断一次,看插入的值比父节点值大,那么就当作右孩子,反之就当作左孩子。//由于此时cur是为空的,没必要另开空间来存储新节点,因此就把key放入该节点中cur = new Node(key);if (key < parent->_key){//插入到左边parent->_left = cur;}else{//插入到右边parent->_right = cur;}return true;
}
4、二叉搜索树的删除操作?
在实现二叉搜索树删除的接口的时候先是来说一下查找函数。
二叉搜索树的查找
:思路和插入的一样,只是需要比较一下大小。
①通过需要查找的值key
和二叉搜索树里面的每个节点的值cur->_key
进行比较。查找值key
大于 当前节点值cur->_key
,则就往当前节点cur
的右子树走。
②查找值key
小于 当前节点值cur->_key
,则就往当前节点cur
的左子树走。
③找到后就返回当前节点cur
。
代码如下:
//查找函数bool Find(const K& key){Node* cur = _root;while (cur){if (cur->_key > key){//往左走cur = cur->_left;}else if (cur->_key < key){cur = cur->_right;}else{return cur;//在判断是否存在某个值的时候,直接返回true即可。}}return false;//说明没找到。}
删除操作:
- 要删除
结点N左右孩⼦均为空
。即叶子节点,可以直接删除。- 要删除的
结点N左孩⼦位空
,右孩⼦结点不为空
。- 要删除的
结点N右孩⼦位空
,左孩⼦结点不为空
。- 要删除的
结点N左右孩⼦结点均不为空
。对应序号的解决策略:
- 把N结点的⽗亲对应孩⼦指针指向空,直接删除N结点(情况1可以当成2或者3处理,效果是⼀样的)。
- 把N结点的⽗亲对应孩⼦指针指向N的右孩⼦,直接删除N结点。
- 把N结点的⽗亲对应孩⼦指针指向N的左孩⼦,直接删除N结点。
- ⽆法直接删除N结点,因为N的两个孩⼦⽆处安放,只能⽤替换法删除。
第4种情况替换如下:
①先找到右子树的最小值节点(或左子树的最大值节点)。
②再用该最小值(或最大值)替换被删除节点的值。
③最后记得删除找到的最小值(或最大值)节点。
//删除函数bool Erase(const K& key){Node* parent = nullptr;Node* cur = _root;//先查找到对应删除的节点while (cur){if (cur->_key < key)//若当前节点的数据小于要比较的数据元素,则向右走{parent = cur;cur = cur->_right;}else if (cur->_key > key){parent = cur;cur = cur->_left;}else{//找到节点直接后就可以删除该节点//主要分为四种情况//1、左右都为空;2、左位空,右不为空;3、右位空,左不为空;4、左右都不为空// 左右为空的都可以划分到其中一个为空的情况,因为当左右都为空的时候,//下面检测到左节点为空,则就会进入左为空的程序//左为空if (cur->_left == nullptr){//先判断是否为根节点if (cur == _root){//直接把节点给到根节点_root = cur->_right;}else if (cur == parent->_left)//若是父节点的左孩子为空,则//把cur->_right给到父节点的左孩子{parent->_left = cur->_right;}else//反之就是把父节点的右孩子{parent->_right = cur->_right;}delete cur;}//右为空else if (cur->_right == nullptr){if (cur == _root){_root = cur->_left;}else if (cur == parent->_left){parent->_left = cur->_left;}else{parent->_right = cur->_left;}delete cur;}//左右都不为空else{//替代法Node* replaceParent = cur;//在删除左右都不为空的时候,需要找一个节点的值来替代,可以//是当前节点的右子树的最左节点,也可以是当前节点左子树的最右节点,//下面是用的右子树的最左节点。Node* replace = cur->_right;while (replace->_left){replaceParent = replace;replace = replace->_left;}//此处replace就是右子树的最左孩子节点//把值给到要删除的节点,即替换cur->_key = replace->_key;//此时需要判断replace节点是replaceParent节点的左孩子还是右孩子if (replace == replaceParent->_left){replaceParent->_left = replace->_right;}else{replaceParent->_right = replace->_right;}delete replace;//相当于替换后,就删除替换的那个节点}return true;}}//没找到就返回falsereturn false;}
5、二叉搜索树的遍历?
中序遍历
:对于二叉搜索树,中序遍历会按升序输出所有节点的值。
前序遍历、后序遍历
:按照特定顺序访问节点,但不保证有序性。
下面把三种遍历方式都写出来:
//中序遍历搜索二叉树
void _InOrder(Node* root)
{if (root == nullptr){return;}//左 根 右_InOrder(root->_left);cout << root->_key<<" ";_InOrder(root->_right);
}void _PrevOrder(Node* root)
{if (root == nullptr){return;}cout << root->_key << " ";_InOrder(root->_left);_InOrder(root->_right);
}void _PostOrder(Node* root)
{if (root == nullptr){return;}_InOrder(root->_left);_InOrder(root->_right); cout << root->_key << " ";
}
运行结果如下:
6、二叉搜索树的性能分析?
最好和平均情况
:树的高度为O(log n)
,插入、删除和查找操作的时间复杂度为O(log n)
。
最坏情况
:树的高度为O(n)
,时间复杂度退化为O(n)
,通常发生在插入有序数据时
,树退化为链表
。
为避免性能下降,通常使用平衡二叉搜索树,如AVL树或红黑树,以保证树的高度始终接近O(log n)。后续文章会讲述。
总结:二叉搜索树是一种高效的数据结构,适用于需要频繁进行插入、删除和查找操作的场景。理解其基本操作和实现细节是掌握更复杂数据结构和算法的基础。在实际应用中,通常需要结合平衡技术来保证性能的稳定性。
🎉完整代码如下:
#pragma once#include<iostream>
using namespace std;namespace N
{//先创建二叉树结构template<class K>class BSTNode{public://构造函数BSTNode(const K& key):_key(key),_left(nullptr),_right(nullptr){}public:K _key;BSTNode<K>* _left;BSTNode<K>* _right;};template<class K>class BSTree{typedef BSTNode<K> Node;public://插入数据函数bool Insert(const K& key){//首先,为空的时候,直接插入到根节点if (_root == nullptr){_root = new Node(key);return true;}//根节点不为空的时候,那就先从根节点开始Node* cur = _root;Node* parent = nullptr;//直到为空就插入while (cur){//若插入的数据小于节点的数据值,往左走if (key < cur->_key){//记录下一节点的父节点parent = cur;cur = cur->_left;}//大于节点的值else if (key > cur->_key){parent = cur;//往右边走cur = cur->_right;}//相等就返回else{return false;}}//找到cur==nullptr,此时parent节点就是最后一个节点,在插入key时候,//还需要判断一次,比父节点值大,就插入到右孩子处,反之就左孩子//由于cur是为空的,因此把key放入该节点中cur = new Node(key);if (key < parent->_key){//插入到左边parent->_left = cur;}else{//插入到右边parent->_right = cur;}return true;}//查找函数bool Find(const K& key){Node* cur = _root;while (cur){if (cur->_key > key){//往左走cur = cur->_left;}else if (cur->_key < key){cur = cur->_right;}else{return true;}}return false;}//删除函数bool Erase(const K& key){Node* parent = nullptr;Node* cur = _root;//先查找到对应删除的节点while (cur){if (cur->_key < key)//若当前节点的数据小于要比较的数据元素,则向右走{parent = cur;cur = cur->_right;}else if (cur->_key > key){parent = cur;cur = cur->_left;}else{//找到节点直接后就可以删除该节点//主要分为四种情况//1、左右都为空;2、左位空,右不为空;3、右位空,左不为空;4、左右都不为空// 左右为空的都可以划分到其中一个为空的情况,因为当左右都为空的时候,//下面检测到左节点为空,则就会进入左为空的程序//左为空if (cur->_left == nullptr){//先判断是否为根节点if (cur == _root){//直接把节点给到根节点_root = cur->_right;}else if (cur == parent->_left)//若是父节点的左孩子为空,//则把cur->_right给到父节点的左孩子{parent->_left = cur->_right;}else//反之就是把父节点的右孩子{parent->_right = cur->_right;}delete cur;}//右为空else if (cur->_right == nullptr){if (cur == _root){_root = cur->_left;}else if (cur == parent->_left){parent->_left = cur->_left;}else{parent->_right = cur->_left;}delete cur;}//左右都不为空else{//替代法Node* replaceParent = cur;//在删除左右都不为空的时候,需要找一个节点的值来替代,//可以是当前节点的右子树的最左节点Node* replace = cur->_right;while (replace->_left){replaceParent = replace;replace = replace->_left;}//此处replace就是右子树的最左孩子节点//把值给到要删除的节点,即替换cur->_key = replace->_key;//此时需要判断replace节点是replaceParent节点的左孩子还是右孩子if (replace == replaceParent->_left){replaceParent->_left = replace->_right;}else{replaceParent->_right = replace->_right;}delete replace;//相当于替换后,就删除替换的那个节点}return true;}}//没找到就返回falsereturn false;}void InOrder(){_InOrder(_root);}void PrevOrder(){_PrevOrder(_root);}void PostOrder(){_PostOrder(_root);}private://中序遍历搜索二叉树void _InOrder(Node* root){if (root == nullptr){return;}//左 根 右_InOrder(root->_left);cout << root->_key<<" ";_InOrder(root->_right);}void _PrevOrder(Node* root){if (root == nullptr){return;}cout << root->_key << " ";_InOrder(root->_left);_InOrder(root->_right);}void _PostOrder(Node* root){if (root == nullptr){return;}_InOrder(root->_left);_InOrder(root->_right); cout << root->_key << " ";}private://BSTNode<K>* _root=nullptr;//定义根节点Node* _root = nullptr;};
}
相关文章:
【数据结构专栏】二叉搜索树(Binary Search Tree)的剖析?
文章目录 🧨前言1、二叉搜索树的基本概念?2、二叉搜索树的节点结构组成?3、二叉搜索树的插入操作?4、二叉搜索树的删除操作?5、二叉搜索树的遍历? 6、二叉搜索树的性能分析? 🎉完整代…...
SSM全家桶 1.Maven
或许总要彻彻底底地绝望一次 才能重新再活一次 —— 24.11.20 maven在如今的idea中已经实现自动配置,不需要我们手动下载 一、Maven的简介和快速入门 Maven 是一款为 Java 项目构建管理、依赖管理的工具(软件),使用 Maven 可以自动化构建测试、打包和发…...
前端三剑客(二):CSS
目录 1. CSS 基础 1.1 什么是 CSS 1.2 语法格式 1.3 引入方式 1.3.1 行内样式 1.3.2 内部样式 1.3.3 外部样式 1.4 CSS 编码规范 2. 选择器 2.1 标签选择器 2.2 id 选择器 2.3 class 选择器(类选择器) 2.4 复合选择器 2.5 通配符选择器 3. 常用 CSS 样式 3.1 c…...
解析html将表格插入word文档
用到依赖包 <dependency><groupId>org.jsoup</groupId><artifactId>jsoup</artifactId><version>1.15.2</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweav…...
Java核心知识详解:String类、StringBuffer、数组及日期时间的全面解析
🚀 作者 :“码上有前” 🚀 文章简介 :Java 🚀 欢迎小伙伴们 点赞👍、收藏⭐、留言💬 标题 Java核心知识详解:String类、StringBuffer、数组及日期时间的全面解析 摘要 在Java中…...
唯一设备序列号(UID)、唯一产品识别码(UPI)和备份寄存器BKP
文章目录 一、唯一设备序列号UID二、唯一产品识别码UPI三、备份寄存器BKP 一、唯一设备序列号UID MCU 系列产品内置两个不同长度的唯一设备序列号,分别为 96 位的 UID(Unique device ID)和 128 位的UCID(Unique Customer ID),这两个设备序列号存放在闪存…...
Kafka - 消费者程序仅消费一半分区消息的问题
1. 问题描述 修改安全服务状态有时逻辑正常有时候逻辑不正常,排查incident服务的日志发现消息可以正常发送到 kafka topic ,但是incident-cron 服务有时候有拉取消息的日志有时候没有日志。 kafka 生产者可以将消息正常发送到 kafka topic ,…...
养老院管理系统+小程序项目需求分析文档
智慧综合养老服务平台是以业务为牵引、场景为驱动,围绕“老人”业务域,持续沉淀和打磨形成适应不同养老业务发展需要的业务能力,推动业务模式升级,为养老服务提供数字化解决方案,并依托实体站点与养老机构实现线上线下…...
K8s 下通过prometheus监控 nginx
k8s 下有两个版本的nginx ingress 分别是 ingress nginx 以及 nginx ingress Ingress-nginx 与 Nginx-ingress - LeoZhanggg - 博客园 这里我讨论的是 nginx ingress Nginx Ingress 使用Prometheus 导出数据 nginx ingress 本身支持通过支持这个提供prometheus 格式的…...
基于SpringBoot的京东绿谷旅游信息服务平台设计与实现(源码+定制+开发)
博主介绍: ✌我是阿龙,一名专注于Java技术领域的程序员,全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师,我在计算机毕业设计开发方面积累了丰富的经验。同时,我也是掘金、华为云、阿里云、InfoQ等平台…...
使用Redis生成全局唯一id
为了生成一个符合要求的分布式全局ID,我们可以使用 StringRedisTemplate 来实现。这个ID由三部分组成: 符号位(1 bit):始终为0,表示正数。时间戳(31 bit):表示从某个起始…...
pytorch自定义算子导出onnx
文章目录 1、为什么要自定义算子?2、如何自定义算子3、自定义算子导出onnx4、example1、重写一个pytorch 自定义算子(实现自定义激活函数)2、现有算子上封装pytorch 自定义算子(实现动态放大超分辨率模型) 1、为什么要…...
从搭建uni-app+vue3工程开始
技术栈 uni-app、vue3、typescript、vite、sass、uview-plus、pinia、axios 一、项目搭建 1、创建以 typescript 开发的工程 npx degit dcloudio/uni-preset-vue#vite-ts my-vue3-project2、安装sass npm install -D sass// 安装sass-loader,注意需要版本10&…...
波点音乐自动点击
波点音乐 import uiautomator2 as u2 import time import sys import os# 动态点击时间,打印剩余时间 def dynamic_sleep(seconds):wait_time secondsfor i in range(wait_time):print(f"Waiting... {wait_time - i} seconds remaining")sys.stdout.flu…...
【一篇搞定配置】wget 下载与安装(Window)
🌈 个人主页:十二月的猫-CSDN博客 🔥 系列专栏: 🏀各种软件安装与配置_十二月的猫的博客-CSDN博客 💪🏻 十二月的寒冬阻挡不了春天的脚步,十二点的黑夜遮蔽不住黎明的曙光 目录 1.…...
2025年春招修订版《C/C++笔面试系列》(1) C语言经典笔面试题(上)
C语言是嵌入式开发的常用语言,也是主要语言,很多企业在招聘嵌入式软件工程师时,C语言的熟练程度是一个重要考察点。笔试也是以C语言为主,所以想要拿到面试机会,还得通过C语言笔试,本专题总结了各大企业C语言…...
【042C】基于51RFID门禁系统(LCD12864显示)【Proteus仿真+Keil程序+报告+原理图】
☆、设计硬件组成:51单片机最小系统RFID读卡器4*4矩阵键盘AT24C02存储芯片LCD12864液晶显示继电器蜂鸣器LED灯。 1、设计采用STC89C52、AT89C52、AT89S52作为主控芯片,采用LCD12864液晶显示屏实时显示门禁系统; 2、系统集成两种解锁方式&am…...
scratch二次开发:blockly工作区垃圾桶和进度条的隐藏和显示
大家好,我是小黄。 本期给大家介绍的内容是实现blockly工作区的垃圾桶和进度条的显示和隐藏实现。 本次基于的项目源码大家可以关注小黄回复垃圾桶自行获取。 一.垃圾桶的显示和实现。 在blockly中,我们进行块的删除的时候最常用的两种方法是…...
【STM32】MPU6050初始化常用寄存器说明及示例代码
一、MPU6050常用配置寄存器 1、电源管理寄存器1( PWR_MGMT_1 ) 此寄存器允许用户配置电源模式和时钟源。 DEVICE_RESET :用于控制复位的比特位。设置为1时复位 MPU6050,内部寄存器恢复为默认值,复位结束…...
LDR6020驱动的Type-C接口显示器解决方案
一、引言 随着科技的飞速发展,Type-C接口凭借其高速数据传输、强大的电力传输能力以及便捷的正反可插设计,正逐渐成为现代电子设备的主流接口标准。在显示器领域,Type-C接口的引入不仅简化了线缆连接,还为用户带来了更丰富的功能…...
Spring Boot + Android 实现登录功能
在移动互联网的今天,许多应用需要通过移动端实现与服务器的交互功能,其中登录是最常见且基础的一种功能。通过登录,用户可以获得独特的身份标识,从而访问特定的资源或服务。本篇博客将详细介绍如何使用 Spring Boot 和 Android 实…...
【通俗理解】边际化技巧在概率论中的应用——从公式到实例
【通俗理解】边际化技巧在概率论中的应用——从公式到实例 关键词提炼 #边际化技巧 #概率论 #联合概率 #条件概率 #积分计算 #概率分布 #贝叶斯推断 第一节:边际化技巧的类比与核心概念【尽可能通俗】 边际化技巧,就像是你在一个复杂的概率迷宫中&am…...
Chen_AdaMV-MoE_Adaptive_Multi-Task_Vision_Mixture-of-Experts 译文
摘要 稀疏激活的专家混合(MoE)正在成为多任务学习(MTL)的一个有前途的范例。 MoE 不是将多个任务的知识压缩到单个模型中,而是分离参数空间,仅利用给定任务类型及其输入的相关模型片段,从而提供…...
多线程下使用数据库 - 20241124
问题 并发性较低,每秒千次但是较高一致性,比如利用数据库中的数据进行判断是否执行某个操作 存在的问题是,如何只锁定判断相关的数据,而不影响数据库操作无关数据。脏读/不可重复读/幻读 解决方案 利用数据InnoDB引擎的LBCC和…...
GMAN解读(论文+代码)
一、注意力机制 注意力机制与传统的卷积神经网络不同的是,前者擅长捕获全局依赖和长程关系,权重会动态调整。而后者对于所有特征都使用同一个卷积核。关于更多注意力机制内容,详见: 注意力机制、自注意力机制、多头注意力机制、通…...
《文件操作》
一 . 文本文件和二进制文件 根据数据的组织形式,数据文件被分为了二进制文件和文本文件 数据在内存中是以二进制的形式存储,如果不加转换的输出到外存的文件中,就是二进制文件。 如果要求在外存上以ASCII 码的形式存储,则需要再存…...
【君正T31开发记录】8.了解rtsp协议及设计模式
前边搞定了驱动,先不着急直接上手撸应用层的代码,先了解一下大致要用到的东西。 设计PC端先用vlc rtsp暂时H264编码(vlc好像不支持h265,这个后边我试试)的视频流,先需要支持上rtsp server,了解rtsp协议是必…...
C++菜鸟教程 - 从入门到精通 第三节
上节课的题 上节课的题,大家都做出来了吗? 看一下这道题: 题目描述 N!1*2*...*N; 例5!1*2*3*4*5120. 编程求1!2!3!...N!. 输入 输入一行,只有一个整数n (1<n<10) 输出 输出只有一行(这意味着末尾有一个回车符号),包括1…...
原生JS和CSS,HTML实现开屏弹窗
开屏弹窗常应用于打开游戏,或者打开网站的时候,跳出来在正中间,来显示一些信息,并可以设置今日不再显示 CSS代码如下 <style>#box {width: 100vw;height: 100vh;background-color: rgba(0, 0, 0, 0.2);position: relative…...
微软发布Win11 24H2系统11月可选更新KB5046740!
系统之家11月22日报道,微软针对Win11 24H2系统推出2024年11月最新可选更新补丁KB5046740,更新后系统版本后升至26100.2454,此次更新后修复当应用程序以PDF和XLSX格式导出图表对象时停止响应、无法使用API查找旋转信息等问题。以下小编将给大家…...
【Rabbitmq篇】高级特性----TTL,死信队列,延迟队列
目录 一.TTL 1.设置消息的TTL 2.设置队列的TTL 3.俩者区别 二.死信队列 定义: 消息成为死信的原因: 1.消息被拒绝(basic.reject 或 basic.nack) 2.消息过期(TTL) 3.队列达到最大长度 编辑 …...
【Linux】gcc/g++使用
编译 我们知道,gcc只能编译C,g既能编译C,也能编译C。 由于两者的选项是相同的,这里我们使用gcc来说明。 这就是一个我们在linux中gcc编译一段代码后会自动生成一个a.out为名的可执行文件,然后我们./a.out,…...
IDEA2023 SpringBoot整合MyBatis(三)
一、数据库表 CREATE TABLE students (id INT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(100) NOT NULL,age INT,gender ENUM(Male, Female, Other),email VARCHAR(100) UNIQUE,phone_number VARCHAR(20),address VARCHAR(255),date_of_birth DATE,enrollment_date DATE,cours…...
Java网络编程 - cookiesession
cookie 之前学习了 Okhttp3 库可以调用API、抓取网页、下载文件。但是这些操作都是不要求登录的,如果 API、网页、文件等内容要求登录才能访问,就需要学习新的 cookie 相关的知识。 下面以豆瓣为例,使用 Java 程序读取“我的豆瓣”页面内容…...
100.【C语言】数据结构之二叉树的堆实现(顺序结构) 1
目录 1.顺序结构 2.示意图 编辑 从物理结构还原为逻辑结构的方法 3.父子节点编号的规律 4.顺序存储的前提条件 5.堆的简介 堆的定义 堆的两个重要性质 小根堆和大根堆 6.堆的插入 7.堆的实现及操作堆的函数 堆的结构体定义 堆初始化函数HeapInit 堆插入元素函…...
《Python基础》之循环结构
目录 简介 一、for循环 1、基本语法与作用 2、使用 range() 函数配合 for 循环 3、嵌套的for循环 二、while循环 1、基本语法与作用 2、while 循环嵌套 (1)、while循环与while循环嵌套 (2)、while循环与for循环嵌套 简介 …...
使用JDBC操作数据库
文章目录 使用JDBC操作数据库1. JDBC访问数据库步骤2. Statement与PreparedStatement区别3. JDBC的内容4. JDBC封装4.1 为什么进行JDBC封装4.2 实现JDBC封装4.3 什么是DAO4.4 配置数据库访问参数4.5 配置数据库连接池使用之JNDI的方式 5. 单例模式5.1 懒汉模式5.2 饿汉模式 使用…...
轻松解析 PDF 文档:深入了解 Python 的 pdfplumber 库
轻松解析 PDF 文档:深入了解 Python 的 pdfplumber 库 PDF 是一种常见的文件格式,广泛用于报告、文档、表单等领域。然而,如何高效解析 PDF 内容(尤其是文本和表格),一直是开发者面临的挑战。pdfplumber 是…...
实验五 时域采样与频域采样
时域采样理论的验证 【实例3-1】近似绘制x (n) R4n 在(0,2 π \pi π ) 上的幅频响应曲线( F T [ x ( n ) ] FT[x(n)] FT[x(n)] )。 x [1, 1, 1, 1]; N 64; xk fft(x, N); figure; subplot(2, 1, 1); stem(0:3, x, .); subplot(2, 1, 2); k 0:N-1; plot(2*k/N, abs(x…...
爬虫cookie反爬------加速乐(jsl)
加速乐 反爬虫技术:加速乐采用了包括OB混淆、动态加密算法和多层Cookie获取等高级反爬虫技术,确保整体校验的严密性。关键校验字段位于Cookie中的 __jsl_clearance_s,其验证过程通常涉及三次关键的请求,有效抵御恶意爬虫的侵扰。…...
设计模式——解释器模式
定义: 解释器模式是一种行为设计模式,它给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。在这种模式中,通常会将一个复杂的表达式(如数学表达…...
sorted()函数
sorted(iterable, keyNone, reverseFalse)iterable: 需要排序的可迭代对象(如列表、元组、字符串等)。 key: 一个函数,用于从每个元素中提取排序的依据。如果未指定,默认直接比较元素本身。 reverse: 一个布尔值,Tru…...
动静态分析
静态分析 获取哈希值: 查壳: 导出函数: 获取资源信息: 通过发现dos头和pe头,来确定它是个可执行程序。 动态分析...
2024年信号处理与神经网络应用国际学术会议(SPNNA 2024)
重要信息 会议时间:2024年12月13-15日 会议地点:中国武汉 会议官网:www.spnna.org 会议简介 2024年信号处理与神经网络应用国际学术会议(SPNNA 2024)将于2024年12月13日至15日在中国武汉召开。本次会议旨在为全球研…...
winfrom快速自适应
在软件界面设计中,我们通常需要添加各种布局器和规则来实现界面布局,但对于不太熟练的工程师来说,这可能存在一定难度。这里要分享一种自适应布局的方法,它可以根据界面比例自动缩放内容控件,在较短时间内完成软件布局…...
VMware16安装macOS12【详细教程】
因为在应用上线IOS应用商店时,需要用到mac系统进行,于是就在VMware16pro虚拟机进行安装macOS12系统,安装的过程做了一个记录,希望对你有所帮助! 前言 首先需要下载好下面工具: VMware workstation pro 16…...
【设计模式】【创建型模式(Creational Patterns)】之单例模式
单例模式是一种常用的创建型设计模式,其目的是确保一个类只有一个实例,并提供一个全局访问点。 单例模式的原理 单例模式的核心在于控制类的实例化过程,通常通过以下方式实现: 私有化构造函数,防止外部直接实例化。…...
【1.2 Getting Started--->Installation Guide】
NVIDIA TensorRT DOCS 此 NVIDIA TensorRT 10.6.0 安装指南提供安装要求、TensorRT 包中包含的内容列表以及安装 TensorRT 的分步说明。 安装指南 摘要: 本 NVIDIA TensorRT 10.3.0 安装指南提供了安装要求、TensorRT 软件包中包含的内容列表以及安装 TensorRT 的…...
Vue 中 data 属性为函数的深度剖析:原理、区别与实践
在 Vue.js 中,data 属性通常是一个 函数 而不是一个对象,这背后有一系列设计上的原因和原理,尤其是与 Vue 的组件系统、实例化机制、以及响应式数据的管理有关。下面我将详细解答这个问题,并结合实际项目示例和代码分析,进行全面讲解。 1. Vue 中 data 为什么是一个函数而…...
【漏洞复现】H3C 用户自助服务平台 dynamiccontent.properties.xhtml 远程命令执行
免责声明: 本文旨在提供有关特定漏洞的信息,以帮助用户了解潜在风险。发布此信息旨在促进网络安全意识和技术进步,并非出于恶意。读者应理解,利用本文提到的漏洞或进行相关测试可能违反法律或服务协议。未经授权访问系统、网络或应用程序可能导致法律责任或严重后果…...