【C++】用红黑树模拟实现set与map

目录

一、红黑树的完善:

1、红黑树节点模版的修改:

2、仿函数在模拟实现中的应用:

3、新增迭代器:

4、红黑树中的迭代器实现:

二、set与map的模拟实现:

1、insert:

2、map的[ ]:

三、测试:

四、完整代码:


红黑树初始代码:

#pragma once
#include<iostream>using namespace std;enum COLOR
{RED,BLACK
};template<class K, class V>
struct RBTreeNode
{RBTreeNode<K, V>* _left;RBTreeNode<K, V>* _right;RBTreeNode<K, V>* _parent;pair<K, V> _kv;COLOR col;RBTreeNode(const pair<K, V>& kv):_left(nullptr), _right(nullptr), _parent(nullptr), _kv(kv), col(RED){}
};template<class K, class V>
class RBTree
{typedef RBTreeNode<K, V>  Node;
public:bool Insert(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->_left;}else if (cur->_kv.first < kv.first){parent = cur;cur = cur->_right;}else{return false;}}//走到这就是找到了cur = new Node(kv);cur->col = RED;//再连接到这个红黑树中if (parent->_kv.first > cur->_kv.first){parent->_left = cur;}else//parent->_kv.first < cur->_kv.first{parent->_right = cur;}cur->_parent = parent;//已经连接完成后while (parent && parent->col == RED){//这里祖父必定存在,因为如果进循环后parent就是red,然而red不可能为根节点,所以parent的parent必定存在Node* grandfather = parent->_parent;if (parent == grandfather->_left){Node* uncle = grandfather->_right;if (uncle && uncle->col == RED){//修改颜色uncle->col = BLACK;parent->col = BLACK;grandfather->col = RED;//修改curcur = grandfather;//修改parent继续指向cur的parentparent = cur->_parent;}else//uncle不存在或者uncle为黑色就需要旋转了{if (cur == parent->_left){RotateR(grandfather);parent->col = BLACK;grandfather->col = RED;}else//cur == parent->_right{RotateL(parent);RotateR(grandfather);cur->col = BLACK;grandfather->col = RED;}break;}}else//parent == grandfather->_right{Node* uncle = grandfather->_left;if (uncle && uncle->col == RED){//修改颜色uncle->col = BLACK;parent->col = BLACK;grandfather->col = RED;//修改curcur = grandfather;//修改parent继续指向cur的parentparent = cur->_parent;}else//uncle不存在或者uncle为黑色就需要旋转了{if (cur == parent->_right){RotateL(grandfather);parent->col = BLACK;grandfather->col = RED;}else//cur == parent->_right{RotateR(parent);RotateL(grandfather);cur->col = BLACK;grandfather->col = RED;}break;}}}_root->col = BLACK;return true;}//左单旋void RotateL(Node* parent){Node* cur = parent->_right;Node* curleft = cur->_left;parent->_right = curleft;if (curleft){curleft->_parent = parent;}cur->_left = parent;//将parent的父节点保存起来Node* pparent = parent->_parent;parent->_parent = cur;if (parent == _root){_root = cur;cur->_parent = nullptr;}else{if (pparent->_kv.first < cur->_kv.first){pparent->_right = cur;}else //if (pparent->_kv.first > cur->_kv.first){pparent->_left = cur;}cur->_parent = pparent;}}//右单旋void RotateR(Node* parent){Node* cur = parent->_left;Node* curright = cur->_right;parent->_left = curright;if (curright){curright->_parent = parent;}cur->_right = parent;//将parent的父节点保存起来Node* pparent = parent->_parent;parent->_parent = cur;if (parent == _root){_root = cur;cur->_parent = nullptr;}else{if (pparent->_kv.first < cur->_kv.first){pparent->_right = cur;}else //if (pparent->_kv.first > cur->_kv.first){pparent->_left = cur;}cur->_parent = pparent;}}bool CheckColor(Node* root, int blacknum, int benchmark){if (root == nullptr){if (blacknum != benchmark){cout << "黑色节点的数量不匹配" << endl;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 CheckColor(root->_left, blacknum, benchmark)&& CheckColor(root->_right, blacknum, benchmark);}bool IsRBTree(){return _IsRBTree(_root);}bool _IsRBTree(Node* root){if (root == nullptr)return true;if (root->col == RED){return false;}//基准值int benchmark = 0;Node* cur = _root;while (cur){if (cur->col == BLACK)++benchmark;cur = cur->_left;}return CheckColor(root, 0, benchmark);}
private:Node* _root = nullptr;
};

一、红黑树的完善:

1、红黑树节点模版的修改:

这里要将红黑树节点的模版从两个修改为一个T,这是首先通过set或者map的模版参数传给红黑树的第二个模版参数进行实例化Node。

2、仿函数在模拟实现中的应用:

再节点中存储的是T的,在set中这个T是K结构的,在进行比较的时候,直接访问比较就可以了,但是在map中这个T是K,V结构的键值对,在进行比较的时候,就不能够直接比较,这个时候就可以通过仿函数(通过对一个类进行()的重载,使这个类在使用的时候看上去像一个函数)取这个键值对中的first来进行比较即可。

所以在传模版的时候就需要第三个模版参数来进行仿函数的控制。

map中的仿函数实现:

template<class K, class V>
class map
{struct MapKeyOfT{const K& operator()(const pair<K, V>& kv){return kv.first;}};
public:private:RBTree<K, pair<const K, V>, MapKeyOfT> _t;
};

set中的仿函数的实现:

    template<class K>class set{struct SetKeyOfT{const K& operator()(const K& key){return key;}};public:private:RBTree<K, K, SetKeyOfT> _t;};

仿函数在比较中的应用:

上面是部分代码的修改:

下面是仿函数在红黑树中的使用思路:

如上所示:

通过在自我实现的map或者是set中进行仿函数的实现,在set中返回key值即可,在map中返回这个键对值的first即可。

这样在比较的时候就可以实现map的大小比较了。

3、新增迭代器:

将红黑树的节点进行再一次的封装,这样封装出一个迭代器的类,应该是只有一个模版参数T但是要实现const迭代器和普通迭代器要使用这个迭代器的类,这样再加上两个模版参数来进行迭代器的实现。

template<class T, class Ptr, class Ref>
struct __TreeIterator
{typedef RBTreeNode<T> Node;typedef __TreeIterator<T, Ptr, Ref> Self;Node* _node;
};

构造函数:

	__TreeIterator(Node* node):_node(node){}

解引用操作:

	Ref operator*(){return _node->_data;}

->操作:

	Ptr operator->(){return &_node->_data;}

!=操作

	bool operator!=(const Self& s) const{return _node != s._node;}

++操作

思路:

首先进行此判断,当前迭代器所指向的位置进行++操作后,要么在右子树的最小节点或者是往祖先找,下一个节点要是一个父节点的左节点。

那么就进行判断:

如果此时迭代器所指向的节点右边存在子树,那么就直接找到右子树的最左节点给node最后进行返回*this.

如果此时迭代器所指向的节点右边不存在子树,那么就往祖先找,直到找到孩子是父节点左的那个节点,就是下一个要访问的节点。

Self& operator++()
{if (_node->_right){//右子树不是空,就找右子树的最小节点(最左边的节点)Node* RightTree = _node->_right;while (RightTree->_left){RightTree = RightTree->_left;}_node = RightTree;}else{//右为空,就找孩子是父节点的左孩子的那个父节点Node* cur = _node;Node* parent = cur->_parent;while (parent && cur == parent->_right){cur = cur->_parent;parent = parent->_parent;}_node = parent;}return *this;
}

--操作:

思路:

首先进行此判断,当前迭代器所指向的位置进行--操作后,要么在左子树的最大节点或者是往祖先找,下一个节点要是一个父节点的右节点。

如果迭代器所指向的节点的左子树不为空,则--操作后应该找到其左子树当中的最右结点。
如果迭代器所指向的节点的左子树为空,则--操作后应该在该结点的祖先结点中,找到孩子不在父亲左的祖先。

那么就进行判断:

如果此时迭代器所指向的节点左边存在子树,那么就直接找到左子树的最右节点给node最后进行返回*this.

如果此时迭代器所指向的节点左边不存在子树,那么就往祖先找,直到找到孩子是父节点右的那个节点,就是下一个要访问的节点。

Self& operator--()
{if (_node->_left){Node* RootRight = _node->_left;while (RootRight->_right){RootRight = RootRight->_right;}_node = RootRight;}else{//要找到孩子是父亲的右边的那个节点就是--后的值Node* cur = _node;Node* parent = _node->_parent;while (parent && cur == parent->_left){cur = cur->_parent;parent = parent->_parent;}_node = parent;}return *this;
}

4、红黑树中的迭代器实现:

既然有了迭代器这个类,那么在红黑树中就可以进行begin和end的实现:

template<class K, class T, class KeyOfT>
class RBTree
{typedef RBTreeNode<T>  Node;
public:typedef __TreeIterator<T, T*, T&> iterator;typedef __TreeIterator<T, const T*, const T&> const_iterator;iterator begin(){Node* leftmin = _root;while (leftmin && leftmin->_left){leftmin = leftmin->_left;}return iterator(leftmin);}iterator end(){return iterator(nullptr);}const_iterator begin() const{Node* leftmin = _root;while (leftmin && leftmin->_left){leftmin = leftmin->_left;}return const_iterator(leftmin);}const_iterator end() const{return const_iterator(nullptr);}
};

二、set与map的模拟实现:

在下面我们需要修改insert的实现,接着通过insert来进行map中的[ ]的实现。

1、insert:

首先将insert的返回值修改为iterator和bool的键对值,接着将实现中的return都修改一下:

在修改RBTree中的insert之后,也要对map和set中的insert进行修改:

map中:

直接进行调用即可

set中:

不能够直接进行调用,因为存在迭代器不匹配的问题,那么看看STL标准模板库中的解决方式:

上述是在set中的标准库中的实现,先直接抄过来看看:

可以知道,将set的insert实现的代码从直接调用变成上述中就可以编译通过,解决方法:

那么就需要在迭代器类中增加一个构造函数

当这个类被实例化成const迭代器的时候,这就是一个普通构造,是普通迭代器构造const迭代器,但是如果这个类被实例化成普通迭代器的时候,新增的就是一个拷贝构造(普通迭代器构造普通迭代器)

2、map的[ ]:

三、测试:

int main()
{ppr::map<int, int> m;m.Insert(make_pair(1, 1));m.Insert(make_pair(3, 3));m.Insert(make_pair(2, 2));ppr::map<int, int>::iterator mit = m.begin();while (mit != m.end()){// 不能修改key,可以修改value//mit->first = 1;mit->second = 2;cout << mit->first << ":" << mit->second << endl;++mit;}cout << endl;ppr::set<int> s;s.Insert(5);s.Insert(2);s.Insert(2);s.Insert(12);s.Insert(22);s.Insert(332);s.Insert(7);ppr::set<int>::iterator it = s.begin();while (it != s.end()){cout << *it << " ";++it;}cout << endl;for (const auto& e : s){cout << e << " ";}cout << endl;ppr::map<string, string> dict;dict.Insert(make_pair("sort", "111"));dict["apple"]; // 插入for (const auto& kv : dict){cout << kv.first << ":" << kv.second << endl;}cout << endl;dict["apple"] = "苹果"; // 修改dict["sort"] = "222"; // 修改dict["pear"] = "梨"; // 插入+修改for (const auto& kv : dict){cout << kv.first << ":" << kv.second << endl;}cout << endl;return 0;
}

四、完整代码:

红黑树:

#pragma once
#include<iostream>
using namespace std;
enum COLOR
{RED,BLACK
};template<class T>
struct RBTreeNode
{RBTreeNode<T>* _left;RBTreeNode<T>* _right;RBTreeNode<T>* _parent;T _data;COLOR col;RBTreeNode(const T& data):_left(nullptr), _right(nullptr), _parent(nullptr), _data(data), col(RED){}
};template<class T, class Ptr, class Ref>
struct __TreeIterator
{typedef RBTreeNode<T> Node;typedef __TreeIterator<T, Ptr, Ref> Self;typedef __TreeIterator<T, T*, T&> iterator;__TreeIterator(const iterator& it):_node(it._node){}Node* _node;__TreeIterator(Node* node):_node(node){}Ref operator*(){return _node->_data;}Ptr operator->(){return &_node->_data;}bool operator!=(const Self& s) const{return _node != s._node;}Self& operator--(){if (_node->_left){Node* RootRight = _node->_left;while (RootRight->_right){RootRight = RootRight->_right;}_node = RootRight;}else{//要找到孩子是父亲的右边的那个节点就是--后的值Node* cur = _node;Node* parent = _node->_parent;while (parent && cur == parent->_left){cur = cur->_parent;parent = parent->_parent;}_node = parent;}return *this;}Self& operator++(){if (_node->_right){//右子树不是空,就找右子树的最小节点(最左边的节点)Node* RightTree = _node->_right;while (RightTree->_left){RightTree = RightTree->_left;}_node = RightTree;}else{//右为空,就找孩子是父节点的左孩子的那个父节点Node* cur = _node;Node* parent = cur->_parent;while (parent && cur == parent->_right){cur = cur->_parent;parent = parent->_parent;}_node = parent;}return *this;}
};template<class K, class T, class KeyOfT>
class RBTree
{typedef RBTreeNode<T>  Node;
public:typedef __TreeIterator<T, T*, T&> iterator;typedef __TreeIterator<T, const T*, const T&> const_iterator;iterator begin(){Node* leftmin = _root;while (leftmin && leftmin->_left){leftmin = leftmin->_left;}return iterator(leftmin);}iterator end(){return iterator(nullptr);}const_iterator begin() const{Node* leftmin = _root;while (leftmin && leftmin->_left){leftmin = leftmin->_left;}return const_iterator(leftmin);}const_iterator end() const{return const_iterator(nullptr);}Node* Find(const K& key){Node* cur = _root;KeyOfT kot;while (cur){if (kot(cur->_data) < key){cur = cur->_right;}else if (kot(cur->_data) > key){cur = cur->_left;}else{return cur;}}return nullptr;}pair<iterator, bool> Insert(const T& data){//先进来判断这个树是不是空树if (_root == nullptr){_root = new Node(data);_root->col = BLACK;return make_pair(iterator(_root), true);}Node* parent = nullptr;Node* cur = _root;Node* newnode = cur;//找到要插入的位置KeyOfT kot;while (cur){if (kot(cur->_data) > kot(data)){parent = cur;cur = cur->_left;}else if (kot(cur->_data) < kot(data)){parent = cur;cur = cur->_right;}else{return make_pair(iterator(cur), false);}}//走到这就是找到了cur = new Node(data);cur->col = RED;//再连接到这个红黑树中if (kot(parent->_data) > kot(cur->_data)){parent->_left = cur;}else{parent->_right = cur;}cur->_parent = parent;//已经连接完成后while (parent && parent->col == RED){//这里祖父必定存在,因为如果进循环后parent就是red,然而red不可能为根节点,所以parent的parent必定存在Node* grandfather = parent->_parent;if (parent == grandfather->_left){Node* uncle = grandfather->_right;if (uncle && uncle->col == RED){//修改颜色uncle->col = BLACK;parent->col = BLACK;grandfather->col = RED;//修改curcur = grandfather;//修改parent继续指向cur的parentparent = cur->_parent;}else//uncle不存在或者uncle为黑色就需要旋转了{if (cur == parent->_left){RotateR(grandfather);parent->col = BLACK;grandfather->col = RED;}else//cur == parent->_right{RotateL(parent);RotateR(grandfather);cur->col = BLACK;grandfather->col = RED;}break;}}else//parent == grandfather->_right{Node* uncle = grandfather->_left;if (uncle && uncle->col == RED){//修改颜色uncle->col = BLACK;parent->col = BLACK;grandfather->col = RED;//修改curcur = grandfather;//修改parent继续指向cur的parentparent = cur->_parent;}else//uncle不存在或者uncle为黑色就需要旋转了{if (cur == parent->_right){RotateL(grandfather);parent->col = BLACK;grandfather->col = RED;}else//cur == parent->_right{RotateR(parent);RotateL(grandfather);cur->col = BLACK;grandfather->col = RED;}break;}}}_root->col = BLACK;return make_pair(iterator(newnode), true);}//左单旋void RotateL(Node* parent){Node* cur = parent->_right;Node* curleft = cur->_left;parent->_right = curleft;if (curleft){curleft->_parent = parent;}cur->_left = parent;//将parent的父节点保存起来Node* pparent = parent->_parent;parent->_parent = cur;if (parent == _root){_root = cur;cur->_parent = nullptr;}else{if (pparent->_left == parent){pparent->_left = cur;}else{pparent->_right = cur;}cur->_parent = pparent;}}//右单旋void RotateR(Node* parent){Node* cur = parent->_left;Node* curright = cur->_right;parent->_left = curright;if (curright){curright->_parent = parent;}cur->_right = parent;//将parent的父节点保存起来Node* pparent = parent->_parent;parent->_parent = cur;if (parent == _root){_root = cur;cur->_parent = nullptr;}else{if (pparent->_left == parent){pparent->_left = cur;}else{pparent->_right = cur;}cur->_parent = pparent;}}bool CheckColor(Node* root, int blacknum, int benchmark){if (root == nullptr){if (blacknum != benchmark){cout << "黑色节点的数量不匹配" << endl;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 CheckColor(root->_left, blacknum, benchmark)&& CheckColor(root->_right, blacknum, benchmark);}bool IsRBTree(){return _IsRBTree(_root);}bool _IsRBTree(Node* root){if (root == nullptr)return true;if (root->col == RED){return false;}//基准值int benchmark = 0;Node* cur = _root;while (cur){if (cur->col == BLACK)++benchmark;cur = cur->_left;}return CheckColor(root, 0, benchmark);}
private:Node* _root = nullptr;
};

模拟实现map:

#pragma once
#include"RBTree.h"
namespace ppr
{template<class K, class V>class map{struct MapKeyOfT{const K& operator()(const pair<K, V>& kv){return kv.first;}};public:typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::iterator iterator;typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::const_iterator const_iterator;iterator begin(){return _t.begin();}iterator end(){return _t.end();}const_iterator begin() const{return _t.begin();}const_iterator end() const{return _t.end();}V& operator[](const K& key){pair<iterator, bool> ret = Insert(make_pair(key, V()));return ret.first->second;}pair<iterator, bool> Insert(const pair<K, V>& kv){return _t.Insert(kv);}private:RBTree<K, pair<const K, V>, MapKeyOfT> _t;};
}

模拟实现set:

#pragma once
#include"RBTree.h"
namespace ppr
{template<class K>class set{struct SetKeyOfT{const K& operator()(const K& key){return key;}};public:typedef typename RBTree<K, K, SetKeyOfT>::const_iterator iterator;typedef typename RBTree<K, K, SetKeyOfT>::const_iterator const_iterator;iterator begin() const{return _t.begin();}iterator end() const{return _t.end();}pair<iterator, bool> Insert(const K& kv){//类模版里面取内置类型要加上typename告诉编译器这是一个类型pair<typename RBTree<K, K, SetKeyOfT>::iterator, bool> ret = _t.Insert(kv);return pair<iterator, bool>(ret.first, ret.second);}private:RBTree<K, K, SetKeyOfT> _t;};
}

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

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

相关文章

vue中关于router.beforeEach()的用法

router.beforeEach()是Vue.js中的路由守卫&#xff0c;用于在路由跳转前进行校验、取消、重定向等操作。 基本使用&#xff1a; const router new VueRouter({ ... })router.beforeEach((to, from, next) > {// ... }) to: 即将要进入的目标路由对象 from: 当前导航正要…

HTML的介绍

HTML HTML是一种超文本标记语言,超文本是指,除了文本之外,还可能包含图片,音频,或者评注等的 文本形式,比文本强大,通过链接和交互方式来组织和呈现信息.标记语言是指,由标签构成的语言.HTML定义了多种不同的标签,用来表示不同的内容. 标签的介绍: 1.<h3> 三级 </h3&…

如何彻底掌握 JavaScript 23种设计模式

设计模式是解决特定问题的常用解决方案&#xff0c;它们可以帮助开发者编写更清晰、可维护、可扩展的代码。在 JavaScript 中&#xff0c;常见的设计模式可以分为三大类&#xff1a;创建型模式、结构型模式 和 行为型模式。本文将全面介绍 JavaScript 中常见的设计模式&#xf…

03_23 种设计模式之《原型模式》

文章目录 一、原型模式基础知识原型模式的结构应用场景 实例拷贝构造函数被调用场景如下&#xff1a;典型的应用场景&#xff1a; 一、原型模式基础知识 原型模式是一种创建型设计模式&#xff0c;其功能为复制一个运行时的对象&#xff0c;包括对象各个成员当前的值。而代码又…

Python知识点:基于Python技术,如何使用YOLO进行实时物体检测

开篇&#xff0c;先说一个好消息&#xff0c;截止到2025年1月1日前&#xff0c;翻到文末找到我&#xff0c;赠送定制版的开题报告和任务书&#xff0c;先到先得&#xff01;过期不候&#xff01; 使用YOLO进行实时物体检测的Python技术详解 实时物体检测是计算机视觉中的一个关…

等保测评中安全计算环境高风险分析

在信息安全等级保护测评中&#xff0c;安全计算环境的重要性不言而喻。它涵盖了从网络设备、主机设备到数据安全等多个关键领域&#xff0c;一旦出现高风险情况&#xff0c;可能会对整个信息系统造成严重的安全威胁。 一、安全审计功能缺失 如果重要核心网络设备、安全设备、操…

云计算第四阶段 CLOUD2周目 01-03

国庆假期前&#xff0c;给小伙伴们更行完了云计算CLOUD第一周目的内容&#xff0c;现在为大家更行云计算CLOUD二周目内容&#xff0c;内容涉及K8S组件的添加与使用&#xff0c;K8S集群的搭建。最重要的主体还是资源文件的编写。 (*^▽^*) 环境准备&#xff1a; 主机清单 主机…

matlab 判断多组数据的分布是否一致,可以使用什么方法?

在 MATLAB 中&#xff0c;可以使用以下几种方法来判断多组数据的分布是否一致&#xff1a; 1. Kolmogorov-Smirnov 检验 (K-S Test) K-S 检验是一种非参数检验&#xff0c;用于比较两组数据是否来自相同的分布。MATLAB 提供了 kstest2 函数来进行这种检验。该方法适用于连续分…

【D3.js in Action 3 精译_033】4.1.0 DIY 实战:如何通过学习 d3.autoType 函数深度参与 D3 生态建设

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第一部分 D3.js 基础知识 第一章 D3.js 简介&#xff08;已完结&#xff09; 1.1 何为 D3.js&#xff1f;1.2 D3 生态系统——入门须知1.3 数据可视化最佳实践&#xff08;上&#xff09;1.3 数据可…

基于YOLO11/v10/v8/v5深度学习的安检X光危险品检测与识别系统设计与实现【python源码+Pyqt5界面+数据集+训练代码】

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

Microsoft Visual Studio安装gtest

1. 参考【Windows Visual Studio下安装和使用google test&#xff08;gtest&#xff09;】 https://blog.csdn.net/Bule_Zst/article/details/78420894 2. 编译gtest使用Win32模式。 3. 配置属性&#xff0c;C/C&#xff0c;常规&#xff0c;附加包含目录 …

Zilliz获Forrester报告全球第一;OB支持向量能力;Azure发布DiskANN;阿里云PG发布内置分析引擎

重要更新 1. Azure发布PostgreSQL向量索引扩展DiskANN&#xff0c;声称在构建HNSW/IVFFlat索引上&#xff0c;速度、精准度都超越pg_vector&#xff0c;并解决了pg_vector长期存在的偶发性返回错误结果的问题( [1] )。 2. 阿里云RDS PostgreSQL 发布AP加速引擎&#xff08;rds…

《Programming from the Ground Up》读后感

之所以看这本书&#xff0c;是想了解一些跟汇编相关的知识&#xff0c;打开这本书后就被作者的观点——“If you don’t understand something the first time, reread it. If you still don’t understand it, it is sometimes best to take it by faith and come back to it …

qemu启动busybox虚拟机网络连接配置

一、busybox文件系统网络问题 由于根文件是用busybox构建&#xff0c;所以很多配置文件是没有的&#xff0c;包括部分网络的默认设置。启动虚拟机后只能使用ip命令和ifconfig命令查看网络状态。 二、开启qemu网络支持 想要使虚拟机上网&#xff0c;最简单的方式可以使用 -netde…

error: RPC failed; curl 16 Error in the HTTP2 framing layer

yschai@LAPTOP-F2L146JK:~$ git clone https://github.com/Chyusen/yschai.git Cloning into ‘yschai’… error: RPC failed; curl 16 Error in the HTTP2 framing layer fatal: expected flush after ref listing 使用Ubuntu在git clone github上的项目的时候,遇到以上报错…

Opencv中的直方图(3)直方图比较函数compareHist()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 比较两个直方图。 函数 cv::compareHist 使用指定的方法比较两个密集或两个稀疏直方图。 该函数返回 d ( H 1 , H 2 ) d(H_1, H_2) d(H1​,H2​…

南科大分享|大数据技术如何赋能大模型训练及开发

嘉宾介绍 张松昕&#xff0c;南方科技大学统计与数据科学系研究学者&#xff0c;UCloud 顾问资深算法专家&#xff0c;曾任粤港澳大湾区数字经济研究院访问学者&#xff0c;主导大模型高效分布式训练框架的开发&#xff0c;设计了 SUS-Chat-34B 的微调流程&#xff0c;登顶 Ope…

基于深度学习的图像背景去除系统

项目介绍 该项目的主要目标是开发一种高效、准确且适用于高分辨率的抠图系统&#xff0c;能够在自然场景中精确定位并分割出图像中的人、动物、建筑等一系列目标物体。 技术介绍 本项目使用的是基于python的pytorch神经网络框架&#xff0c;使用的神经网络是基于Resnet-50的…

非空断言操作符(!)

非空断言操作符&#xff08;!&#xff09;是 TypeScript 中的一种语法&#xff0c;用于告诉编译器某个值在特定位置不会是 null 或 undefined&#xff0c;即使编译器无法静态地证明这一点。它可以帮助消除编译器警告&#xff0c;但需要谨慎使用&#xff0c;以避免潜在的运行时错…

【微信小程序_7_WXML 模板语法 - 按钮事件和输入框事件绑定】

摘要:本文主要介绍了小程序中 WXML 模板语法的事件绑定相关知识。首先阐述了事件是渲染层到逻辑层的通讯方式,包括交互事件的过程。接着介绍了小程序中常用的事件,如 tap、input 和 change 及其绑定方式和事件描述。详细说明了事件对象的属性列表,包括 type、timeStamp、ta…