【C++】模拟实现红黑树

🦄个人主页:修修修也

🎏所属专栏:实战项目集

⚙️操作环境:Visual Studio 2022


目录

一.了解项目功能

二.逐步实现项目功能模块及其逻辑详解

📌实现RBTreeNode类模板

🎏构造RBTreeNode类成员变量

🎏实现RBTreeNode类构造函数

📌实现RBTree类模板

🎏构造RBTree类成员变量

🎏实现RBTree类构造函数

🎏实现RBTree插入函数

🎏实现RBTree插入左单旋(和AVL树一样)

🎏实现RBTree插入右单旋(和AVL树一样)

🎏判断红黑树是否符合红黑树规则函数

三.项目完整代码

test.c文件

RBTree.h文件

结语


一.了解项目功能

在本次项目中我们的目标是实现一个红黑树类模板,还不了解红黑树概念的朋友可以先移步[【数据结构】什么是红黑树(Red Black Tree)?]其结构图示如下:

        红黑树结点(RBTreeNode)需要包含五个成员:键值对_kv, 左指针域_left, 右指针域_right, 父亲指针域_parent, 颜色标识_col.结点(RBTreeNode)逻辑结构图示如下:

        红黑树类模板提供的功能有:

  1. 红黑树结点类的构造函数
  2. 红黑树的构造函数
  3. 红黑树的插入函数
  4. 左单旋函数
  5. 右单旋函数
  6. 判断红黑树是否符合红黑树规则函数

二.逐步实现项目功能模块及其逻辑详解

通过第二部分对项目功能的介绍,我们已经对  的功能有了大致的了解,虽然看似需要实现的功能很多,貌似一时间不知该如何下手,但我们可以分步分模块来分析这个项目的流程,最后再将各部分进行整合,所以大家不用担心,跟着我一步一步分析吧!


!!!注意,该部分的代码只是为了详细介绍某一部分的项目实现逻辑,故可能会删减一些与该部分不相关的代码以便大家理解,需要查看或拷贝完整详细代码的朋友可以移步本文第四部分。


📌实现RBTreeNode类模板

🎏构造RBTreeNode类成员变量

          我们在一开始需求分析时就已经明确了红黑树结点(RBTreeNode)需要包含五个成员:键值对_kv, 左指针域_left, 右指针域_right, 父亲指针域_parent, 颜色标识_col.结点(RBTreeNode)逻辑结构图示如下:

        对于颜色标识符,我们可以设置一个枚举来标识红色和黑色,增加代码的可读性:

enum Colour
{RED,BLACK
};

        这里还有一个小的点需要提一下,我们在这里实现的RBTreeNode类,后续是要给RBTree类使用的,考虑到后续我们在红黑树的操作函数中会有直接操作结点成员变量的情况,如:

cur->_left = root->_right; //相当于在RBTreeNode外部直接通过类指针访问了类成员变量_left

        基于class的封装特性,class的成员变量一般都是默认为私有的,如果我们要允许其他类直接访问class的成员变量和函数,就要将其都设置为public,或者通过友元/内部类来解决成员访问问题.

        既然如此,我们不妨直接使用struct定义结点成员变量和函数,因为struct定义的类的成员变量和函数默认就是公有的,完全可以满足我们的需求.

        综上所述,该部分代码如下:

template<class K,class V>
struct RBTreeNode
{RBTreeNode<K, V>* _left;RBTreeNode<K, V>* _right;RBTreeNode<K, V>* _parent;pair<K, V> _kv;Colour _col;
};

🎏实现RBTreeNode类构造函数

        RBTreeNode的构造函数我们实现两个即可,一个是有参构造,一个是无参构造,而无参构造又可以通过给缺省值的方式和有参构造合二为一,所以我们用初始化列表来实现一下RBTreeNode的构造函数(我在红黑树的概念中已经分析过为什么新插入的结点一定是红色,这里就不多赘述了):

//缺省值的作用是在无参调用时直接去调用模板实例化的类的无参构造函数
//这里一定不能将缺省值给0/nullptr!因为你不知道模板实例化的类具体到底是内置类型还是自定义类型(如Date)
//所以要显示调用pair<K,V>类型它自己的无参构造函数RBTreeNode(const pair<K,V>& kv=pair<K,V>()):_left(nullptr),_right(nullptr),_parent(nullptr),_kv(kv),_col(RED)
{}

📌实现RBTree类模板

🎏构造RBTree类成员变量

        RBTree类成员变量比较简单,就是一个根节点的指针,为了简化模板中出现的RBTreeNode<K,V>类型的名字,我们将其简化命名为:Node

        该部分实现代码如下:

template<class K,class V>
class RBTree
{typedef RBTreeNode<K,V> Node;private:Node* _root;
};

🎏实现RBTree类构造函数

        RBTree类的构造函数非常简单,因为只有一个成员变量根节点指针_root,所以我们用初始化列表将该结点指针初始话为nullptr即可,代码如下:

RBTree():_root(nullptr)
{}

🎏实现RBTree插入函数

        RBTree类的插入函数实现思路如下:

        如果我们遇到了插入后违反红黑树规则的情况,那么红黑树的调整规则如下:

  1. 插入结点是根节点(即破坏了根节点是黑色的规则)--->解决方法,直接将该节点变黑
  2. 插入结点的父节点也是红色(即破坏了红结点的孩子必须是黑色的规则),分两种情况
  3. 插入结点的叔叔结点是红色: 将叔叔和父亲变为黑色, 爷爷结点变为红色, 然后继续向上判定爷爷结点是否违反了红黑树的规则并进行调整
  4. 插入结点的叔叔结点不存在或是黑色: 根据形态进行相应的旋转操作,旋转完成后,将旋转后的根节点变黑,将祖父结点变红即可

        综上所述,红黑树的插入函数代码实现如下:

bool Insert(const pair<K, V>& kv)
{//前期的插入逻辑就是二叉搜索树的插入逻辑if (_root == nullptr){_root = new Node(kv);_root->_col = BLACK;return true;}//找插入位置Node* cur = _root;Node* parent = nullptr;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{//插左边parent->_left = cur;}cur->_parent = parent;//控制红黑树的特性...控制颜色//插入的永远是红结点//插入的是根,把结点变红//插入时父节点是黑,就ok了//插入的父节点是红,看叔叔//	叔叔是红,把父亲叔叔都变黑,把爷爷变红(然后继续向上处理)//	叔叔是黑,旋转,转完父爷都变色while ( parent && parent->_col == RED && parent->_parent){Node* grandfather = parent->_parent;//因为我们在红黑树中不用平衡因子但是要判断是LL/RR/LR/RL型的旋转,因此需要在这里分情况讨论if (parent == grandfather->_left){Node* uncle = grandfather->_right;//叔叔存在且为红if (uncle && uncle->_col == RED){//变色parent->_col = uncle->_col = BLACK;grandfather->_col = RED;//继续向上处理cur = grandfather;parent = cur->_parent;}else//叔叔不存在或存在且为黑,就旋转{if (cur == parent->_left){RotateR(grandfather);//转完换色parent->_col = BLACK;grandfather->_col = RED;}else{RotateL(parent);RotateR(grandfather);//转完换色cur->_col = BLACK;grandfather->_col = RED;}}}else//parent == grandfather->_right{Node* uncle = grandfather->_left;if (uncle && uncle->_col == RED){//变色parent->_col = uncle->_col = BLACK;grandfather->_col = RED;//继续向上处理cur = grandfather;parent = cur->_parent;}else{if (cur == parent->_left){RotateR(parent);RotateL(grandfather);//改色cur->_col = BLACK;grandfather->_col = RED;}else{RotateL(grandfather);//祖父一定是红色,父子谁最后旋到根谁变黑//单旋父黑,双旋子黑//单旋爷变子,双旋子变父parent->_col = BLACK;grandfather->_col = RED;}}}}_root->_col = BLACK;return true;
}

🎏实现RBTree插入左单旋(和AVL树一样)

        左单旋处理应用的情况为:

  • 插入结点是父亲结点的右孩子
  • 父亲结点是爷爷结点的右孩子

        左单旋的处理操作步骤为:

  • 将父亲结点的左子树链接到爷爷结点的右孩子的位置
  • 将爷爷链接到父亲结点的左孩子位置

        综上,实现代码及详解如下:

    //左单旋void RotateL(Node* parent){Node* cur = parent->_right;Node* curleft = cur->_left;Node* ppnode = parent->_parent;//将失衡结点右孩子的左子树链接到失衡结点的右孩子parent->_right = curleft;if (curleft){curleft->_parent = parent;}//将失衡结点连接到失衡结点右孩子的左孩子位置parent->_parent = cur;cur->_left = parent;//处理父父结点的链接cur->_parent = ppnode;if (ppnode == nullptr)//为空代表parent就已经是root了{_root = cur;}else{if (ppnode->_left == parent)//失衡结点是其父节点的左孩子{ppnode->_left = cur;}else       //失衡结点是其父节点的右孩子{ppnode->_right = cur;}}}

🎏实现RBTree插入右单旋(和AVL树一样)

        右单旋处理应用的情况为:

  • 插入结点是父亲结点的左
  • 父亲结点是爷爷结点的左

        右单旋的处理操作步骤为:

  • 将父亲结点的右子树链接到爷爷结点的左孩子的位置
  • 将爷爷结点链接到父亲结点的右孩子位置

        综上,实现代码及详解如下:

    //右单旋void RotateR(Node* parent){Node* cur = parent->_left;Node* curright = cur->_right;Node* ppnode = parent->_parent;//将失衡结点左孩子的右子树连接到失衡结点的左孩子位置parent->_left = curright;if (curright){curright->_parent = parent;}//将失衡结点连接到失衡结点左孩子的右孩子位置parent->_parent = cur;cur->_right = parent;//链接父父结点cur->_parent = ppnode;if (ppnode == nullptr)//为空代表parent就已经是root了{_root = cur;}else{if (ppnode->_left == parent){ppnode->_left = cur;}else{ppnode->_right = cur;}}}

🎏判断红黑树是否符合红黑树规则函数

        判断一棵树是不是红黑树,就要从红黑树的几个规则出发,看其是否满足下面这几个规则:

  • 每个结点不是红色就是黑色
  • 根结点是黑色
  • 如果一个结点是红色的,则它的子结点一定是黑色
  • 任一结点到NULL(树尾)的任何路径上,所含的黑色结点数一定相同
  • 每个NULL(树尾)空结点都是黑色的

        综上,实现代码如下:

//检查结点是否满足没有连续的两个红结点,以及所有路径的黑节点数量都相同函数
bool CheckColour(Node* root, int blacknum, int benchmark)
{if (root == nullptr){if (benchmark != blacknum)return false;return true;}//计算路径黑节点数量if (root->_col == BLACK){++blacknum;}//如果一个结点是红色,它的父亲也是红色,那就违反了没有两个连续红结点的规则if (root->_col == RED && root->_parent && root->_parent->_col == RED){cout << root->_kv.first << "连续红结点" << endl;return false;}return CheckColour(root->_left,blacknum,benchmark)&& CheckColour(root->_right,blacknum,benchmark);
}//RBTree验证函数递归子函数
bool _IsBalance(Node* root)
{if (root == nullptr)return true;//规则:根节点是黑色if (root->_col != BLACK)return false;//求黑节点基准值(用左路的黑节点数量来计算)int benchmark = 0;Node* cur = _root;while (cur){if (cur->_col == BLACK)benchmark++;cur = cur->_left;}//规则:不能有连续的红结点,且每条路径黑节点数量相同return CheckColour(root, 0, benchmark);
}//RBTree验证函数(嵌套的目的是为了方便传参)
bool IsBalance()
{return _IsBalance(_root);
}

三.项目完整代码

我们将程序运行的代码分别在三个工程文件中编辑,完整代码如下:

test.c文件

        该文件主要包含一些对AVL树的功能测试代码,大家可以酌情参考或自己编写测试用例:

#include"RBTree.h"void test1()
{int a[] = { 16,3,7,11,9,26,18,14,15 };RBTree<int, int> t;for (auto e : a){t.Insert(make_pair(e, e));cout << "Insert:" << e << "->" << t.IsBalance() << endl;}
}void test2()
{int a[] = { 14, 9, 5, 17, 11, 12, 7, 19, 16, 27 };RBTree<int, int> t;for (auto e : a){t.Insert(make_pair(e, e));cout << "Insert:" << e << "->" << t.IsBalance() << endl;}
}void test3()
{int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };RBTree<int, int> t;for (auto e : a){t.Insert(make_pair(e, e));cout << "Insert:" << e << "->" << t.IsBalance() << endl;}
}//随机数暴力测试
void test4()
{const int N = 1000000;vector<int> v;v.reserve(N);srand(time(0));for (size_t i = 0; i < N; i++){v.push_back(rand());}cout << "数据录入完毕,开始插入" << endl;RBTree<int, int> t;for (auto e : v){t.Insert(make_pair(e, e));}cout << t.IsBalance() << endl;t.InOrder();cout << "插入结束" << endl;
}int main()
{test4();return 0;
}

RBTree.h文件

#pragma once#include<iostream>
#include<vector>
using namespace std;enum Colour
{RED,BLACK
};template<class K,class V>
struct RBTreeNode
{RBTreeNode(const pair<K,V>& kv=pair<K,V>()):_left(nullptr),_right(nullptr),_parent(nullptr),_kv(kv),_col(RED){}RBTreeNode<K, V>* _left;RBTreeNode<K, V>* _right;RBTreeNode<K, V>* _parent;pair<K, V> _kv;Colour _col;
};template<class K,class V>
class RBTree
{typedef RBTreeNode<K,V> Node;
public:RBTree():_root(nullptr){}bool Insert(const pair<K, V>& kv){if (_root == nullptr){_root = new Node(kv);_root->_col = BLACK;return true;}Node* cur = _root;Node* parent = nullptr;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{//插左边parent->_left = cur;}cur->_parent = parent;//...控制颜色//插入的永远是红结点//插入的是根,把结点变红//插入时父节点是黑,就ok了//插入的父节点是红,看叔叔//	叔叔是红,把父亲叔叔都变黑,把爷爷变红(然后继续向上处理)//	叔叔是黑,旋转,转完父爷都变色while ( parent && parent->_col == RED && parent->_parent){Node* grandfather = parent->_parent;if (parent == grandfather->_left){Node* uncle = grandfather->_right;//叔叔存在且为红if (uncle && uncle->_col == RED){//变色parent->_col = uncle->_col = BLACK;grandfather->_col = RED;//继续向上处理cur = grandfather;parent = cur->_parent;}else//叔叔不存在或存在且为黑,就旋转{if (cur == parent->_left){RotateR(grandfather);//转完换色parent->_col = BLACK;grandfather->_col = RED;}else{RotateL(parent);RotateR(grandfather);//转完换色cur->_col = BLACK;grandfather->_col = RED;}}}else//parent == grandfather->_right{Node* uncle = grandfather->_left;if (uncle && uncle->_col == RED){//变色parent->_col = uncle->_col = BLACK;grandfather->_col = RED;//继续向上处理cur = grandfather;parent = cur->_parent;}else{if (cur == parent->_left){RotateR(parent);RotateL(grandfather);//改色cur->_col = BLACK;grandfather->_col = RED;}else{RotateL(grandfather);//祖父一定是红色,父子谁最后旋到根谁变黑//单旋父黑,双旋子黑//单旋爷变子,双旋子变父parent->_col = BLACK;grandfather->_col = RED;}}}}_root->_col = BLACK;return true;}//左单旋void RotateL(Node* parent){Node* cur = parent->_right;Node* curleft = cur->_left;Node* ppnode = parent->_parent;//将失衡结点右孩子的左子树链接到失衡结点的右孩子parent->_right = curleft;if (curleft){curleft->_parent = parent;}//将失衡结点连接到失衡结点右孩子的左孩子位置parent->_parent = cur;cur->_left = parent;//处理父父结点的链接cur->_parent = ppnode;if (ppnode == nullptr)//为空代表parent就已经是root了{_root = cur;}else{if (ppnode->_left == parent)//失衡结点是其父节点的左孩子{ppnode->_left = cur;}else       //失衡结点是其父节点的右孩子{ppnode->_right = cur;}}}//右单旋void RotateR(Node* parent){Node* cur = parent->_left;Node* curright = cur->_right;Node* ppnode = parent->_parent;//将失衡结点左孩子的右子树连接到失衡结点的左孩子位置parent->_left = curright;if (curright){curright->_parent = parent;}//将失衡结点连接到失衡结点左孩子的右孩子位置parent->_parent = cur;cur->_right = parent;//链接父父结点cur->_parent = ppnode;if (ppnode == nullptr)//为空代表parent就已经是root了{_root = cur;}else{if (ppnode->_left == parent){ppnode->_left = cur;}else{ppnode->_right = cur;}}}//中序遍历函数void InOrder(){_InOrder(_root);  //代替成员函数完成递归cout << endl;       //方便后续观察测试用例}//中序遍历子递归函数void _InOrder(Node* root){if (root == nullptr){return;}_InOrder(root->_left);       //递归访问左子树cout << root->_kv.first << " ";   //访问根节点_InOrder(root->_right);      //递归访问右子树}//验证双红结点和路径黑结点数是否相同函数bool CheckColour(Node* root, int blacknum, int benchmark){if (root == nullptr){if (benchmark != blacknum)return false;return true;}if (root->_col == BLACK){++blacknum;}if (root->_col == RED && root->_parent && root->_parent->_col == RED){cout << root->_kv.first << "连续红结点" << endl;return false;}return CheckColour(root->_left,blacknum,benchmark)&& CheckColour(root->_right,blacknum,benchmark);}bool IsBalance(){return _IsBalance(_root);}//RBTree验证函数bool _IsBalance(Node* root){if (root == nullptr)return true;//规则:根节点是黑色if (root->_col != BLACK)return false;//求黑节点基准值int benchmark = 0;Node* cur = _root;while (cur){if (cur->_col == BLACK)benchmark++;cur = cur->_left;}//规则:不能有连续的红结点,且每条路径黑节点数量相同return CheckColour(root, 0, benchmark);}private:Node* _root;
};

结语

希望这篇红黑树的实现详解能对大家有所帮助,欢迎大佬们留言或私信与我交流.

学海漫浩浩,我亦苦作舟!关注我,大家一起学习,一起进步!

 相关文章推荐

【C++】模拟实现AVL树

【数据结构】什么是平衡二叉搜索树(AVL Tree)?

【C++】STL标准模板库容器map

【C++】STL标准模板库容器set

【C++】模拟实现二叉搜索(排序)树

【数据结构】C语言实现链式二叉树(附完整运行代码)

【数据结构】什么是二叉搜索(排序)树?

【C++】模拟实现priority_queue(优先级队列)

【C++】模拟实现queue

【C++】模拟实现stack

【C++】模拟实现list

【C++】模拟实现vector

【C++】标准库类型vector

【C++】模拟实现string类

【C++】标准库类型string

【C++】构建第一个C++类:Date类

【C++】类的六大默认成员函数及其特性(万字详解)

【C++】什么是类与对象?


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

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

相关文章

异常场景分析

优质博文&#xff1a;IT-BLOG-CN 为了防止黑客从前台异常信息&#xff0c;对系统进行攻击。同时&#xff0c;为了提高用户体验&#xff0c;我们都会都抛出的异常进行拦截处理。 一、异常处理类 Java把异常当做是破坏正常流程的一个事件&#xff0c;当事件发生后&#xff0c;…

Spring Boot新闻推荐:实时数据处理

4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式&#xff0c;是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示&#xff1a; 图4-1系统工作原理…

JSR303微服务校验

一.创建idea 二.向pom.xml添加依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.7.RELEASE</version></parent><properties><java.vers…

职业技术学校开设无人机培训技术详解

职业技术学校开设无人机培训技术&#xff0c;是一个涉及多个方面的综合性教学过程。以下是对该培训技术的详细解析&#xff1a; 一、培训目标 无人机培训技术的目标在于培养学员掌握无人机的基本原理、组装调试、飞行操作、安全规范及维修保养等技能&#xff0c;使其成为具备…

基于SSM的定制衣服系统的设计与实现(定制衣服管理平台的设计与开发、智慧服装定制系统的设计与实现、定制衣服管理系统的设计与实现(源码+定制+参考文档)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

机器人的性能指标

1. 负荷能力 负荷能力负荷能力是指机器人在满足其他性能要求的情况下,能够承载的负荷重量。例如,一台机器人的最大负荷能力可能远大于它的额定负荷能力,但是达到最大负荷时,机器人的工作精度可能会降低,可能无法准确地沿着预定的轨迹运动,或者产生额外的偏差。机器人的负荷量与…

【redis-05】redis保证和mysql数据一致性

redis系列整体栏目 内容链接地址【一】redis基本数据类型和使用场景https://zhenghuisheng.blog.csdn.net/article/details/142406325【二】redis的持久化机制和原理https://zhenghuisheng.blog.csdn.net/article/details/142441756【三】redis缓存穿透、缓存击穿、缓存雪崩htt…

不只是前端,后端、产品和测试也需要了解的浏览器知识(一)

目录标题 一、我们为什么要了解浏览器&#xff1f;1. 对于前端开发者2. 对于后端开发者 二、浏览器发展概述1. 宏观发展2. 微观发展 三、浏览器核心部件1. 浏览器界面介绍2. 目前浏览器的使用的渲染引擎和解释器总结3. 浏览器的解释器 四、各家浏览器目前的市场占比五、整体总结…

索尼MDR-M1:超宽频的音频盛宴,打造沉浸式音乐体验

在音乐的世界里&#xff0c;每一次技术的突破都意味着全新的听觉体验。 索尼&#xff0c;作为音频技术的先锋&#xff0c;再次以其最新力作——MDR-M1封闭式监听耳机&#xff0c;引领了音乐界的新潮流。 这款耳机以其超宽频播放和卓越的隔音性能&#xff0c;为音乐爱好者和专…

tornado

Tornado通过使用非阻塞网络I/O&#xff0c;可以扩展到数以万计的开放链接&#xff0c;非常适合 长时间轮询&#xff0c;WebSockets和其他需要与每个用户建立长期连接的应用程序。 特点 注重性能优越&#xff0c;速度快解决高并发异步非阻塞websockets 长连接内嵌了HTTP服务器…

04 B-树

目录 常见的搜索结构B-树概念B-树的插入分析B-树的插入实现B树和B*树B-树的应用 1. 常见的搜索结构 种类数据格式时间复杂度顺序查找无要求O(N)二分查找有序O( l o g 2 N log_2N log2​N)二分搜索树无要求O(N)二叉平衡树无要求O( l o g 2 N log_2N log2​N)哈希无要求O(1) 以…

IO模型介绍

一、理解IO 网络通信的本质就是进程间通信&#xff0c;进程间通信本质就是IO TCP中的IO接口&#xff1a;read / write / send / recv&#xff0c;本质都是&#xff1a;等 拷贝 所以IO的本质就是&#xff1a;等 拷贝 那么如何高效的IO&#xff1f; 减少“等”在单位时间的…

CORDIC算法笔记整理

CORDIC算法有两种模式&#xff0c;分别为旋转模式和向量模式。而在数字硬件实现混频处理时&#xff0c;CORDIC算法是比较好的方法&#xff0c;使用的是CORDIC的旋转模式&#xff0c;只需通过移位操作和加法就可以实现频谱搬移的乘法操作。 1 CORDIC算法理解 1.1 单次旋转 对…

SpringCloud学习记录|day1

学习材料 2024最新SpringCloud微服务开发与实战&#xff0c;java黑马商城项目微服务实战开发&#xff08;涵盖MybatisPlus、Docker、MQ、ES、Redis高级等&#xff09; 学redis讲到微服务就停了&#xff0c;nginx也是。 所以嘛&#xff0c;我终于来到微服务了。 复习MyBatisP…

CMU 10423 Generative AI:lec14(Vision Language Model:CLIP、VQ-VAE)

文章目录 1 概述2 CLIP (Used in GPT-V)3 VQ-VAE (Used in Gemini)**VQ-VAE 详细笔记****VQ-VAE 的模块组成与数据流** **1. 输入数据****2. 编码器&#xff08;Encoder&#xff09;****2.1 编码器的作用****2.2 数据流与维度变化****2.3 编码器输出** **3. 量化器&#xff08;…

IP 数据包分包组包

为什么要分包 由于数据链路层MTU的限制,对于较⼤的IP数据包要进⾏分包. 什么是MTU MTU相当于发快递时对包裹尺⼨的限制.这个限制是不同的数据链路对应的物理层,产⽣的限制. • 以太⽹帧中的数据⻓度规定最⼩46字节,最⼤1500字节,ARP数据包的⻓度不够46字节,要在后⾯补填 充…

云栖实录 | 开源大数据全面升级:Native 核心引擎、Serverless 化、湖仓架构引领云上大数据发展

本文根据2024云栖大会实录整理而成&#xff0c;演讲信息如下&#xff1a; 演讲人&#xff1a; 王 峰 | 阿里云智能集团研究员、开源大数据平台负责人 李 钰&#xff5c;阿里云智能集团资深技术专家 范 振&#xff5c;阿里云智能集团高级技术专家 李劲松&#xff5c;阿里云…

MongoDB聚合操作及索引底层原理

目录 链接:https://note.youdao.com/ynoteshare/index.html?id=50fdb657a9b06950fa255a82555b44a6&type=note&_time=1727951783296 本节课的内容: 聚合操作: 聚合管道操作: ​编辑 $match 进行文档筛选 ​编辑 将筛选和投影结合使用: ​编辑 多条件匹配: …

【AI】AIOT简介

随着技术的快速发展&#xff0c;人工智能AI和物联网IoT已经成为当今最热门的技术领域。AIOT是人工智能和物联网的结合&#xff0c;使物联网设备更加智能化&#xff0c;能够进行自主决策和学习的技术。 通过物联网产生、收集来自不同维度的、海量的数据存储于云端、边缘端&#…

数据治理006-数据标准的管理

元数据的分类和标准有哪些&#xff1f; 一、元数据的分类 元数据可以根据其描述的对象和属性不同&#xff0c;被分为不同的类型。以下是几种常见的元数据分类方法&#xff1a; 基于数据的类型&#xff1a;根据数据的类型&#xff0c;元数据可以被分为结构化元数据、非结构化元…