当前位置: 首页 > news >正文

【数据结构】二叉搜索树——二叉搜索树的概念和介绍、二叉搜索树的简单实现、二叉搜索树的增删查改

文章目录

  • 二叉搜索树
    • 1. 二叉搜索树的概念和介绍
    • 2. 二叉搜索树的简单实现
      • 2.1二叉搜索树的插入
      • 2.2二叉搜索树的查找
      • 2.3二叉搜索树的遍历
      • 2.4二叉搜索树的删除
      • 2.5完整代码和测试

二叉搜索树

1. 二叉搜索树的概念和介绍

  二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:

  (1)若它的左子树不为空,则左子树上所有节点的值都小于根节点的值

  (2)若它的右子树不为空,则右子树上所有节点的值都大于根节点的值

  (3)它的左右子树也分别为二叉搜索树

在这里插入图片描述

  二叉搜索树(Binary Search Tree)的每个节点包含三个属性:键(key)、左孩子(lchild)和右孩子(rchild)。 键用于存储节点的值,左孩子和右孩子分别指向左子树和右子树的根节点。

  二叉搜索树的结构类似于一个倒置的树,最底层的节点位于树的顶部,每个节点都有一个键值,并且每个节点的左子树上的所有节点的键值都小于该节点的键值,而右子树上的所有节点的键值都大于该节点的键值。这种结构使得二叉搜索树在处理有序数据时非常高效。

  基于以上性质,二叉搜索树在查找、插入和删除操作上具有较好的效率,时间复杂度为O(logn)。

  基于二叉搜索树的特殊结构,二叉搜索树的中序遍历(Inorder Traversal)按照左子树、根节点、右子树的顺序遍历二叉树,它会按照从大到小的顺序输出二叉树中的所有元素。

  以下这颗二叉搜索树的中序遍历结果:1 3 4 6 7 8 10 13 14
在这里插入图片描述
             

2. 二叉搜索树的简单实现

  和之前的二叉树实现类似,二叉搜索树的实现只需要在二叉树的实现基础上,将左右元素根据和根节点的大小,重新考虑排列顺序即可。

  定义二叉搜索树的节点:

//搜索二叉树创建节点
template<class K>
struct BSTreeNode
{//左右节点和节点值keyBSTreeNode<K>* _left;BSTreeNode<K>* _right;K _key;//二叉树节点构造函数BSTreeNode(const K& key):_left(nullptr), _right(nullptr), _key(key){}
};

  定义二叉搜索树类:

//创建二叉搜索树
template<class K>
class BSTree
{//便于书写BNode节点typedef BSTreeNode<K> BNode;public://二叉搜索树构造函数BSTree():_root(nullptr){}private:BNode* _root;
};

             

2.1二叉搜索树的插入

  二叉搜索树的插入过程可以分为以下步骤:

  (1)如果二叉搜索树为空,创建一个新的节点,并将待插入关键字放入新节点的数据域。将新节点作为根节点,左右子树均为空。

  (2)如果二叉搜索树非空,将待查找关键字与根节点关键字进行比较。如果小于根节点关键字,则将待查找关键字插入左子树中;如果大于根节点关键字,则将待查找关键字插入右子树中。

  重复上述步骤,直到找到合适的位置插入待插入的关键字。

  在插入过程中,需要保持二叉搜索树的性质:任意节点的左子树的所有节点的值都小于该节点的值,右子树的所有节点的值都大于该节点的值。如果插入后破坏了这种性质,需要进行调整。

在这里插入图片描述

  非递归的实现:

//二叉树插入节点
bool BSInsert(const K& key)
{//如果该树为空树,直接创建节点if (_root == nullptr){_root = new BNode(key);return true;}//找到二叉树所在的节点BNode* parent = nullptr;BNode* cur = _root;while (cur){if (cur->_key < key){parent = cur;cur = cur->_right;}else if (cur->_key > key){parent = cur;cur = cur->_left;}else{return false;}}//插入节点cur = new BNode(key);if (parent->_key > key){parent->_left = cur;}else {parent->_right = cur;}return true;
}


  递归的实现:

bool _BSInsertR(BNode*& root, const K& key)//这里传&,直接可以得到地址
{if (root == nullptr){root = new BNode(key);return true;}if (root->_key < key){_BSInsertR(root->_right, key);}else if (root->_key > key){_BSInsertR(root->_left, key);}else{return false;}
}

             

2.2二叉搜索树的查找

  二叉搜索树的查找实现过程可以分为以下步骤:

  (1)将待查找关键字与根节点关键字进行比较。如果相等,则找到了目标关键字,查找结束。

  (2)如果待查找关键字小于根节点关键字,则将待查找关键字放入左子树中继续查找。

  (3)如果待查找关键字大于根节点关键字,则将待查找关键字放入右子树中继续查找。

  重复上述步骤,直到找到目标关键字,或者搜索到了空节点(表示未找到目标关键字)。

  在查找过程中,由于二叉搜索树是基于二分的思想,所以每次比较都可以排除一半的搜索空间,因此时间复杂度为O(logn)。

在这里插入图片描述

  非递归实现:

//查找二叉树的节点
bool BSFind(const K& key)
{BNode* 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 _BSFindR(BNode* root, const K& key)
{if (root == nullptr){return false;}if (root->_key < key){return _BSFindR(root->_right, key);}else if (root->_key > key){return _BSFindR(root->_left, key);}else{return true;}
}

             

2.3二叉搜索树的遍历

  二叉搜索树常使用中序遍历,而不是前序遍历和后序遍历。

  因为中序遍历的特点是先访问左子树,然后访问根节点,最后访问右子树。 在访问左子树时,先访问左子树的左子树,再访问左子树的右子树;在访问右子树时,先访问右子树的左子树,再访问右子树的右子树。

  二叉搜索树中序遍历的结果是按照从小到大的顺序输出二叉搜索树中的所有元素。

  二叉搜索树的中序遍历过程可以分为以下步骤:

  (1)首先遍历左子树,访问左子树中的所有节点,并按照中序遍历的顺序递归地访问它们的右子树。

  (2)然后访问根节点。

  (3)最后遍历右子树,访问右子树中的所有节点,并按照中序遍历的顺序递归地访问它们的左子树。

  递归实现:

void _BSInOrder(BNode* root)
{if (root == nullptr){return;}_BSInOrder(root->_left);printf("%d ", root->_key);_BSInOrder(root->_right);
}

             

2.4二叉搜索树的删除

  二叉搜索树的删除操作可以按照以下步骤实现:

  (1)首先,找到要删除的节点。可以通过中序遍历或者二分查找等方式找到要删除的节点。

  (2)如果要删除的节点是叶子节点(没有子节点),直接将该节点从二叉搜索树中删除即可。

  (3)如果要删除的节点只有一个子节点,将该节点的子节点与其父节点相连,删除该节点即可。

  (4)如果要删除的节点有两个子节点,需要找到该节点的左子树中的最大节点(或者右子树中的最小节点),用该节点代替要删除的节点的位置,然后删除该最小(或最大)节点。

  在实现删除操作时,需要注意保持二叉搜索树的性质,即任意节点的左子树的所有节点的值都小于该节点的值,右子树的所有节点的值都大于该节点的值。同时,删除操作可能会导致二叉搜索树的平衡被破坏,需要进行相应的调整操作。

  (1)当没有叶子结点,或者只有一个子节点的情况:
在这里插入图片描述

  (2)当左右都有子节点的情况:
在这里插入图片描述

  非递归实现:

//删除二叉树中的节点
bool BSErase(const K& key)
{BNode* cur = _root;BNode* parent = nullptr;//先要找到所删除的节点while (cur){if (cur->_key > key){parent = cur;cur = cur->_left;}else if (cur->_key < key){parent = cur;cur = cur->_right;}else//找到了所要删除的节点{if (cur->_left == nullptr)//当左节点为空节点{if (cur == _root)//cur为根节点{_root = cur->_right;}else//cur不为空节点{if (parent->_right == cur){parent->_right = cur->_right;}else{parent->_left = cur->_right;}}}else if(cur->_right==nullptr)//当右节点为空节点{if (cur == _root)//cur为空节点{_root = cur->_left;}else//cur不为空节点{if (parent->_right == cur){parent->_right = cur->_left;}else{parent->_left = cur->_left;}}}else//当左右节点都不为空节点{//找代替节点BNode* parent = cur;BNode* leftMax = cur->_left;while (leftMax->_right){parent = leftMax;leftMax = leftMax->_right;}swap(cur->_key, leftMax->_key);if (parent->_left == leftMax){parent->_left = leftMax->_left;}else{parent->_right = leftMax->_left;}cur=leftMax;}delete cur;return true;}}return false;
}

  递归实现:

bool _BSEraseR(BNode* &root, const K& key)
{if (root == nullptr){return false;}if (root->_key < key){_BSEraseR(root->_right, key);}else if (root->_key > key){_BSEraseR(root->_left, key);}else{BNode* del = root;//1.左为空//2.右为空//3.左右都不为空if (root->_left == nullptr){root = root->_right;}else if (root->_right == nullptr){root = root->_left;}else{BNode* leftMax = root->_left;while (leftMax->_right){leftMax = leftMax->_right;}swap(root->_key, leftMax->_key);return _BSEraseR(root->_left, key);}delete del;return true;}
}

             

2.5完整代码和测试

  完整代码:

#pragma once//搜索二叉树创建节点
template<class K>
struct BSTreeNode
{//左右节点和节点值keyBSTreeNode<K>* _left;BSTreeNode<K>* _right;K _key;//二叉树节点构造函数BSTreeNode(const K& key):_left(nullptr), _right(nullptr), _key(key){}
};//创建搜索二叉树
template<class K>
class BSTree
{//便于书写BNode节点typedef BSTreeNode<K> BNode;public://搜索二叉树构造函数BSTree():_root(nullptr){}//二叉树插入节点bool BSInsert(const K& key){//如果该树为空树,直接创建节点if (_root == nullptr){_root = new BNode(key);return true;}//找到二叉树所在的节点BNode* parent = nullptr;BNode* cur = _root;while (cur){if (cur->_key < key){parent = cur;cur = cur->_right;}else if (cur->_key > key){parent = cur;cur = cur->_left;}else{return false;}}//插入节点cur = new BNode(key);if (parent->_key > key){parent->_left = cur;}else {parent->_right = cur;}return true;}//查找二叉树的节点bool BSFind(const K& key){BNode* 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 BSErase(const K& key){BNode* cur = _root;BNode* parent = nullptr;//先要找到所删除的节点while (cur){if (cur->_key > key){parent = cur;cur = cur->_left;}else if (cur->_key < key){parent = cur;cur = cur->_right;}else//找到了所要删除的节点{if (cur->_left == nullptr)//当左节点为空节点{if (cur == _root)//cur为根节点{_root = cur->_right;}else//cur不为空节点{if (parent->_right == cur){parent->_right = cur->_right;}else{parent->_left = cur->_right;}}}else if(cur->_right==nullptr)//当右节点为空节点{if (cur == _root)//cur为空节点{_root = cur->_left;}else//cur不为空节点{if (parent->_right == cur){parent->_right = cur->_left;}else{parent->_left = cur->_left;}}}else//当左右节点都不为空节点{//找代替节点BNode* parent = cur;BNode* leftMax = cur->_left;while (leftMax->_right){parent = leftMax;leftMax = leftMax->_right;}swap(cur->_key, leftMax->_key);if (parent->_left == leftMax){parent->_left = leftMax->_left;}else{parent->_right = leftMax->_left;}cur=leftMax;}delete cur;return true;}}return false;}//二叉树的中序遍历void BSInOrder(){_BSInOrder(_root);cout << endl;}//递归实现二叉树的查找bool BSFindR(const K& key){return _BSFindR(_root, key);}//递归实现二叉树的插入节点bool BSInsertR(const K& key){return _BSInsertR(_root, key);}//递归实现二叉树的删除节点bool BSEraseR(const K& key){return _BSEraseR(_root, key);}private://递归二叉树删除的封装实现bool _BSEraseR(BNode* &root, const K& key){if (root == nullptr){return false;}if (root->_key < key){_BSEraseR(root->_right, key);}else if (root->_key > key){_BSEraseR(root->_left, key);}else{BNode* del = root;//1.左为空//2.右为空//3.左右都不为空if (root->_left == nullptr){root = root->_right;}else if (root->_right == nullptr){root = root->_left;}else{BNode* leftMax = root->_left;while (leftMax->_right){leftMax = leftMax->_right;}swap(root->_key, leftMax->_key);return _BSEraseR(root->_left, key);}delete del;return true;}}//递归二叉树插入的封装实现bool _BSInsertR(BNode*& root, const K& key)//这里传&,直接可以得到地址{if (root == nullptr){root = new BNode(key);return true;}if (root->_key < key){_BSInsertR(root->_right, key);}else if (root->_key > key){_BSInsertR(root->_left, key);}else{return false;}}//递归二叉树查找的封装实现bool _BSFindR(BNode* root, const K& key){if (root == nullptr){return false;}if (root->_key < key){return _BSFindR(root->_right, key);}else if (root->_key > key){return _BSFindR(root->_left, key);}else{return true;}}//为了递归实现,进行一层封装void _BSInOrder(BNode* root){if (root == nullptr){return;}_BSInOrder(root->_left);printf("%d ", root->_key);_BSInOrder(root->_right);}private:BNode* _root;
};


  简单测试:

#define _CRT_SECURE_NO_WARNINGS 1#include<iostream>
using namespace std;#include"BinarySearchTree.h"void BSTree_test1()
{BSTree<int> t;t.BSInsert(5);t.BSInsert(8);t.BSInsert(6);t.BSInsert(1);t.BSInsert(3);t.BSInsert(2);t.BSInsert(4);t.BSInOrder();cout << "是否存在二叉树的值为1:";if (t.BSFind(1))cout << "存在";else cout << "不存在";cout << endl;int arr[] = { 5,3,1,2,4,9,8,6,7,10 };BSTree<int> t1;for (auto e : arr){t1.BSInsert(e);}t1.BSInOrder();t1.BSErase(3);t1.BSInOrder();cout << "是否存在二叉树的值为1:";if (t1.BSFindR(1))cout << "存在";else cout << "不存在";cout << endl;t1.BSInsertR(11);t1.BSInOrder();t1.BSEraseR(11);t1.BSInOrder();}int main()
{BSTree_test1();return 0;
}

这里就是数据结构中二叉搜索树的基本介绍了😉
如有错误❌望指正,最后祝大家学习进步✊天天开心✨🎉

             

相关文章:

【数据结构】二叉搜索树——二叉搜索树的概念和介绍、二叉搜索树的简单实现、二叉搜索树的增删查改

文章目录 二叉搜索树1. 二叉搜索树的概念和介绍2. 二叉搜索树的简单实现2.1二叉搜索树的插入2.2二叉搜索树的查找2.3二叉搜索树的遍历2.4二叉搜索树的删除2.5完整代码和测试 二叉搜索树 1. 二叉搜索树的概念和介绍 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&…...

通过linux定时任务删除es日志索引

能过linux定时任务删除es日志索引 项目用上了elk&#xff0c;产生的日志索引要定时&#xff0c;其一个方法&#xff0c;通过linux定时任务&#xff0c;调用es接口删除索引。 #!/bin/bash #删除ELK30天前的日志 #计算索引名称包含的日期&#xff0c;比如这里是 %Y.%m.%d (2023…...

【跟小嘉学 Rust 编程】二十二、常用 API

系列文章目录 【跟小嘉学 Rust 编程】一、Rust 编程基础 【跟小嘉学 Rust 编程】二、Rust 包管理工具使用 【跟小嘉学 Rust 编程】三、Rust 的基本程序概念 【跟小嘉学 Rust 编程】四、理解 Rust 的所有权概念 【跟小嘉学 Rust 编程】五、使用结构体关联结构化数据 【跟小嘉学…...

【ES6】Class中this指向

先上代码&#xff1a; 正常运行的代码&#xff1a; class Logger{printName(name kexuexiong){this.print(hello ${name});}print(text){console.log(text);} }const logger new Logger(); logger.printName("kexueixong xiong");输出&#xff1a; 单独调用函数p…...

Python 编程竟然如此幽默!揭秘程序员们的搞笑日常,快来看看吧!

食用原文效果更佳&#xff0c;原文链接 Python 编程竟然如此幽默&#xff01;揭秘程序员们的搞笑日常&#xff0c;快来看看吧&#xff01; 在 Python 编程的世界里&#xff0c;充满了智慧与创造力。 当然&#xff0c;也少不了轻松幽默的段子&#xff0c;这些段子让程序员们在…...

Linux c++开发-03-使用CMake组织工程

一、简单文件的编译 有如下的目录结构&#xff1a; 其中 helloworld.cpp如下&#xff1a; #include <iostream> using namespace std; int main() {printf("hello world my name is Ty!");return 0; }CMakeLists.txt如下&#xff1a; cmake_minimum_requir…...

【C++】函数重载 ④ ( 函数指针定义的三种方式 | 直接定义函数指针 | 通过 函数类型 定义 函数指针 | 通过 函数指针类型 定义 函数指针 )

文章目录 一、函数指针定义方法1、直接定义函数指针2、通过 函数类型 定义 函数指针3、通过 函数指针类型 定义 函数指针4、代码示例 - 不同方式定义函数指针 博客总结 : 重载函数 : 使用 相同 的 函数名 , 定义 不同 的 函数参数列表 ;判定标准 : 只有 函数参数 的 个数 / 类…...

异常-java

目录 一、异常的概念和体系结构 1.1 异常的概念 1.2 异常的体系结构 1.3 异常的分类 二、异常的处理 2.1 防御式编程 2.2 异常抛出 2.3 异常捕获 2.4 异常处理流程 三、自定义异常类 一、异常的概念和体系结构 1.1 异常的概念 程序员在开发过程中&#xff0c;想要将代码写得…...

软件测试/测试开发丨Selenium Web自动化测试 高级控件交互方法

点此获取更多相关资料 本文为霍格沃兹测试开发学社学员学习笔记分享 原文链接&#xff1a;https://ceshiren.com/t/topic/27045 一、使用场景 使用场景对应事件复制粘贴键盘事件拖动元素到某个位置鼠标事件鼠标悬停鼠标事件滚动到某个元素滚动事件使用触控笔点击触控笔事件&am…...

深入Go语言:进阶指南

深入Go语言&#xff1a;进阶指南 欢迎来到深入Go语言的进阶指南。如果你已经熟悉Go语言的基础知识&#xff0c;想要更深入地探索这门语言的高级特性和技巧&#xff0c;那么本篇博客将为你提供有关Go语言的更多深入内容。 Go语言的并发编程 Go语言以其强大的并发支持而闻名。…...

FOXBORO FBM232 P0926GW 自动化控制模块

Foxboro FBM232 P0926GW 是 Foxboro&#xff08;福克斯博罗&#xff09;自动化控制系统的一部分&#xff0c;通常用于监测和控制工业过程。以下是关于这种类型的自动化控制模块可能具有的一些常见功能&#xff1a; 数字输入通道&#xff1a; FBM232 P0926GW 控制模块通常具有多…...

【C# Programming】编程入门:方法和参数

一、方法 1、方法的定义 由一系列以执行特定的操作或计算结果语句组成。方法总是和类关联&#xff0c;类型将相关的方法分为一组。 方法名称 形参和实参(parameter & argument)返回值 2、命名空间 一种分类机制&#xff0c;用于组合功能相关的所有类型。命名空间是分级…...

【报错】 Cannot create property ‘showColumn‘ on number ‘-1‘

1、报错原因&#xff1a; 代码如下&#xff1a; 报错是因为&#xff1a;this.findObject(this.option.column, "thirdId")是一个number &#xff0c;没有.showColumn属性 2、修改代码 将其变成object属性就行了...

C++容器string的运用和注意

介绍 首先&#xff0c;先说明&#xff0c;string在C的string头文件中定义&#xff0c;而在C语言中的字符串就是字符数组&#xff0c;在C中&#xff0c;string容器相当于C语言中的字符数组&#xff0c;string比C语言中的字符数组更为好用&#xff0c;如&#xff1a;C中cin/cout可…...

用对工具,你的全渠道电子商务业务就成功了一半

希望将全渠道电子商务纳入您的业务战略&#xff0c;但不确定从哪里开始&#xff1f;我们为您提供保障。这篇文章将指导您了解全渠道商务的基础知识&#xff0c;以及它与多渠道方法的区别&#xff0c;还将探讨利用全渠道方法的众多好处&#xff0c;并讨论企业如何通过全渠道客户…...

TDengine学习(1):采集量(Metric),标签(label),数据采集点,表,超级表,子表、库

因为TDengine是面向物联网诞生的一种数据库&#xff0c;所以在一些概念的命名上有一点相应的特色。 一、数据采集点 比如需要对一辆高铁上的各种信息进行采集&#xff0c;采集信息存入数据库中。我们可以对高铁车厢内的一些数据进行采集&#xff0c;比如&#xff1a;车厢内温…...

【洛谷 P1029】[NOIP2001 普及组] 最大公约数和最小公倍数问题 题解(辗转相除法)

[NOIP2001 普及组] 最大公约数和最小公倍数问题 题目描述 输入两个正整数 x 0 , y 0 x_0, y_0 x0​,y0​&#xff0c;求出满足下列条件的 P , Q P, Q P,Q 的个数&#xff1a; P , Q P,Q P,Q 是正整数。 要求 P , Q P, Q P,Q 以 x 0 x_0 x0​ 为最大公约数&#xff0c;以…...

Golang 中的 errors 包详解:返回自定义 error 类型

之前的文章《Golang 中的 errors 包详解》详细讲解了 errors 包的主要类型和函数&#xff0c;以及它们的使用方法。本文结合之前讲解的知识&#xff0c;来讲解一下根据自己或团队的项目要求如何返回自定义的 error 类型。 为什么需要自定义 error 类型&#xff1f; 在日常开发…...

C#开发的OpenRA游戏之信标按钮

前面已经分析了两个按钮:变卖和维修,接着下来就是分析信标按钮,这个按钮使用是比较少,但是对于多人游戏时,使用这个信号就很方便同盟军过来查看和帮助了,相当于一个朋友之间共同查看的地址。当你经过同盟标记的标志时,就会听到beacon detected,检测到信标,这就是你的盟…...

16字节协议的串口通信

1.协议要求 协议为帧传输&#xff0c;一共16字节。主要是2字节的固定帧头 EB 90&#xff0c;2字节的帧计数(用来计数发出的帧),10字节的数据和2字节的校验位 帧头&#xff1a;2字节&#xff0c;固定值 8’HEB、8’H90 帧计数&#xff1a;2字节&#xff0c;用来说明发出去帧是…...

短视频创作新利器:Sonic数字人工作流生成口型自然的表情包视频

短视频创作新利器&#xff1a;Sonic数字人工作流生成口型自然的表情包视频 1. 数字人视频创作新趋势 在短视频内容爆炸式增长的今天&#xff0c;创作者们面临着一个共同挑战&#xff1a;如何高效产出高质量视频内容。传统视频制作需要专业设备、复杂后期和大量时间投入&#…...

拯救你的Flash回忆:CefFlashBrowser让经典内容重获新生

拯救你的Flash回忆&#xff1a;CefFlashBrowser让经典内容重获新生 【免费下载链接】CefFlashBrowser Flash浏览器 / Flash Browser 项目地址: https://gitcode.com/gh_mirrors/ce/CefFlashBrowser 你是否曾经因为现代浏览器不再支持Flash而无法重温那些经典的教学课件&…...

VideoAgentTrek Screen Filter 大规模部署成本分析:GPU资源优化配置指南

VideoAgentTrek Screen Filter 大规模部署成本分析&#xff1a;GPU资源优化配置指南 最近和几个做视频内容审核的朋友聊天&#xff0c;大家聊得最多的不是技术有多牛&#xff0c;而是“这玩意儿跑起来到底要花多少钱”。确实&#xff0c;像VideoAgentTrek Screen Filter这类视…...

祝贺电影《得闲谨制》荣获2026亚洲艺术电影节 六项提名

电影《得闲谨制》荣获2026亚洲艺术电影节「金海燕奖」主竞赛单元六项提名&#xff1a; 祝贺导演孔笙 提名最佳导演&#xff1b; 祝贺编剧伍千万里四十八 提名最佳编剧&#xff1b; 祝贺演员肖战 提名最佳男主角&#xff1b; 祝贺演员尹正 提名最佳男配角&#xff1b; 祝贺美术指…...

告别布局跳动!Android Dialog+EditText+软键盘的终极适配指南(含Kotlin代码)

Android Dialog软键盘适配全攻略&#xff1a;从布局跳动到完美交互 在Android开发中&#xff0c;Dialog与软键盘的交互一直是让开发者头疼的问题。当EditText获得焦点时&#xff0c;弹出的软键盘经常会遮挡输入框或导致布局跳动&#xff0c;严重影响用户体验。本文将深入探讨Di…...

s2-proGPU利用率提升方案:批处理合成与异步请求性能压测报告

s2-pro GPU利用率提升方案&#xff1a;批处理合成与异步请求性能压测报告 1. 项目背景与挑战 s2-pro作为Fish Audio开源的专业级语音合成模型镜像&#xff0c;在实际应用中面临GPU利用率不足的问题。通过初步监测发现&#xff1a; 单次请求GPU利用率峰值仅达到35-40%请求间隔…...

CHORD-X深度研究报告生成:集成MySQL进行数据存储与管理的配置指南

CHORD-X深度研究报告生成&#xff1a;集成MySQL进行数据存储与管理的配置指南 如果你正在使用CHORD-X这类强大的研究报告生成工具&#xff0c;可能会遇到一个甜蜜的烦恼&#xff1a;生成的内容越来越多&#xff0c;数据越来越杂&#xff0c;怎么才能把它们管得井井有条&#x…...

AD20 原理图与PCB的协同设计:从单向更新到双向同步的进阶指南

1. AD20协同设计的基础概念 刚接触AD20时&#xff0c;最让我头疼的就是原理图和PCB之间的同步问题。记得第一次做多板卡项目&#xff0c;光是处理不同原理图之间的元件冲突就折腾了一整天。AD20的协同设计功能远比我们想象的强大&#xff0c;但要用好它&#xff0c;得先理解几个…...

BilibiliDown:从技术视角重新定义B站视频下载体验

BilibiliDown&#xff1a;从技术视角重新定义B站视频下载体验 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader &#x1f633; 项目地址: https://gitcode.com/gh_mirrors/bi/Bi…...

【算法实战】分支限界法解电路布线:从理论到代码实现

1. 电路布线问题与分支限界法初探 电路布线问题就像是在一个布满障碍物的迷宫中寻找最短路径。想象一下&#xff0c;你手里拿着一根电线&#xff0c;需要在布满元件的电路板上找到一条最短的路径连接两个点&#xff0c;而且电线只能走直线或者直角转弯。这就是电路布线问题的现…...