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

使用红黑树模拟实现map和set

在STL的源代码中,map和set的底层原理都是红黑树。但这颗红黑树跟我们单独写的红黑树不一样,它需要改造一下:

改造红黑树

节点的定义

因为map和set的底层都是红黑树。而且map是拥有键值对pair<K,V>的,而set是没有键值对,只有一个K。因此,为了应对这两种不同的情况,就使用模板参数T。

当map使用这棵红黑树的时候,T就会变成pair<K,V>。当set使用时,T就会变成K。

//使用枚举
enum Colour
{RED,BLACK,
};// 如果是map,则为pair<K, V>; 如果是set,则为k
//因此,对于节点来说,需要再套一层模板,来应付两种不同的情况
template<class T>
struct RBTreeNode
{T _data;RBTreeNode<T>* _left;RBTreeNode<T>* _right;RBTreeNode<T>* _parent;Colour _col;RBTreeNode(const T& data):_data(data), _left(nullptr), _right(nullptr), _parent(nullptr), _col(RED)  //默认是红色{}
};

改版的红黑树的插入操作

红黑树的模板参数有三个:K、valueType和仿函数KeyOfValue。

K是key的类型,ValueTyp要么是set的K,要么是map的pair<const K,V>。

而仿函数是为了比较节点的值的大小的,因为官方库中键值对pair<K,V>比较大小的方法是比较first和second。但是红黑树中,新增节点是通过比较first,因此我们需要自己写一个仿函数用于单独比较first。

//跟节点的定义一样
//因为关联式容器中存储的是<key, value>的键值对,因此
// k为key的类型,
// ValueType: 如果是map,则为pair<K, V>; 如果是set,则为k。如下:
// map->RBTree<K,pair<const K,V>,MapKeyOfT> _t;
// set->RBTree<K,K,SetKeyOfT> _t
// 
// KeyOfValue: 通过value来获取key的一个仿函数类。其作用就是用于比较。
template<class K,class ValueType,class KeyOfValue>
class RBTree
{typedef RBTreeNode<ValueType> Node;
public: //迭代器typedef __RBTreeIterator<ValueType> iterator;//......
private:Node* _root = nullptr;
};

迭代器

红黑树的迭代器不能使用原生指针,因为它是一棵树,节点地址不连续,因此需要封装起来。

//set的K,map的pair<K,V>
template<class ValueType>
struct __RBTreeIterator
{typedef RBTreeNode<ValueType> Node;typedef __RBTreeIterator<ValueType> Self;Node* _node;__RBTreeIterator(Node* node):_node(node){}
};

1.operator++()

红黑树是二叉搜索树,采用的是中序遍历的方法。因此,迭代器每次向前走,是按照中序遍历的顺序走的。

因此,对于往前++,有两种情况:第一种情况是当前节点的右孩子不为空,那么按照中序遍历的顺序,下一个节点便是右子树的最小值。第二种情况是当前节点的右孩子为空:这种情况下,又分两种情况:①当前节点是父节点的左孩子,那么下一个节点肯定是当前节点的父节点。②当前节点是父节点的右孩子,这意味着当前节点的父节点也被遍历了,又没有右孩子节点,只能往上找了,找的节点是祖先节点,而这个祖先节点是特征是:孩子节点是它的左节点。

 

	//左 根  右Self& operator++(){//当当前节点的右子树不为空,根据中序遍历的顺序,那就找右子树最小值if (_node->_right){Node* minValue = _node->_right;while (minValue->_left){minValue = minValue->_left;}//找到最小值的节点后,更新节点_node = minValue;}else  //当当前节的的右子树为空,说明它是叶子节点。此时需要判断情况{//判断当前节点是父亲节点的左孩子还是右孩子//第一种情况:如果是cur==parent->_right,即当前节点是父节点的右孩子的话,就//去找祖先节点(这个祖先节点的特征:孩子节点是它的左节点)//第二种情况:当前节点是父亲节点的左孩子,那么下一个节点就是父亲节点了Node* cur = _node;//定义父亲节点。Node* parent = cur->_parent;//如果当前节点不是父亲的右孩子,并且父亲是不存在,那么就是根节点或者是左孩子节点了//那就不进入循环。while (parent && cur == parent->_right){//如果是,那就往上找到下一个节点。cur = cur->_parent;parent = parent->_parent;}//更新节点_node = parent;}return *this;}

2.begin()和end();

迭代器的begin和end,是左闭右开的区间。那么begin就是最左的节点,end则是最右节点的下一个节点。这里不使用哨兵来作为end节点。

对于begin,就找到最左的节点就好啦!

iterator begin(){Node* left = _root;while (left && left->_left){left = left->_left;}return iterator(left);}

对于end,这里选择直接置为空,传入匿名对象。这样子做的话,当遍历到最后一个节点后,它会往回遍历,一直到了根节点的上面一个节点,也就是空。此时就会结束循环。

	iterator end(){return iterator(nullptr);}

迭代器整体代码:

template<class ValueType>
struct __RBTreeIterator
{typedef RBTreeNode<ValueType> Node;typedef __RBTreeIterator<ValueType> Self;Node* _node;__RBTreeIterator(Node* node):_node(node){}ValueType& operator*(){return _node->_data;}ValueType* operator->(){return &_node->_data;}Self& operator++(){if (_node->_right){Node* minValue = _node->_right;while (minValue->_left){minValue = minValue->_left;}_node = minValue;}else {Node* cur = _node;Node* parent = cur->_parent;while (parent && cur == parent->_right){cur = cur->_parent;parent = parent->_parent;}_node = parent;}return *this;}bool operator!=(const Self& s){return _node != s._node;}
};

set的模拟实现

仿函数

由于set只有Key,因此就让仿函数直接返回Key值就可以了。

template<class K>class set{//set的仿函数,返回set的K值struct SetKeyOfValue{const K& operator()(const K& key){return key;}};

整体都是复用了红黑树的接口,并没有什么技术含量,问题都在红黑树中解决了。

namespace my_set
{template<class K>class set{//set的仿函数,返回set的K值struct SetKeyOfValue{const K& operator()(const K& key){return key;}};public:typedef typename RBTree<K, K, SetKeyOfValue>::iterator iterator;iterator begin(){return _t.begin();}iterator end(){return _t.end();}bool insert(const K& key){return _t.Insert(key);}private:RBTree<K, K, SetKeyOfValue> _t;};

map的模拟实现:

仿函数

由于比较的是first,因此我们返回键值对中的first即可。

template<class K, class V>class map{struct MapKeyOfValue{const K& operator()(const pair<const K, V>& kv){return kv.first;}};

整体代码,一样的都是复用了红黑树的接口,并没有什么技术含量:

namespace my_map
{template<class K, class V>class map{struct MapKeyOfValue{const K& operator()(const pair<const K, V>& kv){return kv.first;}};public:typedef typename RBTree<K, pair<const K, V>, MapKeyOfValue>::iterator iterator;iterator begin(){return _t.begin();}iterator end(){return _t.end();}bool insert(const pair<const K, V>& kv){return _t.Insert(kv);}private:RBTree<K, pair<const K, V>, MapKeyOfValue> _t;};

最后是红黑树的整体代码,这段代码跟单独写的红黑树的代码差不多,就是在新增节点的操作那里,比较节点的值使用的是仿函数。

#pragma once//使用枚举
enum Colour
{RED,BLACK,
};// 如果是map,则为pair<K, V>; 如果是set,则为k
//因此,对于节点来说,需要再套一层模板,来应付两种不同的情况
template<class T>
struct RBTreeNode
{T _data;RBTreeNode<T>* _left;RBTreeNode<T>* _right;RBTreeNode<T>* _parent;Colour _col;RBTreeNode(const T& data):_data(data), _left(nullptr), _right(nullptr), _parent(nullptr), _col(RED)  //默认是红色{}
};template<class ValueType>
struct __RBTreeIterator
{typedef RBTreeNode<ValueType> Node;typedef __RBTreeIterator<ValueType> Self;Node* _node;__RBTreeIterator(Node* node):_node(node){}ValueType& operator*(){return _node->_data;}ValueType* operator->(){return &_node->_data;}//左 根  右Self& operator++(){//当当前节点的右子树不为空,根据中序遍历的顺序,那就找右子树最小值if (_node->_right){Node* minValue = _node->_right;while (minValue->_left){minValue = minValue->_left;}//找到最小值的节点后,更新节点_node = minValue;}else  //当当前节的的右子树为空,说明它是叶子节点。此时需要判断情况{//判断当前节点是父亲节点的左孩子还是右孩子//第一种情况:如果是cur==parent->_right,即当前节点是父节点的右孩子的话,就//去找祖先节点(这个祖先节点的特征:孩子节点是它的左节点)//第二种情况:当前节点是父亲节点的左孩子,那么下一个节点就是父亲节点了Node* cur = _node;//定义父亲节点。Node* parent = cur->_parent;//如果当前节点不是父亲的右孩子,并且父亲是不存在,那么就是根节点或者是左孩子节点了//那就不进入循环。while (parent && cur == parent->_right){//如果是,那就往上找到下一个节点。cur = cur->_parent;parent = parent->_parent;}//更新节点_node = parent;}return *this;}bool operator!=(const Self& s){return _node != s._node;}
};
//跟节点的定义一样
//因为关联式容器中存储的是<key, value>的键值对,因此
// k为key的类型,
// ValueType: 如果是map,则为pair<K, V>; 如果是set,则为k。如下:
// map->RBTree<K,pair<const K,V>,MapKeyOfT> _t;
// set->RBTree<K,K,SetKeyOfT> _t
// 
// KeyOfValue: 通过value来获取key的一个仿函数类。其作用就是用于比较。
template<class K,class ValueType,class KeyOfValue>
class RBTree
{typedef RBTreeNode<ValueType> Node;
public:typedef __RBTreeIterator<ValueType> iterator;iterator begin(){Node* left = _root;while (left && left->_left){left = left->_left;}return iterator(left);}iterator end(){return iterator(nullptr);}bool Insert(const ValueType& data){//先按二叉搜索树的规矩来创建一棵二叉搜索树if (_root == nullptr){_root = new Node(data);//因为红黑树的根节点是黑色的_root->_col = BLACK;return true;}KeyOfValue kot;Node* parent = nullptr;Node* cur = _root;while (cur){if (kot(cur->_data) < kot(data)){parent = cur;cur = cur->_right;}else if (kot(cur->_data) > kot(data)){parent = cur;cur = cur->_left;}else{return false;}}cur = new Node(data);cur->_col = RED;//多写一步,防止写错代码。if (kot(parent->_data) < kot(data)){parent->_right = cur;cur->_parent = parent;}else{parent->_left = cur;cur->_parent = parent;}//创建完二叉搜索树//开始创建红黑树,使用颜色来判断是否需要调整//循环往上走,循环条件:当走到的parent不为空,并且parent是红色的//即我们列举是三种情况,parent都是红的,就需要重新调整//如果parent是黑色的,那就不需要了。直接就是一棵红黑树,不进入循环while (parent && parent->_col == RED){//保存祖先节点,即g节点Node* grandfther = parent->_parent;//判断父节点是在祖先节点的哪边if (parent == grandfther->_left){//父节点在左边,那么叔叔节点就在右边Node* uncle = grandfther->_right;//情况一:uncle存在且为红。改变颜色即可if (uncle && uncle->_col == RED){//变色。parent->_col = uncle->_col = BLACK;grandfther->_col = RED;//往上走cur = grandfther;parent = cur->_parent;}else  //uncle不存在 或者 存在但是黑色{//情况二  p是g的左孩子,cur是p的左孩子,以g为轴右单旋if (cur == parent->_left){//右单旋RotateR(grandfther);//变色  右单旋后,parent为根节点,变黑色。cur和g节点为红色parent->_col = BLACK;grandfther->_col = RED;}else  //情况三  p是g的左孩子,cur是p的右孩子.{//先以p为轴左旋转RotateL(parent);//变成情况二,再以g为轴右单旋RotateR(grandfther);//变色  cur变成根节点,为黑色。p和g是红色cur->_col = BLACK;grandfther->_col = RED;}break;}}else  //parent是在grandfther的右边{//叔叔节点就在祖先节点的左边Node* uncle = grandfther->_left;//情况一:uncle存在且为红。改变颜色即可if (uncle && uncle->_col == RED){//变色。parent->_col = uncle->_col = BLACK;grandfther->_col = RED;//往上走cur = grandfther;parent = cur->_parent;}else  //uncle不存在 或者 存在但是黑色{//情况二  p是g的右孩子,cur是p的右孩子。if (cur == parent->_right){//左单旋RotateL(grandfther);//变色  右单旋后,parent为根节点,变黑色。cur和g节点为红色parent->_col = BLACK;grandfther->_col = RED;}else  //情况三  p是g的右孩子,cur是p的左孩子.{//先以p为轴右旋转RotateR(parent);//变成情况二,再以g为轴左单旋RotateL(grandfther);//变色  cur变成根节点,为黑色。p和g是红色cur->_col = BLACK;grandfther->_col = RED;}break;}}}//最后将根节点置为黑_root->_col = BLACK;return true;}void RotateL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;if (subRL){subRL->_parent = parent;}Node* ppNode = parent->_parent;subR->_left = parent;parent->_parent = subR;if (ppNode == nullptr){_root = subR;_root->_parent = nullptr;}else{if (ppNode->_left == parent){ppNode->_left = subR;}else{ppNode->_right = subR;}subR->_parent = ppNode;}}void RotateR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;if (subLR){subLR->_parent = parent;}Node* ppNode = parent->_parent;subL->_right = parent;parent->_parent = subL;if (ppNode == nullptr){_root = subL;_root->_parent = nullptr;}else{if (ppNode->_left == parent){ppNode->_left = subL;}else{ppNode->_right = subL;}subL->_parent = ppNode;}}void Inorder(){_Inorder(_root);}void _Inorder(Node* root){if (root == nullptr)return;_Inorder(root->_left);std::cout << root->_kv.first << ": " << root->_kv.second << std::endl;_Inorder(root->_right);}bool Check(Node* root, int blackNum, const int ref){if (root == nullptr){//cout << blackNum << endl;if (blackNum != ref){cout << "违反规则:本条路径的黑色节点的数量跟最左路径不相等" << endl;return false;}return true;}if (root->_col == RED && root->_parent->_col == RED){cout << "违反规则:出现连续红色节点" << endl;return false;}if (root->_col == BLACK){++blackNum;}return Check(root->_left, blackNum, ref)&& Check(root->_right, blackNum, ref);}bool IsBalance(){if (_root == nullptr){return true;}if (_root->_col != BLACK){return false;}int ref = 0;Node* left = _root;while (left){if (left->_col == BLACK){++ref;}left = left->_left;}return Check(_root, 0, ref);}
private:Node* _root = nullptr;
};

相关文章:

使用红黑树模拟实现map和set

在STL的源代码中&#xff0c;map和set的底层原理都是红黑树。但这颗红黑树跟我们单独写的红黑树不一样&#xff0c;它需要改造一下&#xff1a; 改造红黑树 节点的定义 因为map和set的底层都是红黑树。而且map是拥有键值对pair<K,V>的&#xff0c;而set是没有键值对&a…...

【django项目开发】用户登录后缓存权限到redis中(十)

这里写目录标题一、权限的数据的特点二、首先settings.py文件中配置redis连接redis数据库一、权限的数据的特点 需要去数据库中频繁的读和写&#xff0c;为了项目提高运行效率&#xff0c;可以把用户的权限在每次登录的时候都缓存到redis中。这样的话&#xff0c;权限判断的中…...

算法总结c++

文章目录基本概念时间复杂度空间复杂度基本结构1. 数组前缀和差分数组快慢指针(索引)左右指针&#xff08;索引&#xff09;盛水容器三数之和最长回文子串2. 链表双指针删除链表的倒数第 n 个结点翻转链表递归将两个升序链表合并为一个新的 升序 链表链表翻转3. 散列表twoSum无…...

Python 之 NumPy 切片索引和广播机制

文章目录一、切片和索引1. 一维数组2. 二维数组二、索引的高级操作1. 整数数组索引2. 布尔数组索引三、广播机制1. 广播机制规则2. 对于广播规则另一种简单理解一、切片和索引 ndarray 对象的内容可以通过索引或切片来访问和修改&#xff08;&#xff09;&#xff0c;与 Pytho…...

Redis【包括Redis 的安装+本地远程连接】

Redis 一、为什么要用缓存&#xff1f; 缓存定义 缓存是一个高速数据交换的存储器&#xff0c;使用它可以快速的访问和操作数据。 程序中的缓存 在我们程序中&#xff0c;如果没有使用缓存&#xff0c;程序的调用流程是直接访问数据库的&#xff1b; 如果多个程序调用一个数…...

深度学习训练营_第P3周_天气识别

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f366; 参考文章&#xff1a;Pytorch实战 | 第P3周&#xff1a;彩色图片识别&#xff1a;天气识别**&#x1f356; 原作者&#xff1a;K同学啊|接辅导、项目定制**␀ 本次实验有两个新增任务&…...

“华为杯”研究生数学建模竞赛2006年-【华为杯】C题:维修线性流量阀时的内筒设计问题(附获奖论文及matlab代码)

赛题描述 油田采油用的油井都是先用钻机钻几千米深的孔后,再利用固井机向四周的孔壁喷射水泥砂浆得到水泥井管后形成的。固井机上用来控制砂浆流量的阀是影响水泥井管质量的关键部件,但也会因磨损而损坏。目前我国还不能生产完整的阀体,固井机仍依赖进口。由于损坏的内筒已…...

数据结构:带环单链表基础OJ练习笔记(leetcode142. 环形链表 II)(leetcode三题大串烧)

目录 一.前言 二.leetcode160. 相交链表 1.问题描述 2.问题分析与求解 三.leetcode141. 环形链表 1.问题描述 2.代码思路 3.证明分析 下一题会用到的重要小结论&#xff1a; 四.leetcode142. 环形链表 II 1.问题描述 2.问题分析与求解 Judgecycle接口&#xf…...

数模美赛如何找数据 | 2023年美赛数学建模必备数据库

2023美赛资料分享/思路答疑群&#xff1a;322297051 欧美相关统计数据&#xff08;一般美赛这里比较多&#xff09; 1、http://www.census.gov/ 美国统计局&#xff08;统计调查局或普查局&#xff09;官方网站 The Census Bureau Web Site provides on-line access to our …...

SSTI漏洞原理及渗透测试

模板引擎&#xff08;Web开发中&#xff09; 是为了使 用户界面 和 业务数据&#xff08;内容&#xff09;分离而产生的&#xff0c;它可以生成特定格式的文档&#xff0c; 利用模板引擎来生成前端的HTML代码&#xff0c;模板引擎会提供一套生成HTML代码的程序&#xff0c;之后…...

【算法基础】高精度除法

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前是C语言 算法学习者 ✈️专栏&#xff1a;【C/C】算法 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac…...

optimizer.zero_grad(), loss.backward(), optimizer.step()的理解及使用

optimizer.zero_grad&#xff0c;loss.backward&#xff0c;optimizer.step用法介绍optimizer.zero_grad()&#xff1a;loss.backward()&#xff1a;optimizer.step()&#xff1a;用法介绍 这三个函数的作用是将梯度归零&#xff08;optimizer.zero_grad()&#xff09;&#x…...

融资、量产和一栈式布局,这家Tier 1如此备战高阶智驾决赛圈

作者 | Bruce 编辑 | 于婷从早期的ADAS&#xff0c;到高速/城市NOA&#xff0c;智能驾驶的竞争正逐渐升级&#xff0c;这对于车企和供应商的核心技术和产品布局都是一个重要的考验。 部分智驾供应商已经在囤积粮草&#xff0c;响应变化。 2023刚一开年&#xff0c;智能驾驶领域…...

centos7.8安装oralce11g

文章目录环境安装文件准备添加用户操作系统环境配置解压安装问题解决创建用户远程连接为了熟悉rman备份操作&#xff0c;参照大神的博客在centos中安装了一套oracle11g&#xff0c;将安装步骤记录如下环境安装文件准备 这里准备一台centos7.8 虚拟机 配置ip 192.168.18.100 主…...

【蓝桥杯集训·每日一题】AcWing 3956. 截断数组

文章目录一、题目1、原题链接2、题目描述二、解题报告1、思路分析2、时间复杂度3、代码详解三、知识风暴一维前缀和一、题目 1、原题链接 3956. 截断数组 2、题目描述 给定一个长度为 n 的数组 a1,a2,…,an。 现在&#xff0c;要将该数组从中间截断&#xff0c;得到三个非空子…...

万丈高楼平地起:Linux常用命令

目录 系统管理命令 man命令 ls命令 cd命令 useradd命令 passwd命令 free命令 whoami命令 ps命令 date命令 pwd命令 shutdown命令 文件目录管理命令 touch命令 cat命令 mkdir命令 rm命令 cp命令 mv命令 find命令 more指令 less指令 head指令 tail指令 …...

Linux(Linux的连接使用)

连接Linux我们一般使用CRT或者Xshell工具进行连接使用。 如CRT使用SSH的方式 输出主机&#xff0c;账户&#xff0c;密码那些就可以连接上了。 Linux系统是一个文件型操作系统&#xff0c;有一句话说Linux的一切皆是文件。Linux系统的启动大致有下面几个步骤 Linux系统有7个运…...

Unity中画2D图表(2)——用XChart包绘制散点分布图 + 一条直线方程

散点图用于显示关系。 对于 【相关性】 &#xff0c;散点图有助于显示两个变量之间线性关系的强度。 对于 【回归】 &#xff0c;散点图常常会添加拟合线。 举例1&#xff1a;你可以展示【年降雨量】与【玉米亩产量】的关系 举例2&#xff1a;你也可以分析各个【节假日】与【大…...

Go 排序包 sort

写在前面的使用总结&#xff1a; 排序结构体 实现Len&#xff0c;Less&#xff0c;Swap三个函数 package main import ( "fmt" "sort") type StuScore struct { name string score int } type StuScores []StuScore func (s StuScores) Len(…...

Java Email 发HTML邮件工具 采用 freemarker模板引擎渲染

Java Email 发HTML邮件工具 采用 freemarker模板引擎 1.常用方式对比 Java发送邮件有很多的实现方式 第一种&#xff1a;Java 原生发邮件mail.jar和activation.jar <!-- https://mvnrepository.com/artifact/javax.mail/mail --> <dependency><groupId>jav…...

CNI 网络流量分析(六)Calico 介绍与原理(二)

文章目录CNI 网络流量分析&#xff08;六&#xff09;Calico 介绍与原理&#xff08;二&#xff09;CNIIPAM指定 IP指定非 IPAM IPCNI 网络流量分析&#xff08;六&#xff09;Calico 介绍与原理&#xff08;二&#xff09; CNI 支持多种 datapath&#xff0c;默认是 linuxDa…...

短视频标题的几种类型和闭坑注意事项

目录 短视频标题的几种类型 1、悬念式 2、蹭热门式 3、干货式 4、对比式方法 5、总分/分总式方法 6、挑战式方式 7、启发激励式 8、讲故事式 02注意事项 1、避免使用冷门、生僻词汇 标题是点睛之笔&#xff0c;核心是视频内容 短视频标题的几种类型 1、悬念式 通过…...

操作系统——1.操作系统的概念、定义和目标

目录 1.概念 1.1 操作系统的种类 1.2电脑的组成 1.3电脑组成的介绍 1.4操作系统的概念&#xff08;定义&#xff09; 2.操作系统的功能和目标 2.1概述 2.2 操作系统作为系统资源的管理者 2.3 操作系统作为用户和计算机硬件间的接口 2.3.1用户接口的解释 2.3.2 GUI 2.3.3接…...

【html弹框拖拽和div拖拽功能】原生html页面引入vue语法后通过自定义指令简单实现div和弹框拖拽功能

前言 这是html版本的。只是引用了vue的语法。 这是很多公司会出现的一种情况&#xff0c;就是原生的页面&#xff0c;引入vue的语法开发 这就导致有些vue上很简单的功能。放到这里需要转换一下 以前写过一个vue版本的帖子&#xff0c;现在再加一个html版本的。 另一个vue版本…...

2023新华为OD机试题 - 计算网络信号(JavaScript) | 刷完必过

计算网络信号 题目 网络信号经过传递会逐层衰减,且遇到阻隔物无法直接穿透,在此情况下需要计算某个位置的网络信号值。 注意:网络信号可以绕过阻隔物 array[m][n] 的二维数组代表网格地图,array[i][j] = 0代表 i 行 j 列是空旷位置;array[i][j] = x(x 为正整数)代表 i 行 …...

27.边缘系统的架构

文章目录27 Architecures for the Edge 边缘系统的架构27.1 The Ecosystem of Edge-Dominant Systems 边缘主导系统的生态系统27.2 Changes to the Software Development Life Cycle 软件开发生命周期的变化27.3 Implications for Architecture 对架构的影响27.4 Implications …...

机器学习强基计划8-1:图解主成分分析PCA算法(附Python实现)

目录0 写在前面1 为什么要降维&#xff1f;2 主成分分析原理3 PCA与SVD的联系4 Python实现0 写在前面 机器学习强基计划聚焦深度和广度&#xff0c;加深对机器学习模型的理解与应用。“深”在详细推导算法模型背后的数学原理&#xff1b;“广”在分析多个机器学习模型&#xf…...

Hudi-集成Spark之spark-shell 方式

Hudi集成Spark之spark-shell 方式 启动 spark-shell &#xff08;1&#xff09;启动命令 #针对Spark 3.2 spark-shell \--conf spark.serializerorg.apache.spark.serializer.KryoSerializer \--conf spark.sql.catalog.spark_catalogorg.apache.spark.sql.hudi.catalog.Hoo…...

Python爬虫:从js逆向了解西瓜视频的下载链接的生成

前言 最近花费了几天时间,想获取西瓜视频这个平台上某个视频的下载链接,运用js逆向进行获取。其实,如果小编一开始就注意到这一点(就是在做js逆向时,打了断点之后,然后执行相关代码,查看相关变量的值,结果一下子就蹦出很多视频相关的数据,查看了网站下的相关api链接,也…...

Numpy-如何对数组进行切割

前言 本文是该专栏的第24篇,后面会持续分享python的数据分析知识,记得关注。 继上篇文章,详细介绍了使用numpy对数组进行叠加。本文再详细来介绍,使用numpy如何对数组进行切割。说句题外话,前面有重点介绍numpy的各个知识点。 感兴趣的同学,可查看笔者之前写的详细内容…...

wordpress 免费好用主题/厦门网站推广费用

收集到各路影友对于SW系列的咨询以及使用疑问&#xff0c;在此一一作答&#xff0c;可能比较长~感谢大家对球球的支持&#xff01;1、SW270C分辨率只有2K&#xff0c;够用吗&#xff1f;研发之初请教过专业摄影师&#xff0c;他们认为27英寸而言&#xff0c;2K分辨率算是合理的…...

网络推广排名/关键词优化技巧

组建团队 人员培养 知识分享...

山西建设执业注册中心网站/百度域名注册官网

Redis 压缩列表(ziplist)1. 介绍压缩列表(ziplist)是哈希键的底层实现之一。它是经过特殊编码的双向链表&#xff0c;和整数集合(intset)一样&#xff0c;是为了提高内存的存储效率而设计的。当保存的对象是小整数值&#xff0c;或者是长度较短的字符串&#xff0c;那么redis就…...

江西网站制作的公司哪家好/推广运营平台

MT2601是一种高度集成的基带平台兼备调制解调器和应用处理子系统使能智能可穿戴应用&#xff0c;具有集成性蓝牙&#xff0c;WiLAN和GPS模块。芯片集成双核ARMCORTEX-A7支持多种引导接口&#xff0c;包括EMMC和32位此外&#xff0c;对于最佳性能&#xff0c;LPDRD2一组广泛的接…...

上海营销网站建设定制服务/热搜词排行榜关键词

C语言练习&#xff1a;第二大整数问题描述编写一个程序&#xff0c;读入一组整数(不超过20个)&#xff0c;当用户输入0时&#xff0c;表示输入结束。然后程序将从这组整数中&#xff0c;把第二大的那个整数找出来&#xff0c;并把它打印出来。说明&#xff1a;(1)0表示输入结束…...

wordpress清新/上海网络推广专员

<jQuery EasyUI最新版下载> 在本教程中&#xff0c;你将学习到有关于easyui折叠面板的知识。折叠面板包含了一系列的面板&#xff0c;其中所有的面板标题都是可见的&#xff0c;但只有一个面板的主体内容在某个时间是可见的。当用户点击面板标题时&#xff0c;该面板的主…...