【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,一经查实,立即删除!

相关文章

HTML的介绍

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

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

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

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

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

【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…

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的…

[mysql]多表查询详解

我们如果要查询,我们就要用 SELECT .... FROM .... WHERE AND/OR/NOT #我们需要用过滤的条件来对数据进行筛选,不然会有很多多余数据 ORDER BY (ASC/DESC)#排序 LIMIT....,#是在几个有限的数据库管理系统里所以,PGsql,mysql,等 多表查询的意义 我们目前为止的查询语句…

Docker理念

1.为什么会出现Docker Docker 的出现并非偶然&#xff0c;而是由一系列技术发展趋势和实际需求所推动的一项技术创新。 随着软件行业的快速发展&#xff0c;开发团队的规模不断扩大&#xff0c;成员可能分布在不同的地理位置&#xff0c;使用不同的操作系统和开发工具。这就导致…

AI预测体彩排3采取888=3策略+和值012路或胆码测试10月11日升级新模型预测第101弹

经过100多期的测试&#xff0c;当然有很多彩友也一直在观察我每天发的预测结果&#xff0c;得到了一个非常有价值的信息&#xff0c;那就是9码定位的命中率非常高&#xff0c;已到达90%的命中率&#xff0c;这给喜欢打私菜的朋友提供了极高价值的预测结果~当然了&#xff0c;大…

AI核身-金融场景凭证篡改检测Baseline实践

金融领域交互式自证业务中涵盖信用成长、用户开户、商家入驻、职业认证、商户解限等多种应用场景&#xff0c;通常都需要用户提交一定的材料&#xff08;即凭证&#xff09;用于证明资产收入信息、身份信息、所有权信息、交易信息、资质信息等&#xff0c;而凭证的真实性一直是…

selenium自动化测试之Junit

1. 常用的注解 将junit的索引添加到pom文件&#xff1a; <!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api --><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId&…

基于Java实现(APP)智能停车场管理系统

移动应用开发系统设计说明书&#xff08;智能停车场管理系统&#xff09; 服务集成流程详细设计 实现功能 序号功能点1新增用户2注册用户3修改场地信息4列出场地信息5新增认证车辆6列出认证车辆7删除认证车辆8车辆进入信息录入9停车记录列表展示10出停车场信息录入 参数说明…

YOLOv8实战PCB电路板缺陷检测【数据集+YOLOv8模型+源码+PyQt5界面】

本文采用YOLOv8作为核心算法框架&#xff0c;结合PyQt5构建用户界面&#xff0c;使用Python3进行开发。YOLOv8以其高效的实时检测能力&#xff0c;在多个目标检测任务中展现出卓越性能。本研究针对PCB电路板缺陷数据集进行训练和优化&#xff0c;该数据集包含丰富的PCB电路板缺…

【计网】从零开始学习http协议 ---深入理解cookie和session

我的天空里没有太阳&#xff0c; 总是黑夜&#xff0c; 但并不暗&#xff0c; 因为有东西代替了太阳。 --- 东野圭吾 --- 从零开始学习http协议 1 理解cookie1.1 什么是cookie1.2 验证cookie1.3 cookie的属性 2 理解session2.1 什么是session2.2 验证session 1 理解cooki…