C++红黑树详解
文章目录
- 红黑树
- 概念
- 规则
- 为什么最长路径不超过最短路径的二倍?
- 红黑树的时间复杂度
- 红黑树的结构
- 插入
- 叔叔节点情况的讨论
- 只变色(叔叔存在且为红)
- 抽象的情况
- 变色+单旋(叔叔不存在或叔叔存在且为黑)
- 变色+双旋(叔叔不存在或叔叔存在且为黑)
- 判断是不是红黑树
- 代码
红黑树
概念
红黑树保证了最长的路径不超过最短路径的二倍
规则
- 根节点是黑色的
- 每个节点不是红色就是黑色
- 如果有一个节点是红的,那么它的两个孩子都是黑的,就是说一条路径不会有两个连续的红色节点(不会出现红红,其他情况可以出现红黑,黑黑,黑红)
- 对于每个节点到其空节点上的简单路径,每一条路径上都有相同数量的黑色节点
为什么最长路径不超过最短路径的二倍?
- 最短路径就是全黑
- 最长路径就是一黑一红的组合
- 假设每条路径有x个黑色的节点
最短:x
最长:2*x
这是最极端的场景 - 其它的场景都在最短和最长之间
比如下面这幅图:
最短:3
最长:4
最长路径不超过最短路径的2倍
路径的条数(要算到走到空的场景):9条路径
其它书里可能出现下面的图:
这样是为了计算路径的条数更加方便,防止算错
加了这样的空节点也不违反规则
红黑树的时间复杂度
假设节点个数为N
用极端的场景来算
红黑树最短路径的高度为:2^h-1 = N, h = log(N+1)
最长路径的高度为:2^2h-1 = N,h = (log(N+1))/2
其实最快可以近似为logN,最慢可以近似为2*logN,
整体上时间复杂度还是logN,只是没有AVL树那么接近logN
红黑树的结构
// 枚举红黑树的颜色
enum Colour
{RED,BLACK
};// 按Key/Value的模式实现
template<class K,class V>
class RBTreeNode
{pair<K, V> _kv;RBTreeNode<K, V>* _left;RBTreeNode<K, V>* _right;RBTreeNode<K, V>* _parent;Colour _col;RBTreeNode(const pair<K,V>& kv):_kv(kv),_left(nullptr),_right(nullptr),_parent(nullptr){}
};template<class K,class V>
class RBTree
{typedef RBTreeNode<K, V> Node;
public:private:Node* _root = nullptr;
};
插入
插入红色节点还是黑色节点呢?
- 插入红色节点可能违反规则3,红色节点的父亲可能是红色节点,父亲是黑色节点就不用管
- 插入时黑色节点必然会违反规则4,每条路径上都要有相同数量的黑色节点
- 按二叉搜索树的规则插入,不违反上面的4条规则
- 如果是空树插入,则插入黑色节点。如果是非空树插入,必然插入红色,因为黑色违反规则4
- 插入红色节点,如果父亲是黑色节点,不违反规则,插入结束
- 插入红色节点,如果父亲是红色节点,违反规则3。
插入节点c必然是红色,父亲节点p也是红色,因为之前也要遵循红黑树的规则,所以爷爷节点g也要是黑色,是红色之前就违反规则了。所以c,p,g三个节点的颜色是固定的。
先在关键看叔叔节点u了,u可以是红色,也可以是黑色,所以要分情况讨论叔叔节点的颜色。
叔叔节点情况的讨论
只变色(叔叔存在且为红)
- c为红,p为红,g为黑,u存在且为红。将p变黑,因为红红违反了规则3,p必须变红。u也变黑,g变红。
- 把g当做c继续向上更新,需要继续向上更新是因为如果g的父亲还是红色,就需要继续向上处理;如果g的父亲是黑色,就处理结束;如果g就是整棵树的根,再把g变为黑色。
抽象的情况
- 叔叔存在且为红,(a和b是抽象出来的子树)a和b要满足下面的模版,爷爷的两个孩子都是红色,才满足只变色
- 抽象的情况:
- bh(black height),bh == 0
- bh == 1
- bh == 2
变色+单旋(叔叔不存在或叔叔存在且为黑)
p,c是红,g是黑,u不存在或者u存在且为黑
- u不存在,c只能是新增节点(如果c不是新增节点的话,它只能是之前变色变过来的,那它之前就是黑色,黑色节点的数量就不对)。右旋,把父亲节点变黑,g变红
- u存在且为黑,c一定不是新增(如果c是新增,那么新增前,黑色的数量不对),c之前就是黑色的,现在变成了红色,因为进行了变色。右旋,父亲变为黑色,爷爷变为红色
- 不用继续往上更新,因为黑黑可以,红黑也可以,就不用管了。
变色+双旋(叔叔不存在或叔叔存在且为黑)
p,c是红,g是黑,u不存在或者u存在且为黑
- u不存在,c只能是新增节点(如果c不是新增节点的话,它只能是之前变色变过来的,那它之前就是黑色,黑色节点的数量就不对)。
- u存在且为黑,c一定不是新增(如果c是新增,那么新增前,黑色的数量不对),c之前就是黑色的,现在变成了红色,因为进行了变色。
- 左单旋,然后右单旋,父亲节点不变色,cur节点由红色变成黑色,grandfather节点由黑色变成红色。不用继续往上更新,因为黑黑可以,红黑也可以,就不用管了。
关键看叔叔
判断是不是红黑树
用4个规则进行判断,满足这四个规则就满足最长路径不超过最短路径的两倍。
- 规则1枚举了颜色就实现了节点不是黑色就是红色
- 规则2直接检查根的颜色是不是黑色就可以了
- 规则3不能是连续的红色节点,遇到红色节点就检查孩子不太方便,如果孩子不存在就更不方便了,并且孩子可能有两个。但是检查父亲节点的颜色就方便多了,遇到红色节点就检查父亲节点的颜色。
- 规则4是每条路径的黑色节点的数量必须相同。用前序遍历检查,用形参blacknum记录到当前节点的黑色节点的数量,遇到黑色节点就++,走到空就计算完一条路径的黑色节点的数量。用任意一条的黑色节点的数量作为参考值,依次比较。
// 判断红黑树是否平衡
bool IsBalance()
{// 根节点是空if (_root == nullptr)return true;// 根节点非空且是红色if (_root->_col == RED)return false;// 算出一条路径上黑色节点的个数作为参考值Node* cur = _root;// 参考值int blacknum = 0;while (cur){if (cur->_col == BLACK){++blacknum;}// 就走最左边的一条路径cur = cur->_left;}return Check(_root,0,blacknum);
}private:
bool Check(Node* root, int blacknum, const int refnum)
{// refnum参考值if (root == nullptr){// 当前路径走完了if (blacknum != refnum){cout << "存在黑色节点的数量不相等的路径" << endl;return false;}return true;}// 规则3if (root->_col == RED && root->_parent->_col == RED){cout << "存在连续两个红节点" << endl;return false;}if (root->_col == BLACK){++blacknum;}return Check(root->_left, blacknum, refnum) &&Check(root->_right, blacknum, refnum);
}
代码
#pragma once
#include<iostream>
using namespace std;// 枚举红黑树的颜色
enum Colour
{RED,BLACK
};// 按Key/Value的模式实现
template<class K,class V>
struct RBTreeNode
{pair<K, V> _kv;RBTreeNode<K, V>* _left;RBTreeNode<K, V>* _right;RBTreeNode<K, V>* _parent;Colour _col;RBTreeNode(const pair<K,V>& kv):_kv(kv),_left(nullptr),_right(nullptr),_parent(nullptr){}
};template<class K,class V>
class RBTree
{typedef RBTreeNode<K, V> Node;
public:bool Insert(const pair<K, V>& kv){if (_root == nullptr){_root = new Node(kv);_root->_col = BLACK;return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_kv.first < kv.first){parent = cur;cur = cur->_right;}else if (cur->_kv.first > kv.first){parent = cur;cur = cur->_left;}else{// 不冗余,插入失败return false;}}cur = new Node(kv);// 如果是非空树,插入红色节点cur->_col = RED;if (parent->_kv.first < kv.first){parent->_right = cur;}else if (parent->_kv.first > kv.first){parent->_left = cur;}// 链接父亲节点cur->_parent = parent;// parent是红色,出现了连续的红色节点,需要向上调整// 调整之后cur是根,cur的parent是nullptrwhile (parent&&parent->_col == RED){Node* grandfather = parent->_parent;if (grandfather->_left == parent){// g// p uNode* uncle = grandfather->_right;if (uncle && uncle->_col == RED){// 变色是为了处理连续的红节点,保证黑节点的数量不变,// 向上继续调整是因为grandfather的节点可能是黑节点就结束,// 可能是红节点就继续向上处理parent->_col = uncle->_col = BLACK;grandfather->_col = RED;// 继续向上处理cur = grandfather;parent = cur->_parent;}else{// uncle不存在或uncle存在且为黑// g// p u// c// 右单旋if (cur == parent->_left){RotateR(grandfather);parent->_col = BLACK;grandfather->_col = RED;}else{// 双旋// g// p u// cRotateL(parent);RotateR(grandfather);cur->_col = BLACK;grandfather->_col = RED;}break;}}else{// g// u pNode* uncle = grandfather->_left;if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLACK;grandfather->_col = RED;// 继续向上更新cur = grandfather;parent = cur->_parent;}else{// uncle不存在或者存在且是黑// g// u p// c// 左单旋if (parent->_right == cur){RotateL(grandfather);parent->_col = BLACK;grandfather->_col = RED;}else{// g// u p// c// 双旋RotateR(parent);RotateL(grandfather);cur->_col = BLACK;grandfather->_col = RED;}break;}}}// 无论如何结束之后根都是黑色的_root->_col = BLACK;return true;}// 右单旋,旋转点是parentvoid RotateR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;// b可能为空树if (subLR != nullptr)subLR->_parent = parent;// 记录parent的parentNode* pParent = parent->_parent;subL->_right = parent;parent->_parent = subL;// 1. 10是这棵树的总根if (parent == _root){_root = subL;subL->_parent = nullptr;}else{// 2. 10是这棵树的局部根// pParent左可能是parent,右也可能是parentif (pParent->_left == parent){pParent->_left = subL;}else{pParent->_right = subL;}subL->_parent = pParent;}}// 左单旋,旋转点是parentvoid RotateL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;// b不是空树if (subRL)subRL->_parent = parent;// 记录父亲节点的父亲节点Node* pParent = parent->_parent;subR->_left = parent;parent->_parent = subR;// 1. 10是这棵树的总根if (_root == parent){_root = subR;subR->_parent = nullptr;}else{// 2. 10是这棵树的局部根if (pParent->_left == parent){pParent->_left = subR;}else{pParent->_right = subR;}subR->_parent = pParent;}}void InOrder(){_InOrder(_root);cout << endl;}int Height(){return _Height(_root);}int Size(){return _Size(_root);}Node* Find(const K& key){Node* cur = _root;while (cur){if (cur->_kv.first < key){cur = cur->_right;}else if (cur->_kv.first > key){cur = cur->_left;}else{return cur;}}return nullptr;}bool IsBalance(){// 根节点是空if (_root == nullptr)return true;// 根节点非空且是红色if (_root->_col == RED)return false;// 算出一条路径上黑色节点的个数作为参考值Node* cur = _root;// 参考值int blacknum = 0;while (cur){if (cur->_col == BLACK){++blacknum;}// 就走最左边的一条路径cur = cur->_left;}return Check(_root,0,blacknum);}private:bool Check(Node* root, int blacknum, const int refnum){// refnum参考值if (root == nullptr){// 当前路径走完了if (blacknum != refnum){cout << "存在黑色节点的数量不相等的路径" << endl;return false;}return true;}// 规则3if (root->_col == RED && root->_parent->_col == RED){cout << "存在连续两个红节点" << endl;return false;}if (root->_col == BLACK){++blacknum;}return Check(root->_left, blacknum, refnum) &&Check(root->_right, blacknum, refnum);}void _InOrder(Node* root){if (root == nullptr){return;}_InOrder(root->_left);cout << root->_kv.first << ":" << root->_kv.second << endl;_InOrder(root->_right);}int _Height(Node* root){if (root == nullptr)return 0;int leftHeight = _Height(root->_left);int rightHeight = _Height(root->_right);return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;}int _Size(Node* root){if (root == nullptr)return 0;return _Size(root->_left) + _Size(root->_right) + 1;}private:Node* _root = nullptr;
};#define _CRT_SECURE_NO_WARNINGS#include"RBTree.h"void TestRBTree1()
{RBTree<int, int> t;// 常规的测试用例//int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };// 特殊的带有双旋场景的测试用例int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };for (auto e : a){t.Insert({ e,e });}t.InOrder();cout << t.IsBalance() << endl;
}int main()
{TestRBTree1();return 0;
}
相关文章:
C++红黑树详解
文章目录 红黑树概念规则为什么最长路径不超过最短路径的二倍?红黑树的时间复杂度红黑树的结构插入叔叔节点情况的讨论只变色(叔叔存在且为红)抽象的情况变色单旋(叔叔不存在或叔叔存在且为黑)变色双旋(叔叔不存在或叔叔存在且为黑…...
【经验分享】ARM Linux-RT内核实时系统性能评估工具
【经验分享】ARM Linux-RT内核实时系统性能评估工具 前言下载和编译方法常用工具介绍总结 前言 最近在研究Linux-RT实时系统,介绍下常用的实时系统的性能评估工具。 下载和编译方法 用git下载 git clone git://git.kernel.org/pub/scm/utils/rt-tests/rt-tests.…...
【kong gateway】5分钟快速上手kong gateway
kong gateway的请求响应示意图 安装 下载对应的docker 镜像 可以直接使用docker pull命令拉取,也可以从以下地址下载:kong gateway 3.9.0.0 docker 镜像 https://download.csdn.net/download/zhangshenglu1/90307400, postgres-13.tar http…...
Vue入门(Vue基本语法、axios、组件、事件分发)
Vue入门 Vue概述 Vue (读音/vju/,类似于view)是一套用于构建用户界面的渐进式框架,发布于2014年2月。与其它大型框架不同的是,Vue被设计为可以自底向上逐层应用。Vue的核心库只关注视图层,不仅易于上手,还便于与第三…...
【可实战】Linux 系统扫盲、 Shell扫盲(如何写一个简单的shell脚本)
一、Linux系统扫盲 1.Linux 能运行主要的 UNIX 工具软件、应用程序和网络协议 2.Linux 的发行版说简单点就是将 Linux 内核与应用软件做一个打包。 目前市面上较知名的发行版有:Ubuntu、RedHat、CentOS、Debian、Fedora、SuSE、OpenSUSE、Arch Linux、SolusOS 等…...
【深入理解SpringCloud微服务】Sentinel源码解析——DegradeSlot熔断规则
Sentinel源码解析——DegradeSlot熔断规则 断路器原理复习DegradeSlot熔断规则原理源码解析DegradeSlot#entry()DegradeSlot#exit(Context, ...)ResponseTimeCircuitBreakerExceptionCircuitBreaker 断路器原理复习 断路器一般有三个状态:关闭、打开、半开…...
电脑系统bcd文件损坏修复方法:小白也会的修复方法
电脑系统bcd文件损坏怎么办?当电脑开机时出现bcd文件损坏,一般情况是由于电脑系统的引导坏了,需要进行修复。现在越来越多的小伙伴遇到电脑引导丢失或者安装后无法正常引导的问题,我们现在一般是pe下进行修复引导,那么电脑系统bc…...
链式存储结构
不强制要求数据在内存中集中存储,各个元素可以分散存储在内存中。 结点 结点由数据域、指针域组成。 头结点、头指针和首元结点 头指针:一个和结点类型相同的指针,它的特点是:永远指向链表中的第一个结点。上文提到过…...
Oracle 创建用户和表空间
Oracle 创建用户和表空间 使用sys 账户登录 建立临时表空间 --建立临时表空间 CREATE TEMPORARY TABLESPACE TEMP_POS --创建名为TEMP_POS的临时表空间 TEMPFILE /oracle/oradata/POS/TEMP_POS.DBF -- 临时文件 SIZE 50M -- 其初始大小为50M AUTOEXTEND ON -- 支持…...
媒体新闻发稿要求有哪些?什么类型的稿件更好通过?
为了保证推送信息的内容质量,大型新闻媒体的审稿要求一向较为严格。尤其在商业推广的过程中,不少企业的宣传稿很难发布在这些大型新闻媒体平台上。 媒体新闻发稿要求有哪些?就让我们来了解下哪几类稿件更容易过审。 一、媒体新闻发稿要求有哪…...
Qt中QVariant的使用
1.使用QVariant实现不同类型数据的相加 方法:通过type函数返回数值的类型,然后通过setValue来构造一个QVariant类型的返回值。 函数: QVariant mainPage::dataPlus(QVariant a, QVariant b) {QVariant ret;if ((a.type() QVariant::Int) &a…...
3.4 Go函数作用域(标识符)
作用域标识符 简单来说,作用域指的是标识符可以起作用的范围,即其可见范围。将标识符的可见性限制在一定范围内,这个范围就是作用域。 把标识符约束在一定的可见范围内,这个范围就是作用域。 1. 宇宙块 特点:预定义…...
搭建Spring Boot开发环境
JDK(1.8及以上版本) Apache Maven 3.6.0 修改settings.xml 设置本地仓库位置 <localRepository>D:/repository</localRepository> 设置远程仓库镜像 <mirror><id>alimaven</id><name>aliyun maven</name&…...
洛谷 P5709:Apples Prologue / 苹果和虫子
【题目来源】 https://www.luogu.com.cn/problem/P5709 【题目描述】 小 B 喜欢吃苹果。她现在有 m(1≤m≤100)个苹果,吃完一个苹果需要花费 t(0≤t≤100)分钟,吃完一个后立刻开始吃下一个。现在时间过去了…...
PyTorch张量操作reshape view permute transpose
1. reshape() 和 view() view和reshape都用于改变张量的shape view是reshape的一个特例,view要求张量在内存中是连续的,否则会抛出错误,view只能用于contiguous的张量 reshape会自动处理contiguous的情况,如果张量是contiguous…...
JAVAweb学习日记(八) 请数据库模型MySQL
一、MySQL数据模型 二、SQL语言 三、DDL 详细见SQL学习日记内容 四、DQL-条件查询 五、DQL-分组查询 聚合函数: 分组查询: 六、DQL-分组查询 七、分页查询 八、多表设计-一对多&一对一&多对多 一对多-外键: 一对一: 多…...
【ElasticSearch】 Java API Client 7.17文档
本文章内容根据 Elastic Search Java API Client 7.17 版本官方文档 内容翻译而来,用于方便后续学习翻阅 序言 这是适用于 Elasticsearch 的官方 Java API Client 文档。该客户端针对所有 Elasticsearch API 提供强类型的请求和响应。 功能 所有 Elasticsearc…...
Python “字典” 实战案例:5个项目开发实例
Python “字典” 实战案例:5个项目开发实例 内容摘要 本文包括 5 个使用 Python 字典的综合应用实例。具体是: 电影推荐系统配置文件解析器选票统计与排序电话黄页管理系统缓存系统(LRU 缓存) 以上每一个实例均有完整的程序代…...
Qt中Widget及其子类的相对位置移动
Qt中Widget及其子类的相对位置移动 最后更新日期:2025.01.25 下面让我们开始今天的主题… 一、开启篇 提出问题:请看上图,我们想要实现的效果是控件黄色的Widge(m_infobarWidget)t随着可视化窗口(m_glWidge…...
4.flask-SQLAlchemy,表Model定义、增删查改操作
介绍 SQLAlchemy是对数据库的一个抽象 开发者不用直接与SQL语句打交道 Python对象来操作数据库 SQLAlchemy是一个关系型数据库 安装 flask中SQLAlchemy的配置 from flask import Flask from demo.user_oper import userdef create_app():app Flask(__name__)# 使用sessi…...
字节跳动自研HTTP开源框架Hertz简介附使用示例
字节跳动自研 HTTP 框架 Hertz Hertz 是字节跳动自研的高性能 HTTP 框架,专为高并发、低延迟的场景设计。它基于 Go 语言开发,结合了字节跳动在微服务架构中的实践经验,旨在提供更高效的 HTTP 服务开发体验。 1. 背景介绍 随着字节跳动业务…...
Effective C++ 规则51:编写 new 和 delete 时需固守常规
1、背景 在 C 中,如果你需要为类自定义 new 和 delete,必须遵循一些约定和规则,以确保内存管理的一致性、可维护性和安全性。当我们使用 new 和 delete 操作时,C 编译器会: 调用全局或类特定的 operator new 来分配内…...
[RoarCTF 2019]Easy Calc1
题目 查看页面源代码 <script>$(#calc).submit(function(){$.ajax({url:"calc.php?num"encodeURIComponent($("#content").val()),type:GET,success:function(data){$("#result").html(<div class"alert alert-success">…...
【Bug 记录】el-sub-menu 第一次进入默认不高亮
项目场景: 项目场景:el-sub-menu 第一次进入默认不高亮 问题描述 例如:sub-menu 的 index 后端默认传过来是 number,我们需要手动转为 string,否则会有警告,而且第一次进入 sub-menu 默认不高亮。 解决方…...
自然语言处理——从原理、经典模型到应用
1. 概述 自然语言处理(Natural Language Processing,NLP)是一门借助计算机技术研究人类语言的科学,是人工智能领域的一个分支,旨在让计算机理解、生成和处理人类语言。其核心任务是将非结构化的自然语言转换为机器可以…...
Linux——冯 • 诺依曼体系结构
目录 一、冯•诺依曼体系结构原理二、内存提高冯•诺依曼体系结构效率的方法三、当用QQ和朋友聊天时数据的流动过程四、关于冯诺依曼五、总结 我们常见的计算机,如笔记本。我们不常见的计算机,如服务器,大部分都遵守冯诺依曼体系 流程&#…...
【FISCO BCOS】二十四、通过Java SDK对FISCO BCOS进行压力测试
Java SDK Demo是基于Java SDK的基准测试集合,能够对FISCO BCOS节点进行压力测试。Java SDK Demo提供有合约编译功能,能够将Solidity合约文件转换成Java合约文件,此外还提供了针对转账合约、CRUD合约以及AMOP功能的压力测试示例程序。本篇我们来讲讲使用java SDK压力测试的操…...
Gurobi基础语法之字典
Python中的字典:dict 我们先来介绍一下Python语法中的 dict 类型, 字典中可以通过任意键值来对数据进行映射,任何无法修改的python对象都可以当作键值来使用,这些无法修改的Python对象包括:整数(比如:1),浮…...
汽车OEMs一般出于什么目的来自定义Autosar CP一些内容
汽车OEMs在使用AUTOSAR CP(Classic Platform)协议时,可能会根据自身的特定需求对标准协议进行修改,形成自己的企业标准(企标)。这种修改通常是为了满足特定的硬件平台、功能需求、安全要求或优化性能。以下是一些常见的修改场景和例子: 1. 硬件平台适配 企业可能会根据…...
设计模式的艺术-享元模式
结构性模式的名称、定义、学习难度和使用频率如下表所示: 1.如何理解享元模式 当一个软件系统在运行时产生的对象数量太多,将导致运行代价过高,带来系统性能下降等问题。 在享元模式中,存储这些共享实例对象的地方称为享元池&…...
Java使用FFM API调用SDL
首发于Enaium的个人博客 首先我们需要创建一个Gradle项目,之后设置项目的JDK版本,设置为22及以上版本。 plugins {kotlin("jvm") version "2.1.0" }group "cn.enaium" version "1.0-SNAPSHOT"repositories {…...
bash: ./xxx: No such file or directory
问题现象 在使用开源或他人可执行文件的时候,可能会遇到 bash: ./squashfs2sparse: No such file or directory 的报错;实际测试发现该文件存在,并且有可执行权限; 问题分析 通过对报错文件的分析 1:文件具有可执行…...
Linux(Centos 7.6)命令详解:wc
1.命令作用 打印文件的行数、单词数、字节数,如果指定了多个文件,还会打印以上三种数据的总和(Print newline, word, and byte counts for each FILE, and a total line if more than one FILE is specified) 2.命令语法 Usage: wc [OPTION]... [FIL…...
PHP EOF (Heredoc) 详解
PHP EOF (Heredoc) 详解 PHP 中的 EOF(End Of File)是一种非常有用的语法特性,允许开发者创建多行字符串。它特别适合于创建格式化文本,如配置文件、HTML 模板等。本文将详细讲解 PHP EOF 的用法、优势以及注意事项。 什么是 EOF? EOF 是一种特殊的字符串定义方式,它允…...
面向长文本的多模型协作摘要架构:多LLM文本摘要方法
多LLM摘要框架在每轮对话中包含两个基本步骤:生成和评估。这些步骤在多LLM分散式摘要和集中式摘要中有所不同。在两种策略中,k个不同的LLM都会生成多样化的文本摘要。然而在评估阶段,多LLM集中式摘要方法使用单个LLM来评估摘要并选择最佳摘要,而分散式多LLM摘要则使用k个LLM进行…...
第27章 测试驱动开发模式:深入测试技术
写在前面 这本书是我们老板推荐过的,我在《价值心法》的推荐书单里也看到了它。用了一段时间 Cursor 软件后,我突然思考,对于测试开发工程师来说,什么才更有价值呢?如何让 AI 工具更好地辅助自己写代码,或许…...
C语言教程——文件处理(2)
目录 前言 一、顺序读写函数(续) 1.1fprintf 1.2fscanf 1.3fwrite 1.4fread 二、流和标准流 2.1流 2.2标准流 2.3示例 三、sscanf和sprintf 3.1sprintf 3.2sscanf 四、文件的随机读写 4.1fseek 4.2ftell 4.3rewind 五、文件读取结束的…...
QT TLS initialization failed
qt使用QNetworkAccessManager下载文件(给出的链接可以在浏览器里面下载文件),下载失败, 提示“TLS initialization failed”通常是由于Qt在使用HTTPS进行文件下载时,未能正确初始化TLS(安全传输层协议&…...
金融级分布式数据库如何优化?PawSQL发布OceanBase专项调优指南
前言 OceanBase数据库作为国产自主可控的分布式数据库,在金融、电商、政务等领域得到广泛应用,优化OceanBase数据库的查询性能变得愈发重要。PawSQL为OceanBase数据库提供了全方位的SQL性能优化支持,助力用户充分发挥OceanBase数据库的性能潜…...
在Kubernets Cluster中部署LVM类型的StorageClass - 上
适用场景 看到B站技术部门的文章,是关于如何在k8s集群部署Elastic Search和Click House等IO密集型数据库应用的。 因为要充分利用NvME SSD盘的IOPS,所有数据库应用都直接调用本地SSD盘做为stateful application的 Persistent Volumes。为了可用动态的分…...
mysql 学习6 DML语句,对数据库中的表进行 增 删 改 操作
添加数据 我们对 testdatabase 数据中 的 qqemp 这张表进行 增加数据,在这张表 下 打开 命令行 query console 在 软件中就是打开命令行的意思 可以先执行 desc qqemp; 查看一下当前表的结构。 插入一条数据 到qqemp 表,插入时要每个字段都有值 insert…...
【全栈】SprintBoot+vue3迷你商城(10)
【全栈】SprintBootvue3迷你商城(10) 往期的文章都在这里啦,大家有兴趣可以看一下 后端部分: 【全栈】SprintBootvue3迷你商城(1) 【全栈】SprintBootvue3迷你商城(2) 【全栈】Sp…...
2025年01月25日Github流行趋势
项目名称:it-tools 项目地址url:https://github.com/CorentinTh/it-tools项目语言:Vue历史star数:25298今日star数:212项目维护者:CorentinTh, apps/renovate, cgoIT, sharevb, marvin-j97项目简介…...
java后端之登录认证
基础登录功能:根据提供的用户名和密码判断是否存在于数据库 LoginController.java RestController Slf4j public class LoginController {Autowiredprivate UserService userService;PostMapping("/login")public Result login(RequestBody User user) {…...
2024年AI多极竞争:技术创新与商业突破
标题:2024年AI多极竞争:技术创新与商业突破 文章信息摘要: 2024年初,人工智能领域呈现多极竞争格局。OpenAI、Google和Mistral等公司在视频生成、大语言模型架构和模型能力方面实现突破性创新。这些进展体现了AI技术在多模态能力…...
25.1.25Java复习|数组
一、数组复习: import java.util.Scanner; import java.*; public class Example1 {public static void main(String[] args){Scanner scnew Scanner(System.in);String[] namesnew String[5];//创建了一个可以容纳5个字符串的数组for(int i0;i<5;i){System.ou…...
总结8..
#include <stdio.h> // 定义结构体表示二叉树节点,包含左右子节点编号 struct node { int l; int r; } tree[100000]; // 全局变量记录二叉树最大深度,初始为0 int ans 0; // 深度优先搜索函数 // pos: 当前节点在数组中的位置,…...
谈谈对JavaScript 中的事件冒泡(Event Bubbling)和事件捕获(Event Capturing)的理解
JavaScript 中的事件冒泡(Event Bubbling)和事件捕获(Event Capturing),是浏览器在处理事件时采用的两种机制,它们在事件的传播顺序上有显著区别。这两种机制帮助开发者在事件触发时,能够以不同…...
tcp/ip协议和ip协议,tcp/ip协议 ip协议
TCP/IP协议和IP协议在网络通信中扮演着重要的角色,它们之间既有联系又有区别。以下是对两者的详细解释: TCP/IP协议 定义: TCP/IP协议(Transmission Control Protocol/Internet Protocol)是网络通信协议的一种&…...
【JavaEE进阶】Spring留言板实现
目录 🎍预期结果 🍀前端代码 🎄约定前后端交互接口 🚩需求分析 🚩接口定义 🌳实现服务器端代码 🚩lombok介绍 🚩代码实现 🌴运行测试 🎄前端代码实…...