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

哈希及其封装实现unordermap和set

哈希

直接定址法

哈希和之前的红黑树的区别就是,它是通过映射关系来找到目标的,可以把它想象成之前排序的计数排序,那其实就是哈希的一种方法,叫做直接定址法。

对于比较集中的数据,它只需要开一段区间,然后通过映射关系把数据存到对应的位置上就可以了,但是它的缺点也很明显,如果数据很分散,那它的消耗就很大并且效率也很低。同时,对于非整型的数据它还多了一个转换的过程,否则也无法存入。

除留余数法

那么,为了应对这种情况,进化出了我依旧是开一段区间M,但是我把要存入的数据进行取模M,然后把取模后的结果存入对应位置,这种方法叫做除留余数法。这样也可以以较小的代价存入数据,但是新的问题又出现了,必然会有取模M后相等的值出现,这个就叫做哈希冲突,当然这并不是无法解决的,只需要往它后面第一个空着的位置存入即可,但是同样的,这么做也有可能会挤占别的数据的空间,并且往后走的过程也是需要消耗效率的,理想的情况是不出现,但是实际上一定会出现,我们只能减少出现的次数。

使用这种情况,空出的位置越多,浪费越多,空出的位置越少,冲突的概率越高,我们需要在这两者之间取得一个平衡,所以大佬们决定,如果存入的数据达到70%就进行扩容,这样勉强在两者之间取得了一定的平衡,这就叫做负载因子。 

而对于开的空间M也有说法,对于除,我们可以理解为异或,比如M = 2^16 本质上是取后16位,

但是这就会出现如果我前16位相同第17位才不同的情况,那妥妥的哈希冲突,所以大佬们又想出一个办法, 先(M<<17) -1 ,这样后16位都是1,然后再异或,可是这样只有后16位参与进来,所以再把左移前的M>>16位,这样使得32位都参与了运算,极大程度降低了冲突的概率。

当然上面这种还挺复杂的,所以产生了另一种另辟蹊径的方法,那就是取一个质数,这样虽然无法和上面相媲美,但是多少也降了点。

哈希实现(丐版)

假如我想存入这样一组值,那么我的M取个质数就取11。

那么上面这组值取模11之后必然会出现冲突,所以就按照之前我们所说的往后找空位。

存只要没满冲突就冲突嘛,无法效率低点,可是找就不一样了,如果取模后的结果不是我要找的,那么就说明我的位置被占了,或者根本没存,所以我需要往后找,直到找到空为止,那么另一个情况出现了,如果我删除了呢,人为出现了一个空进而导致找不到。所以我们还需要一个枚举类型来定义非空、空、删除这三个状态。这样就完美解决了遇到删除要不要继续找下去的问题,还需要一个n来记录数据个数。

enum isempty
{yes,no,del
};template<class M, class N>
struct Data //节点
{pair<M, N> _kv;isempty _isempty = yes;
};
template<class M, class N>
class aaa
{
public:aaa():_tables(11),_n(0){}bool insert(const pair<M,N>& kv){if (find(kv.first)){//不允许重复值出现的版本return false;}//超过70%就扩容if (_n * 10 / _tables.size() >= 7){aaa<M, N> newht;newht._tables.resize(_tables.size() * 2);//开二倍,//这样原有数据的映射位置不会被改变for (auto& data : _tables){if (data._isempty == no){newht.insert(data._kv);}}//最后交换就大功告成了_table.swap(newht._table);}size_t hash0 = kv.first % _tables.size();size_t hashi = hash0;size_t i = 1;while(_tables[hashi]._isempty == no ){hashi = (hash0 + i) % _table.size();//遇到边界可以回绕回去i++;}_tables[hashi]._kv = kv;_tables[hashi]._isempty == no;_n++;return true;}Data<M, N>* find(const M& key){size_t hash0 = key % _tables.size();size_t hashi = hash0;size_t i = 1;while (_tables[hashi]._isempty != yes){//不为空就继续往后找if (_tables[hashi].kv.first == key){//找到了就返回return &_tables[hashi];}hashi = (hash0 + i) % _table.size();i++;}//不然就是没找到 返回空return nullptr;}bool erase(const M& key){Data<M, N>* ret = find(key);if (ret){//我们不用真的去删除,只需要改一下它的状态就好ret->_isempty = del;return true;}else{//不然就是没找到return false;}}
private:vector<Data<M, N>> _tables;size_t _n = 0;//数据个数
};

是的,丐版的哈希就完成了,就这样。但哈希的实现会因为你使用的方法不同,在实现上也会有所不同,所以接下来我们就在丐版的基础上增加一点东西。

加强部分

利用素数表扩容

比如说在开辟的空间上,大佬们创建了一个素数表,这样可以最大限度的避免冲突。

inline unsigned long __stl_next_prime(unsigned long n){static const int __stl_num_primes = 28;static const unsigned long __stl_prime_list[__stl_num_primes] ={53,97,193,389,769,1543,3079,6151,12289,24593,49157,98317,196613,393241,786433,1572869,3145739,6291469,12582917,25165843,50331653,100663319,201326611,402653189,805306457,1610612741,3221225473,4294967291};const unsigned long* first = __stl_prime_list;const unsigned long* last = __stl_prime_list + __stl_num_primes;const unsigned long* pos = lower_bound(first, last, n);return pos == last ? *(last - 1) : *pos;}

这样我们哈希表的大小就在这么一组数里取,除了最后一个数,其他的树基本上也是靠近二倍的增长,因为最后一个还二倍就溢出了,所以对于最后一个数如果lower_bound取到值等于last,就给

个last-1的值。

取模加强

然后我们就可以对数据取模的部分进行改进,之前  数据%表大小  的方法太原始了,所以我们专门写一个函数来进化它。

size_t HashiFunc(const K& key){size_t hashi = key & (_table.size() - 1);hashi ^= (key >> (32 - _m));//m=16return hashi; }//更新后的扩容
if (_n * 10 / _table.size() >= 7){HashiTable<K, V,Hash> newht;++_m;newht._table.resize(pow(2, _m));for (auto& data : _table){if (data._isempty == no){newht.insert(data._kv);}}_table.swap(newht._table);}

这么改完之后虽然我们的冲突会因为和所有的位取模而降低冲突率,但是大小也上来了。

对非整数类型的数据进行转换

这一步我们没法直接改,因为本身它的数据就是不确定的,所以我们增加一个模板参数,写一个仿函数,默认就用我们的HashiFunc,如果使用者的类型不对,那么由他自己设计仿函数传入。

//比如我们变成string类型
//那么外部就自己写一个仿函数传入
struct stringhashi
{size_t operator()(const string& s){size_t hashi = 0;for (auto ch : s){hashi += ch; }return hashi;}
};

链地址法

直接定址法什么都好,就是对于离散数据消耗太高,于是大佬进化了一下,它还是开一片空间,但是这次它每个节点变成了其他结构,可以是链表,数组甚至红黑树,这样避免了相同值的消耗,我们只要头插即可。

	//节点template<class T>struct HashiNode{T _data;HashiNode<T>* _next;HashiNode(const T& data):_data(data), _next(nullptr){}};

那么对于哈希表来说,主体是不变的,并且相比于丐版,我们还要把加强的部分加上,让它进入全盛状态。

迭代器

	template<class K,class T,class Ref,class Ptr, class KorT,class Hash>struct HashIterator{typedef HashiNode<T> Node;typedef HashiTable<K, T, KorT, Hash> HT;typedef HashIterator<K, T, Ref, Ptr, KorT, Hash> Self;Node* _node;const HT* _ht;//我们不希望可以更改数据而打乱我们的映射 所以constHashIterator(Node* node, const HT* ht):_node(node),_ht(ht){}Ref operator*(){return _node->_data;}Ptr operator&(){return &_node->_data;}bool operator!=(const Self& s){return _node != s._node;}//由于是编译器里实现的是单向迭代器 所以我们有样学样也实现单向迭代器 只往后走Self& operator++(){if (_node->_next)//如果下一个不为空就往后走一步{_node = _node->_next;}else{KorT kt;//由于我们不知道传的是pair还是别的类型 所以干脆给个模版类型来定义Hash hash;//在++之前我们得先找到它在表里映射的位置size_t hashi = hash(kt(_node->_data)) & _ht->_table.size();++hashi;//因为并不是每个位置都一定有值 while (hashi < _ht.table.size()){    //所以每次先把位置的值给_node 如果是空也无所谓//如果不是空 就说明找到了 break就好 不然就++ 继续往后走 直到不为空_node = _ht->_table[hashi];if (_node){break;}else{++hashi;}}//如果++到了size的位置就说明走完了 所以用end()来标识_nodeif (hashi == _ht->_table.size()){_node = nullptr;}}return *this;}};

哈希表主体部分

插入

	//为了配合迭代器 所以返回类型更改为pair
pair<Iterator,bool> insert(const T& data){KorT kt;//利用我们的迭代器先找到数据的映射位置 Iterator it = find(kt(data));//如果能找到 说明已经存在 所以返回那个位置的迭代器就好 if (it != End()){return { it,false };}//Hash hash;//和前面的除留余数法不一样的是 这里只要不满就可以不扩容 尤其是我们还是链地址法if (_n == _table.size()){vector<Node*> newtable(__stl_next_prime(_table.size()) + 1);for (int i = 0; i < _table.size(); i++){//因为扩容的关系 除数改变也会改变取模结果 所以我们还得一个个重新算 而不能直接改Node* cur = _table[i];while (cur){//所以再来一个循环 把数据重新计算然后再头插到新表Node* next = cur->_next;size_t hashi = hash(kt(cur->_data)) % newtable.size();cur->_next = newtable[hashi];newtable[hashi] = cur;cur = next;}_table[i] = nullptr;}_table.swap(newtable);}//如果不考虑上面的扩容,这就是一个链表的头插 就多了一个先找映射位置的过程//先判断是pair还是普通类型 然后再用仿函数转换一下以防不是整形 然后再取到映射位置size_t hashi = hash(kt(data)) % _table.size();Node* newnode = new node(data);newnode->_next = _table[hashi];_table[hashi] = newnode;++_n;return { Iterator(newnode,this),true };}

查找

		Iterator find(const K& key){Hash hash;//找到映射位置size_t hashi = hash(key) % _table.size();//遍历Node* cur = _table[hashi];while (cur){if (kt(cur->_data) == key){return Iterator(cur,this);}cur = cur->_next;}//如果没有找到就返回空return End();}

相比起插入,查找简直不要太简单。

删除

这里虽然也不复杂,但是需要分情况删除,因为我们的节点结构是链表,所以删除的如果是头节点,我们需要先记录它的下一个位置,而如果不是头结点,那么我们还需要记录它的前一个节点。

 

bool erase(const K& key){size_t hashi = key % _table.size();//头结点的前一个一定是空Node* cur = _table[hashi];Node* prev = nullptr;//然后开始分情况遍历while (cur){//如果就是删头结点 那就简单了 直接链接即可if (kt(cur->_data) == key){if (prev == nullptr){_table[hashi] = cur->_next;}//不然就是前一个和后一个链接else{prev->_next = cur->_next;}//然后删除cur即可delete cur;return true;}//否则就往后走 然后继续遍历else{prev = cur;cur = cur->_next;}}//走到这里就代表删除失败return false;}

 

封装

UnorderSet

namespace cxk
{//由于我们的哈希桶实现的很通用 所以我们把该给的参数设置好就可以直接使用了template<class K,class Hash = HashiFun<K>>class UnderedSet{//仿函数 确定我们是什么类型的数据struct SetMorS{const K& operator()(const K& key){return key;}};public://迭代器部分的参数设置的和链表一样 不过不论是不是const迭代器 我们的数据都不允许更改 所以都加上consttypedef typename hashi_bucket::HashiTable<K, const K, SetMorS,Hash>::Iterator iterator;typedef typename hashi_bucket::HashiTable<K, const K, SetMorS,Hash>::Const_Iterator const_iterator;//复用即可iterator begin(){return _ht.Begin();}iterator end(){return _ht.End();}const_iterator begin() const{return _ht.Begin();}const_iterator end() const{return _ht.End();}pair<iterator, bool> insert(const K& key){return _ht.insert(key);}iterator find(const K& key){return _ht.find(key);}bool erase(const K& key){return _ht.erase(key);}private:hashi_bucket::HashiTable<K, const K, SetMorS,Hash> _ht;};
}

UnorderMap

namespace wyf
{template<class K,class V,class Hash = HashiFun<K>>class UnderedMap{//和set不一样的地方就是这里的数据类型是pair 所以传入的只有firststruct MapMorS{const K& operator()(const pair<K, V>& kv){return kv.first;}};public://同样的迭代器和const迭代器typedef typename hashi_bucket::HashiTable<K, pair<const K, V>, MapMorS,Hash>::Iterator iterator;typedef typename hashi_bucket::HashiTable<K, pair<const K, V>, MapMorS,Hash>::Const_Iterator const_iterator;//复用iterator begin(){return _ht.Begin();}iterator end() {return _ht.End();}const_iterator begin() const{return _ht.Begin();}const_iterator end() const{return _ht.End();}V& operator[](const K& key){pair<iterator, bool> ret = insert({ key,V() });return ret.first->second;}pair<iterator, bool> insert(const pair<K, V>& kv){return _ht.insert(kv);}iterator find(const K& key){return _ht.find(key);}bool erase(const K& key){return _ht.erase(key);}private:hashi_bucket::HashiTable<K, pair<const K, V>, MapMorS<K>,Hash> _ht;};
}

在我们对哈希的使用进行升级之后,大多数的操作只需要把我们设计好的参数准备好就可以直接复用,从而达成封装,所以封装其实并不困难,难的点在于对哈希升级的同时兼顾到封装的逻辑。

相关文章:

哈希及其封装实现unordermap和set

哈希 直接定址法 哈希和之前的红黑树的区别就是&#xff0c;它是通过映射关系来找到目标的&#xff0c;可以把它想象成之前排序的计数排序&#xff0c;那其实就是哈希的一种方法&#xff0c;叫做直接定址法。 对于比较集中的数据&#xff0c;它只需要开一段区间&#xff0c;…...

在 AMD GPU 上构建解码器 Transformer 模型

Building a decoder transformer model on AMD GPU(s) — ROCm Blogs 2024年3月12日 作者 Phillip Dang. 在这篇博客中&#xff0c;我们展示了如何使用 PyTorch 2.0 和 ROCm 在单个节点上的单个和多个 AMD GPU 上运行Andrej Karpathy’s beautiful PyTorch re-implementation …...

Canvas简历编辑器-选中绘制与拖拽多选交互设计

Canvas简历编辑器-选中绘制与拖拽多选交互设计 在之前我们聊了聊如何基于Canvas与基本事件组合实现了轻量级DOM&#xff0c;并且在此基础上实现了如何进行管理事件以及多层级渲染的能力设计。那么此时我们就依然在轻量级DOM的基础上&#xff0c;关注于实现选中绘制与拖拽多选交…...

简单工厂(Simple Factory)

简单工厂&#xff08;Simple Factory&#xff09; 在创建一个对象时不向客户暴露内部细节&#xff0c;并提供一个创建对象的通用接口。 说明&#xff1a; 简单工厂把实例化的操作单独放到一个类中&#xff0c;这个类就成为简单工厂类&#xff0c;让简单工厂类来决定应该用哪…...

ffmpeg拉流分段存储到文件-笔记

通过ffmpeg可以从rtsp网络流拉取数据并存储到本地文件里&#xff0c;如下命令。做个笔记 ffmpeg -rtsp_transport tcp -i rtsp://192.168.1.168:6880/live -c copy -f segment -segment_time 60 stream_piece_%d.mp4这条 ffmpeg 命令的作用是从一个 RTSP 流中捕获视频&#xff…...

Java 实习工资大概是多少?——解读影响薪资的因素

文章目录 1. 城市因素&#xff1a;一线、二线的差距2. 公司类型&#xff1a;互联网公司、外企和传统企业的差别3. 个人能力&#xff1a;经验、技术栈的重要性4. 其他影响因素&#xff1a;学历和实习时间总结推荐阅读文章 Java 开发作为广泛应用的职业方向&#xff0c;实习工资的…...

【Linux】万字详解:Linux文件系统与软硬链接

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;Linux 目录 &#x1f680; 前言 一&#xff1a; &#x1f525; 磁盘的物理结构二&#xff1a; &#x1f525; 磁盘的存储结构 三&#xff1a; &#x1f525; 磁盘的逻辑结构 四&#xff1a; &#…...

spacenavd

介绍spacenavd开源项目&#xff0c;主要是因为在斯坦福大学的UMI项目中使用了该项目。在斯坦福大学的 UMI&#xff08;Universal Manipulation Interface&#xff09;项目中&#xff0c;Spacenavd 主要用于处理 3D Space Mouse&#xff08;空间鼠标&#xff09;的输入&#xf…...

C#WPF的XAML的语法详谈和特性

WPF的XAML&#xff08;eXtensible Application Markup Language&#xff09;是一种基于XML的标记语言&#xff0c;用于在.NET框架中定义和描述用户界面。XAML提供了一种声明性的方式来构建应用程序的UI元素&#xff0c;包括窗口、控件、布局、样式、动画和数据绑定等。 XAML的…...

一篇文章讲透数据结构之二叉搜索树

前言 在前面的学习过程中&#xff0c;我们已经学习了二叉树的相关知识。在这里我们再使用C来实现一些比较难的数据结构。 这篇文章用来实现二叉搜索树。 一.二叉搜索树 1.1二叉搜索树的定义 二叉搜索树&#xff08;Binary Search Tree&#xff09;是基于二叉树的一种升级版…...

新手入门c++(8)

到时候了&#xff0c;是时候给你们讲一下其他的定义形式与格式化输入输出了。 1.长整型变量 长整型变量分为两种&#xff1a; ①long类型 在计算机编程中&#xff0c;long 类型是一个整型数据类型&#xff0c;用于存储较大的整数。它的大小和范围取决于操作系统和编译器的实…...

新手铲屎官提问,有哪几款噪音低的宠物空气净化器推荐

相信很多铲屎官都明白的的痛就是猫咪掉毛太严重&#xff0c;所以每次看到满天飞的浮毛时只想赶紧逃离&#xff0c;一点都不想清理。但是家是自己的&#xff0c;猫是自己的&#xff0c;健康也是自己的&#xff0c;不清理也得清理。 为了更有效的清理浮毛&#xff0c;我朋友特意…...

解决RabbitMQ脑裂问题

文章目录 前言一、现象二、解决办法 前言 RabbitMQ脑裂 一、现象 RabbitMQ镜像群出现脑裂现象&#xff0c;各个节点的MQ实例都“各自为政”&#xff0c;数据并不同步。 二、解决办法 # 停止mq sh rabbitmq-server stop_app # 查看mq进程是否存在 ps -ef | grep rabbitmq # …...

经纬恒润AUTOSAR成功适配芯钛科技Alioth TTA8车规级芯片

在汽车电子领域&#xff0c;功能安全扮演着守护者的角色&#xff0c;它确保了车辆在复杂多变的情况下保持稳定可靠的运行。随着汽车电子的复杂性增加&#xff0c;市场对产品功能安全的要求也日益提高。基于此背景&#xff0c;经纬恒润AUTOSAR基础软件产品INTEWORK-EAS-CP成功适…...

4、java random随机数、一维数组、二维数组

目录 Random类与随机数生成数组的概述与使用数组的内存分配与访问数组的常见问题与解决方案一维数组的遍历与操作二维数组的概述与遍历1. Random类与随机数生成 引言 在编程中,我们经常需要生成随机数,比如在游戏、模拟实验或者数据处理中。Java提供了一个非常方便的类Rand…...

C++ 魔法三钥:解锁高效编程的封装、继承与多态

快来参与讨论&#x1f4ac;&#xff0c;点赞&#x1f44d;、收藏⭐、分享&#x1f4e4;&#xff0c;共创活力社区。 目录 &#x1f4af;前言 &#x1f4af;封装 1.封装概念 2.封装格式 3.封装的原理 4.封装的作用 &#x1f4af;继承 1.继承的概念 2.继承格式 3.继承的…...

姿态传感器(学习笔记上)

上节我们学的是温湿传感器&#xff0c;这节我们学的是姿态传感器&#xff0c;虽然都是传感器&#xff0c;但是它们还是有很大的区别的&#xff0c;这节的传感器我们通过学习可知&#xff0c;开发板上的姿态传感器型号是QMI8658C&#xff0c;内部集成3轴加速度传感器和3轴陀螺仪…...

labelimg使用教程

快捷键 W&#xff1a;调出标注的十字架&#xff0c;开始标注 A&#xff1a;切换到上一张图片 D&#xff1a;切换到下一张图片 del&#xff1a;删除标注的矩形框 CtrlS&#xff1a;保存标注好的标签 Ctrl鼠标滚轮&#xff1a;按住Ctrl&#xff0c;然后滚动鼠标滚轮&#xff0c;…...

力扣21 : 合并两个有序链表

链表style 描述&#xff1a; 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例&#xff1a; 节点大小相同时&#xff0c;l1的节点在前 何解&#xff1f; 1&#xff0c;遍历两个链表&#xff0c;挨个比较节点大小 同时遍…...

【Spring】Spring Boot 配置文件(7)

本系列共涉及4个框架&#xff1a;Sping,SpringBoot,Spring MVC,Mybatis。 博客涉及框架的重要知识点&#xff0c;根据序号学习即可。 有什么不懂的都可以问我&#xff0c;看到消息会回复的&#xff0c;可能会不及时&#xff0c;请见谅&#xff01;&#xff01; 1、配置文件作…...

《向量数据库指南》——解锁Wikipedia文章向量的跨语言搜索秘籍

嘿,各位向量数据库和AI应用的小伙伴们,我是你们的老朋友王帅旭,大禹智库的向量数据库高级研究员,也是《向量数据库指南》的作者。今天,咱们来聊聊一个超棒的数据集——百万条 Wikipedia 文章向量,这可是我在研究过程中发现的一个宝藏啊! 首先,咱们得说说这个数据集的来…...

【力扣 + 牛客 | SQL题 | 每日5题】牛客SQL热题204,201,215

1. 力扣1126&#xff1a;查询活跃业务 1.1 题目&#xff1a; 事件表&#xff1a;Events ------------------------ | Column Name | Type | ------------------------ | business_id | int | | event_type | varchar | | occurrences | int | --------…...

下载数据集用于图像分类并自动分为训练集和测试集方法

一、背景 最近需要用Vision Transformer&#xff08;ViT&#xff09;完成图像分类任务&#xff0c;因此查到了WZMIAOMIAO的GitHub&#xff0c;里面有各种图像处理的方法。而图像处理的前期工作就是获取大量的数据集&#xff0c;用于训练模型参数&#xff0c;以准确识别或分类我…...

Python xlrd库介绍

一、简介 xlrd是一个用于读取Excel文件(.xls和.xlsx格式)的Python库。它提供了一系列函数来访问Excel文件中的数据&#xff0c;如读取工作表、单元格的值等。 二、安装 可以使用以下命令安装xlrd库&#xff1a; pip install xlrd 三、使用方法 1. 导入库&#xff1a; 示例…...

Javascript立即执行函数

//立即执行函数 把函数的声明看作一个整体声明结束就立即调用 // (function(){console.log(hello) // })(); console.log((function (){ return 0; })()); // let afunction(){ console.log(hello) }; console.log(typeof a);//function,数组&#xff1a;objeck...

Linux相关概念和易错知识点(17)(文件、文件的系统调用接口、C语言标准流)

目录 1.文件 &#xff08;1&#xff09;文件组成和访问 &#xff08;2&#xff09;文件的管理 &#xff08;3&#xff09;C语言标准流 &#xff08;4&#xff09;struct file ①文件操作表 ②文件内核缓冲区 &#xff08;5&#xff09;Linux下一切皆文件 &#xff08;…...

三防加固工业平板国产化的现状与展望

在当今全球科技竞争日益激烈的背景下&#xff0c;工业4.0和智能制造的浪潮推动了工业自动化设备的迅速发展&#xff0c;其中&#xff0c;三防加固工业平板电脑作为连接物理世界与数字世界的桥梁&#xff0c;其重要性不言而喻。所谓“三防”&#xff0c;即防水、防尘、防震&…...

3.1.3 看对于“肮脏”页面的处理

3.1.3 看对于“肮脏”页面的处理 文章目录 3.1.3 看对于“肮脏”页面的处理再看对于“肮脏”页面的处理MmPageOutVirtualMemory() 再看对于“肮脏”页面的处理 MmPageOutVirtualMemory() NTSTATUS NTAPI MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace,PMEMORY_AREA Me…...

学 Python 还是学 Java?——来自程序员的世纪困惑!

文章目录 1. Python&#xff1a;我就是简单&#xff0c;so what&#xff1f;2. Java&#xff1a;严谨到让你头疼&#xff0c;但大佬都在用&#xff01;3. 到底谁更香&#xff1f;——关于学哪门语言的百思不得姐结论——到底该选谁&#xff1f;推荐阅读文章 每个程序员都可能面…...

Spring Web MVC 入门

1. 什么是 Spring Web MVC Spring Web MVC 是基于 Servlet API 构建的原始 Web 框架&#xff0c;从从⼀开始就包含在Spring框架中。它的 正式名称“SpringWebMVC”来⾃其源模块的名称(Spring-webmvc)&#xff0c;但它通常被称为"Spring MVC". 什么是Servlet呢? Ser…...

设计公司网站页面设计/一网信息一个简单便捷的新闻网站

【回复“1024”&#xff0c;送你一个特别推送】1024 程序员节&#xff0c;就俩字&#xff1a;送书&#xff01;没想到 1024 竟然成为了中国程序员的共同的并且是固定的节日。你不信去百度搜索一下&#xff0c;它会这样告诉你&#xff1a;这阵风从 2015 年刮起&#xff0c;把每年…...

武汉做网站哪个好/seo优化一般包括哪些

inv[i](M-M/i)*inv[M%i]%M 转载于:https://www.cnblogs.com/autsky-jadek/p/7769055.html...

罗湖中心区做网站/网站建设报价单模板

下面是自己封装的&#xff0c;存在一定问题&#xff0c;node接触不久&#xff0c;promise的用法尚未理解&#xff0c;我想实现的是执行多条sql后&#xff0c;如果sql均正常执行&#xff0c;则返回一个定义的对象&#xff0c;如果某一sql出问题&#xff0c;直接rollback&#xf…...

网站空间备份/成都网站seo推广

转自&#xff1a;http://blog.csdn.net/zy_zhengyang/article/details/45009431 代码文件主要针对Matlab进行说明,但个人仍觉得讲解的支持向量机内容非常棒,可以做为理解这一统计方法的辅助资料; LibSVM是台湾林智仁(Chih-Jen Lin)教授2001年开发的一套支持向量机的库&#xff…...

做外贸自己开公司网站/网站建设公司推荐

https://blog.csdn.net/yinruiyang94/article/details/78354257xavier_initializer( uniformTrue, seedNone, dtypetf.float32)12345该函数返回一个用于初始化权重的初始化程序 “Xavier” 。 这个初始化器是用来保持每一层的梯度大小都差不多相同。 参数&#xff1a; uniform:…...

网站悬浮窗代码/楚雄seo

现在很多小伙伴们都会用WordPress来发送html邮件&#xff0c;但是对于一些新手朋友们来说&#xff0c;会不知道在WordPress中如何发送HTML邮件&#xff0c;接下来我们就和西部数码小编一起去看看WordPress中发送HTML邮件的方法。方法一&#xff0c;用filter发送HTML邮件发邮件用…...