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

C++进阶——AVL树的实现

1、AVL的概念

1.1 AVL 树的发明

AVL 树由 G.M. Adelson-Velsky 和 E.M. Landis 在 1962 年的论文《An algorithm for the organization of information》中提出。他们的设计目标是解决二叉搜索树在动态操作(插入、删除)中可能退化为链表的问题。

1.2 AVL 树的定义

AVL 树是一种自平衡二叉搜索树,满足以下性质:

  • 它是一棵空树者:

    • 它的左右子树是 AVL 树

    • 左右子树的高度差(平衡因子)的绝对值 <= 1

1.3 平衡因子

平衡因子(Balance Factor)是 AVL 树的核心概念:

  • 定义:某个节点平衡因子 = 右子树的高度 - 左子树的高度

  • 平衡因子取值范围-101

  • 如果某个节点的平衡因子的绝对值超过 1,则该节点不平衡,需要通过旋转操作进行调整。

1.4 为什么高度差 <= 1 ?

高度差为 0 表示左右子树高度相等,这种理想状态在某些情况下无法实现的。

  • 例如:

    • 当树的节点数为 2 时,高度差只能为 1。

    • 当树的节点数为 4 时,高度差也只能为 1。

  • 如果强制要求高度差为 0,会导致树的结构过于严格,难以在动态操作中保持平衡。

1. 5 AVL 树的性能

AVL 树的性能优势主要体现在其高度平衡性:

  • 高度控制AVL 树高度 始终保持 O(log⁡N)

  • 操作效率插入删除查找等操作的时间复杂度均为 O(log⁡N)

2、AVL树的实现

2.1 AVL树的结构

	template<class K,class V>struct AVLTreeNode{pair<K, V> _kv;AVLTreeNode<K, V>* _left;AVLTreeNode<K, V>* _right;AVLTreeNode<K, V>* _parent;int _bf; // balance factorAVLTreeNode(const pair<K,V>& kv):_kv(kv),_left(nullptr),_right(nullptr),_parent(nullptr),_bf(0){ }};template<class K,class V>class AVLTree{typedef AVLTreeNode<K, V> Node;public:// ……private:Node* _root = nullptr;}

2.2 AVL树的插入

2.2.1 AVL树插入一个值的大概过程

1. 按二叉搜索树规则进行插入一个值

2. 新增结点只会影响祖先(或部分祖先)结点的高度,也就是会影响祖先(或部分祖先)结点的平衡因子,所以更新 从新增结点->根结点路径上的平衡因子。实际中最坏情况下要更新到根,有些情况更新到中间就可以结束了。

3. 更新平衡因子过程中出现不平衡(平衡因子的绝对值超过 1),对不平衡子树 旋转,旋转后本质调平衡的同时,降低了子树的高度,不会再影响上一层,所以插入结束。

2.2.2 平衡因子的更新
更新原则:

1. 平衡因子的定义

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

2. 影响平衡因子的条件

只有子树高度变化 才会影响当前节点的平衡因子

3. 插入节点对平衡因子的影响

  • 如果新增节点parent右子树parent的平衡因子++

  • 如果新增节点parent左子树parent的平衡因子--

更新情况:

1. 更新后parent的平衡因子 等于 0

因为插入前,就是平衡搜索树,平衡因子只能是-1,0,1,所以一定是从-1或1变成0,子树整体的

高度不变结束更新

2. 更新后parent的平衡因子 等于 1-1

一定是从0变成-1或1,子树整体的高度变化继续更新

3. 更新后parent的平衡因子等于 2 -2

一定是从-1变成-2或1变成2,parent高的子树更高了,不平衡了。

通过旋转平衡(即降低树的高度),并使子树的根平衡因子为0

-1->-2(旋转)->0,或1->2(旋转)->0,相当于子树的高度没变结束更新

4. 更新到根节点

如果更新到根节点,且根节点的平衡因子为 1 -1结束更新。因为根的parent为nullptr,不用更

新了。

2.2.3 插入的代码实现
		bool Insert(const pair<K, V>& kv){if (_root == nullptr){_root = new Node(kv);return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (kv.first > cur->_kv.first){parent = cur;cur = cur->_right;}else if (kv.first < cur->_kv.first){parent = cur;cur = cur->_left;}else{return false;}}cur = new Node(kv);if (kv.first > parent->_kv.first){parent->_right = cur;}else{parent->_left = cur;}cur->_parent = parent;// 更新平衡因子while (parent) // parent = nullptr,为根节点的父亲,结束更新{if (cur == parent->_left)--parent->_bf;else++parent->_bf;if (parent->_bf == 0){break;}else if (parent->_bf == -1 || parent->_bf == 1){cur = parent;parent = cur->_parent;}else if (parent->_bf == -2 || parent->_bf == 2){// 旋转break;}else{assert(false);}}return true;}

2.3 旋转

2.3.1 旋转的原则

1. 保持搜索树的规则

2. 让旋转的树从不平衡变平衡,其次降低旋转树的高度

旋转总共分为四种,左单旋/右单旋/左右双旋/右左双旋。

2.3.2 右单旋

即左侧高,右侧的parent旋下来。平衡因子同号。

a,b,c子树为抽象表示,实际上有非常多种情况。

a子树自己不旋转,高度+1subLRparent的左,再将parentsubL的右

注意:

h = 0时,subLRnullptr

parent如果是局部子树的根,就改变连接关系,如果是,就改变根

2.3.3 右单旋的代码实现
		void RotateR(Node* parent){Node* pParent = parent->_parent;Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;if (subLR)subLR->_parent = parent;subL->_right = parent;parent->_parent = subL;subL->_parent = pParent;if (pParent == nullptr) // 当pParent == nullptr时,_root == parent{_root = subL;}else{if (pParent->_left == parent)pParent->_left = subL;elsepParent->_right = subL;}subL->_bf = 0;parent->_bf = 0;}
2.3.4 左单旋

即右侧高,左侧的parent旋下来。平衡因子同号。

a子树自己不旋转,高度+1subRLparent的右,再将parentsubR的左

注意:

h = 0时,subRLnullptr

parent如果是局部子树的根,就改变连接关系,如果是,就改变根

2.3.5 左单旋的代码实现
		void RotateL(Node* parent){Node* pParent = parent->_parent;Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;if (subRL)subRL->_parent = parent;subR->_left = parent;parent->_parent = subR;subR->_parent = pParent;if (pParent == nullptr)_root = subR;else{if (pParent->_left == parent)pParent->_left = subR;elsepParent->_right = subR;}subR->_bf = 0;parent->_bf = 0;}
2.3.6 左右双旋

即中间高,右侧的parent旋下来。平衡因子异号。

从过程上,是对subL进行左旋parent进行右旋

从结果上,subLRsubLsubLRparentsubLR自己做

subLRsubLparent

平衡后分三种情况,即有三种情况的平衡因子

2.3.7 左右双旋的代码实现
		void RotateLR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;int _bf = subLR->_bf;RotateL(subL);RotateR(parent);if (_bf == 0){parent->_bf = 0;subL->_bf = 0;subLR->_bf = 0;}else if (_bf == 1){parent->_bf = 0;subL->_bf = -1;subLR->_bf = 0;}else if (_bf == -1){parent->_bf = 1;subL->_bf = 0;subLR->_bf = 0;}else{assert(false);}}
2.3.8 右左双旋

即中间高,左侧的parent旋下来。平衡因子异号。

从过程上,是对subR进行右旋parent进行左旋

从结果上,subRLparentsubRLsubRsubRL自己做

subRLparentsubR

平衡后分三种情况,即有三种情况的平衡因子

2.3.9 右左双旋的代码实现
		void RotateRL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;int _bf = subRL->_bf;RotateR(subR);RotateL(parent);if (_bf == 0){parent->_bf = 0;subR->_bf = 0;subRL->_bf = 0;}else if (_bf == 1){parent->_bf = -1;subR->_bf = 0;subRL->_bf = 0;}else if (_bf == -1){parent->_bf = 0;subR->_bf = 1;subRL->_bf = 0;}else{assert(false);}}

2.4 AVL树的查找

		Node* Find(const K& key){Node* cur = _root;while (cur){if (key > cur->_kv.first)cur = cur->_right;else if (key < cur->_kv.first)cur = cur->_left;elsereturn cur;}return nullptr;}

2.5 AVL树的平衡检测

		bool _IsBalanceTree(Node* root, int& height) { // 后序// 空树是 AVL 树if (nullptr == root) {height = 0;return true;}// 递归检查左子树int leftHeight = 0;bool isLeftBalanced = _IsBalanceTree(root->_left, leftHeight);// 递归检查右子树int rightHeight = 0;bool isRightBalanced = _IsBalanceTree(root->_right, rightHeight);// 当前节点的高度height = max(leftHeight, rightHeight) + 1;// 计算平衡因子int diff = rightHeight - leftHeight;// 检查平衡因子是否异常if (abs(diff) >= 2) {cout << root->_kv.first << " 高度差异常" << endl;return false;}// 检查当前节点的平衡因子是否正确if (root->_bf != diff) {cout << root->_kv.first << " 平衡因子异常" << endl;return false;}// 如果左右子树都是 AVL 树,且当前节点也平衡,则整棵树是 AVL 树return isLeftBalanced && isRightBalanced;}

2.6 AVL树的删除

2.7 AVL的代码实现

2.7.1 AVLTree.h
#pragma once#include <iostream>
#include <assert.h>using namespace std;namespace Lzc
{template<class K,class V>struct AVLTreeNode{pair<K, V> _kv;AVLTreeNode<K, V>* _left;AVLTreeNode<K, V>* _right;AVLTreeNode<K, V>* _parent;int _bf; // balance factorAVLTreeNode(const pair<K,V>& kv):_kv(kv),_left(nullptr),_right(nullptr),_parent(nullptr),_bf(0){ }};template<class K,class V>class AVLTree{typedef AVLTreeNode<K, V> Node;public:bool Insert(const pair<K, V>& kv){if (_root == nullptr){_root = new Node(kv);return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (kv.first > cur->_kv.first){parent = cur;cur = cur->_right;}else if (kv.first < cur->_kv.first){parent = cur;cur = cur->_left;}else{return false;}}cur = new Node(kv);if (kv.first > parent->_kv.first){parent->_right = cur;}else{parent->_left = cur;}cur->_parent = parent;// 更新平衡因子while (parent){if (cur == parent->_left)--parent->_bf;else++parent->_bf;if (parent->_bf == 0){break;}else if (parent->_bf == -1 || parent->_bf == 1){cur = parent;parent = cur->_parent;}else if (parent->_bf == -2 || parent->_bf == 2){if (parent->_bf == -2 && cur->_bf == -1)RotateR(parent);else if (parent->_bf == 2 && cur->_bf == 1)RotateL(parent);else if (parent->_bf == -2 && cur->_bf == 1)RotateLR(parent);else if (parent->_bf == 2 && cur->_bf == -1)RotateRL(parent);elseassert(false);break;}else{assert(false);}}return true;}void RotateR(Node* parent){Node* pParent = parent->_parent;Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;if (subLR)subLR->_parent = parent;subL->_right = parent;parent->_parent = subL;subL->_parent = pParent;if (pParent == nullptr) // 当pParent == nullptr时,_root == parent{_root = subL;}else{if (pParent->_left == parent)pParent->_left = subL;elsepParent->_right = subL;}subL->_bf = 0;parent->_bf = 0;}void RotateL(Node* parent){Node* pParent = parent->_parent;Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;if (subRL)subRL->_parent = parent;subR->_left = parent;parent->_parent = subR;subR->_parent = pParent;if (pParent == nullptr)_root = subR;else{if (pParent->_left == parent)pParent->_left = subR;elsepParent->_right = subR;}subR->_bf = 0;parent->_bf = 0;}void RotateLR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;int _bf = subLR->_bf;RotateL(subL);RotateR(parent);if (_bf == 0){parent->_bf = 0;subL->_bf = 0;subLR->_bf = 0;}else if (_bf == 1){parent->_bf = 0;subL->_bf = -1;subLR->_bf = 0;}else if (_bf == -1){parent->_bf = 1;subL->_bf = 0;subLR->_bf = 0;}else{assert(false);}}void RotateRL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;int _bf = subRL->_bf;RotateR(subR);RotateL(parent);if (_bf == 0){parent->_bf = 0;subR->_bf = 0;subRL->_bf = 0;}else if (_bf == 1){parent->_bf = -1;subR->_bf = 0;subRL->_bf = 0;}else if (_bf == -1){parent->_bf = 0;subR->_bf = 1;subRL->_bf = 0;}else{assert(false);}}void InOrder(){_InOrder(_root);}int Height(){return _Height(_root);}int Size(){return _Size(_root);}bool IsBalanceTree(){int height = 0;return _IsBalanceTree(_root, height);}Node* Find(const K& key){Node* cur = _root;while (cur){if (key > cur->_kv.first)cur = cur->_right;else if (key < cur->_kv.first)cur = cur->_left;elsereturn cur;}return nullptr;}private: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;}bool _IsBalanceTree(Node* root, int& height) { // 后序// 空树是 AVL 树if (nullptr == root) {height = 0;return true;}// 递归检查左子树int leftHeight = 0;bool isLeftBalanced = _IsBalanceTree(root->_left, leftHeight);// 递归检查右子树int rightHeight = 0;bool isRightBalanced = _IsBalanceTree(root->_right, rightHeight);// 当前节点的高度height = max(leftHeight, rightHeight) + 1;// 计算平衡因子int diff = rightHeight - leftHeight;// 检查平衡因子是否异常if (abs(diff) >= 2) {cout << root->_kv.first << " 高度差异常" << endl;return false;}// 检查当前节点的平衡因子是否正确if (root->_bf != diff) {cout << root->_kv.first << " 平衡因子异常" << endl;return false;}// 如果左右子树都是 AVL 树,且当前节点也平衡,则整棵树是 AVL 树return isLeftBalanced && isRightBalanced;}Node* _root = nullptr;};
}
2.7.2 Test.cpp
#include "AVLTree.h"
#include <vector    >namespace Lzc
{void TestAVLTree1() {AVLTree<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.IsBalanceTree() << endl;}// 插入一堆随机值,测试平衡,顺便测试一下高度和性能等void TestAVLTree2() {const int N = 100000;vector<int> v;v.reserve(N);srand(time(0));for (size_t i = 0; i < N; i++) {v.push_back(rand() + i);}// 测试插入性能size_t begin2 = clock();AVLTree<int, int> t;for (auto e : v) {t.Insert(make_pair(e, e));}size_t end2 = clock();cout << "Insert:" << end2 - begin2 << endl;// 测试平衡性、高度和大小cout << "IsBalanceTree:" << t.IsBalanceTree() << endl;cout << "Height:" << t.Height() << endl;cout << "Size:" << t.Size() << endl;// 测试查找性能size_t begin1 = clock();// 查找已存在的值/*for (auto e : v) {t.Find(e);}*/// 查找随机值for (size_t i = 0; i < N; i++) {t.Find((rand() + i));}size_t end1 = clock();cout << "Find:" << end1 - begin1 << endl;}
}int main()
{Lzc::TestAVLTree1();// Lzc::TestAVLTree2();return 0;
}

相关文章:

C++进阶——AVL树的实现

1、AVL的概念 1.1 AVL 树的发明 AVL 树由 G.M. Adelson-Velsky 和 E.M. Landis 在 1962 年的论文《An algorithm for the organization of information》中提出。他们的设计目标是解决二叉搜索树在动态操作&#xff08;插入、删除&#xff09;中可能退化为链表的问题。 1.2 …...

S32K144入门笔记(十三):LPIT的API函数解读

目录 1. SDK中的函数 2. API函数的释义 2.1 获取默认参数 2.2 初始化 2.3 启动与停止 2.4 计数值的设置于读取 2.5 中断API 1. SDK中的函数 在使用SDK的非抽象驱动函数时&#xff0c;函数的定义与声明在文件lpit_driver.c和lpit_driver.h中&#xff0c;一共有19个函数&a…...

打包当前Ubuntu镜像 制作Ubuntu togo系统

我的系统的基本情况说明&#xff1a; 我原来的系统的具体型号如下&#xff1a; uname -rLinux Engine 5.15.0-134-generic #145~20.04.1-Ubuntu SMP Mon Feb 17 13:27:16 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux我原来的硬盘以及分区策略如下&#xff1a; 可以看到我的分区…...

系统架构设计师—案例分析—架构设计

文章目录 经典架构风格对比面向对象架构风格/显示调用风格优点缺点举例 事件驱动的系统/隐式调用风格优点缺点举例 基于规则的系统架构风格优点缺点举例 管道过滤器风格优点缺点举例 仓库风格优点缺点举例 解释器风格优点缺点举例 分层架构风格优点缺点举例 经典架构风格对比 …...

基于javaweb的SpringBoot智能相册管理系统图片相册系统设计与实现(源码+文档+部署讲解)

技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论…...

Android 14 Telephony 网络选择功能介绍

一、总体介绍 (一)功能 手动搜网的流程:用户通过UI触发,调用TelephonyManager的API,比如startNetworkScan,然后这个请求会传递到RIL层,通过AT命令与基带通信,进行网络扫描。结果返回后,经过TelephonyRegistry通知应用层。中间可能涉及IPC,比如Binder通信,因为应用和…...

Leetcode 刷题笔记1 单调栈part01

leetcode 739 每日温度 对于单调栈问题&#xff0c;我觉得是在循环外部增加一些辅助项减少时间复杂度&#xff0c;但增加内存空间的利用 class Solution:def dailyTemperatures(self, temperatures: List[int]) -> List[int]:ans [0] * len(temperatures)stack []for i …...

深入解析音频编解码器(Audio CODEC):硬件、接口与驱动开发

音频编解码器&#xff08;Audio CODEC&#xff09;是音频处理系统中的核心组件&#xff0c;负责 模拟信号与数字信号的相互转换&#xff0c;广泛应用于 智能音箱、嵌入式系统、消费电子产品 等设备。本篇文章将从 硬件结构、接口解析、驱动开发 和 软件配置 等方面&#xff0c;…...

深度学习【迭代梯度下降法求解线性回归】

梯度下降法 梯度下降法是一种常用迭代方法&#xff0c;其目的是让输入向量找到一个合适的迭代方向&#xff0c;使得输出值能达到局部最小值。在拟合线性回归方程时&#xff0c;我们把损失函数视为以参数向量为输入的函数&#xff0c;找到其梯度下降的方向并进行迭代&#xff0…...

[Lc14_priority_queue] 最后一块石头重量 | 数据流中的第 K 大元素 | 前K个高频单词 | 数据流的中位数

目录 1.最后一块石头的重量 题解 2.数据流中的第 K 大元素 题解 3.前K个高频单词 题解 代码 ⭕4.数据流的中位数 题解 在C中&#xff0c;使用标准库中的priority_queue&#xff0c;默认情况下它是一个最大堆&#xff08;即大堆排序&#xff09;&#xff0c;这意味着最…...

熔断和降级的区别,具体使用场景有哪些?

熔断与降级的核心区别在于触发条件和应用目标&#xff0c;具体差异及使用场景如下&#xff1a; 一、核心区别 对比维度熔断降级触发原因下游依赖服务故障&#xff08;如超时、异常率过高&#xff09;触发系统整体负载过高或流量洪峰管理目标层级框架级保护&#xff08;无业务优…...

利用hexo+github部署属于自己的个人博客网站(2025年3月所写)

利用hexogithub部署属于自己的个人博客网站 前情提要&#xff1a;如果你出现了莫名其妙的报错&#xff0c;可能与权限有关&#xff0c;可以以管理员的身份运行git bash或者cmd 本篇博客仅限于利用hexo搭建博客&#xff0c;并且部署到github上面&#xff0c;让自己可以有一个访…...

首页性能优化

首页性能提升是前端优化中的核心任务之一&#xff0c;因为首页是用户访问的第一入口&#xff0c;其加载速度和交互体验直接影响用户的留存率和转化率。 1. 性能瓶颈分析 在优化之前&#xff0c;首先需要通过工具分析首页的性能瓶颈。常用的工具包括&#xff1a; Chrome DevTo…...

使用usb-cam包时填充摄像头参数话题

问题描述&#xff1a; 在启动usb摄像头之后&#xff0c;像apriltag_ros等包需要读取摄像头的内参信息&#xff0c;但是usb-cam默认是没有内参信息发布的&#xff0c;需要自己填写或标定。 解决方案&#xff1a; 如果你有内参数据或者急于验证后续代码的逻辑正确性&#xff0c…...

pandas学习笔记(一)——基础知识和应用案例

pandas学习笔记 基础语法参考菜鸟教程&#xff1a;https://www.runoob.com/pandas/pandas-tutorial.html # jupyter import pandas as pd import matplotlib from matplotlib import pyplot as plt import numpy as npmatplotlib.use(TkAgg)data {timestamp: [1, 2, 3, 4, 5…...

SpringBoot + Mybatis Plus 整合 Redis

Redis 在用户管理系统中的典型应用场景 结合你的用户增删改查接口&#xff0c;以下是 Redis 的实用场景和具体实现方案&#xff1a; 场景作用实现方案用户信息缓存减少数据库压力&#xff0c;加速查询响应使用 Spring Cache Redis 注解缓存登录 Token 存储分布式 Session 或…...

【AI 大模型】RAG 检索增强生成 ⑤ ( 向量数据库 | 向量数据库 索引结构和搜索算法 | 常见 向量数据库 对比 | 安装并使用 向量数据库 chromadb 案例 )

文章目录 一、向量数据库1、向量数据库引入2、向量数据库简介3、向量数据库 索引结构和搜索算法4、向量数据库 应用场景5、传统数据库 与 向量数据库 对比 二、常见 向量数据库 对比三、向量数据库 案例1、安装 向量数据库 chromadb2、核心要点 解析① 创建数据库实例② 创建数…...

解决single cell portal点击下载但跳转的是网页

Single cell RNA-seq of Tmem100-lineage cells in a mouse model of osseointegration - Single Cell Portal 想下载个小鼠数据集&#xff1a; 点击下载跳转为网页&#xff1a; 复制bulk download给的链接无法下载 bulk download给的原链接&#xff1a; curl.exe "http…...

基于 Prometheus + Grafana 监控微服务和数据库

以下是基于 Prometheus Grafana 监控微服务和数据库的详细指南&#xff0c;包含架构设计、安装配置及验证步骤&#xff1a; 一、整体架构设计 二、监控微服务 1. 微服务指标暴露 Spring Boot 应用&#xff1a; xml <!-- 添加 Micrometer 依赖 --> <dependency>…...

GitHub Copilot 在 VS Code 上的终极中文指南:从安装到高阶玩法

GitHub Copilot 在 VS Code 上的终极中文指南&#xff1a;从安装到高阶玩法 前言 GitHub Copilot 作为 AI 编程助手&#xff0c;正在彻底改变开发者的编码体验。本文将针对中文开发者&#xff0c;深度解析如何在 VS Code 中高效使用 Copilot&#xff0c;涵盖基础设置、中文优化…...

为什么选择 Rust 和 WebAssembly?

一、低级控制与高级体验 在 Web 应用开发中&#xff0c;JavaScript 虽然灵活&#xff0c;但往往难以保证稳定的性能。其动态类型系统和垃圾回收&#xff08;GC&#xff09;机制会导致性能波动&#xff0c;甚至在不经意间因偏离 JIT&#xff08;即时编译器&#xff09;的最佳路…...

Vala语言基础知识-源文件和编译

源文件和编译 Vala代码‌以.vala为扩展名。与Java等语言不同&#xff0c;Vala‌不强制要求严格的文件结构‌——它没有类似Java的"包"&#xff08;package&#xff09;或"类文件"&#xff08;class file&#xff09;的概念&#xff0c;而是通过文件内的文本…...

CAN总线的CC帧和FD帧之间如何仲裁

为满足CAN总线日益提高的带宽需求&#xff0c;博世公司于2012年推出CAN FD&#xff08;具有灵活数据速率的CAN&#xff09;标准&#xff0c;国际标准化组织&#xff08;ISO&#xff09;2015年通过ISO 11898-1:2015标准&#xff0c;正式将CAN FD纳入国际标准&#xff0c;以示区别…...

SpringBoot 第一课(Ⅲ) 配置类注解

目录 一、PropertySource 二、ImportResource ①SpringConfig &#xff08;Spring框架全注解&#xff09; ②ImportResource注解实现 三、Bean 四、多配置文件 多Profile文件的使用 文件命名约定&#xff1a; 激活Profile&#xff1a; YAML文件支持多文档块&#xff…...

Python的类和对象(4)

1、反射 动态的给类和对象添加属性&#xff0c;获取属性&#xff0c;删除属性&#xff0c;修改属性【反射】。 --4个内置函数 1&#xff09;设置属性&#xff1a;setattr( 对象/类&#xff0c;属性名&#xff0c;属性值) 2&#xff09;获取属性&#xff1a;getattr(对象/类&am…...

使用EasyExcel进行简单的导入、导出

准备 在pom.xml添加依赖 <!-- EasyExcel --><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.1.1</version></dependency>导入 controller // 用户导入Operation(summary…...

Excel(函数篇):COUNTIF与CONUTIFS函数、SUMIF与SUMIFS函数、ROUND函数、MATCH与INDEX函数、混合引用与条件格式

目录 COUNTIF和COUNTIFS函数COUNTIF函数COUNTIFS函数SUMIF和SUMIFS函数SUMIF函数SUMIFS函数SUMIFS函数与控件实现动态年月汇总ROUND、ROUNDUP、ROUNDDOWN函数单元格混合引用条件格式与公式,标记整行数据MATCH和INDEX函数COUNTIF和COUNTIFS函数 COUNTIF函数 统计下“苏州”出现…...

虚拟定位 1.2.0.2 | 虚拟定位,上班打卡,校园跑步模拟

Fake Location是一款运行于安卓平台上的功能强大、简单实用的虚拟定位软件。它能够帮助用户自定义位置到地图上的任意地方&#xff0c;以ROOT环境运行不易被检测&#xff0c;同时也支持免ROOT运行。提供路线模拟、步频模拟、WIFI模拟等方式&#xff0c;支持反检测。 大小&…...

【最大异或和——可持久化Trie】

题目 代码 #include <bits/stdc.h> using namespace std;const int N 6e510; //注意这里起始有3e5&#xff0c;又可能插入3e5 const int M N * 25;int rt[N], tr[M][2]; //根&#xff0c;trie int idx, cnt, br[M]; //根分配器&#xff0c;点分配器&#xff0c;点的相…...

C# WPF编程-启动新窗口

C# WPF编程-启动新窗口 新建窗口&#xff1a; 工程》添加》窗口 命名并添加新的窗口 这里窗口名称为Window1.xaml 启动新窗口 Window1 win1 new Window1(); win1.Show(); // 非模态启动窗口win1.ShowDialog(); // 模态启动窗口 模态窗口&#xff1a;当一个模态窗口被打开时&a…...