认识哈希表
作者:~小明学编程
文章专栏:Java数据结构
格言:目之所及皆为回忆,心之所想皆为过往
目录
为什么我们需要哈希表?
哈希表的原理
什么是哈希值
冲突
负载因子
解决冲突
闭散列
开散列/哈希桶
代码实现
不考虑泛型
put操作
get操作
整体代码
考虑泛型
hashCode和equals为何要同时重写
代码:
为什么我们需要哈希表?
前面我们已经讲了很多的数据结构了,例如顺序表,链表,二叉树等等,这些数据结构的增删查改的时间复杂度有的是增为O(1),但删就为O(n),有的虽然增为O(n),但是删为O(1),但是我们的哈希表很牛,增删的时间复杂度都是O(1),就问你牛杯不?下面我们就来详细的说说这是怎么实现的。
哈希表的原理
之所以我们的时间复杂度能达到O(1)是因为我们没有比较,直接将我们的元素插入到哈希表中,我们想插入的元素都会有一个哈希值,这个哈希值我们可以看作是一个地址,这样我们就相当于通过这个地址直接插入元素,当我们想要取出这个元素的时候也可以通过我们的哈希值直接找到我们的元素。
什么是哈希值
我们先来看一下这幅图
上面是我们的数组,下面是我们想要放进去的数字,可以看到我们数组的长度是7,这时候我们的哈希值就可以是我们的key%capacity,也就是拿我们的当前的值余上我们的数组长度,这样我们放的时候就不会出现数组越界的情况了,有点像我们的桶排序。
我们可以看到前面放元素的过程就是这样,现在我们想要把8也放进去然后就会发现问题,我们8所计算出来的哈希值也是2。
冲突
这时我们就发现我们想要放进去的8与我们哈希表里面的1冲突了,这种冲突不可避免,首先我们想到的就是去降低我们冲突发生的频率,想要降低冲突频率当然就是扩大我们的哈希表,也就是扩大我们的数组。
负载因子
所谓的负载因子就是我们哈希表底层的数组,已经放进去的元素/数组的长度,负载因子与我们冲突的关系如下:
一般情况下我们的负载因子设定为0.75也就是当我们的底层数组被放了七八成的时候我们就要开始对数组进行扩容了。
这个时候也许会有疑问,我们的负载因子为什么不设置为1或者0.5呢?
这是因为当我们的负载因子设置为1的时候我们肯定已经产生大量的冲突了,这是我们所不想看到的,我们想要的是较低的冲突,那么既然我们想要较低的冲突我们为什么不将其设置为0.5呢?通过上面的图我们可以看到,但负载因子是0.5的时候我们的冲突率是很低的,确实冲突率是降低了,但是我们的数组才用了一半就要进行数组的扩容这样太浪费空间了,所以我们取中设0.75为我们的负载因子。
解决冲突
解决哈希冲突两种常见的方法是:闭散列和开散列。
闭散列
闭散列:也叫开放定址法,当我们发生冲突的时候我们的数组我们可以将发生冲突的元素放到数组中的其它空闲的位置。
对于如何去找下一个空闲的位置我们常见的有两种方法:
线性探测法:就是向当前冲突的位置一直向后找直到找到空闲的位置,但是这样做的缺点就是会导致我们冲突的元素都聚集到一起了。
二次探测:二次探测的出现就是解决我们线性探测法的问题的,其目的就是避免聚集,所以我们找空位置的方式就不再是挨着去找了,而是用一个公式找出我们的位置H(i) =( H0+i^2)%m,其中:i = 1,2,3…, 是通过散列函数Hash(x)对元素的关键码 key 进行计算得到的位置,m是表的大小。
开散列/哈希桶
开散列法又叫链地址法(开链法):我们将哈希表的底层数组中的每个元素都设置为一个链表,当我们产生冲突的时候就向我们的链表中插入一个新的节点,如下图:
思路很简单,接下来我们就用代码来实现一下。
代码实现
不考虑泛型
首先我们就是要设置我们的链表节点:
static class Node {public int key;public int val;public Node next;public Node(int key, int val) {this.key = key;this.val = val;}}
我们将其定义为一个静态的内部类,里面包含我们的key值,数据域val,还有我们的下一个节点的地址next。
Node[] array;//哈希表public int userSize = 0;//我们哈希表里面的元素个数public static final double DEFAULT_LOAD_FACTOR = 0.75;//负载因子public HashBuck() {this.array = new Node[10];}
接下来就是设定我们的哈希表,设置为我们的节点类型的数组,元素个数和负载因子。
put操作
我们的put操作的功能就是向我们的哈希表中放元素,这里我们的key是整型的所以:
1.算出我们的hash值,new一个我们当前的节点。
2.通过hsah值找到我们元素在数组中的位置。
3.遍历当前链表的所有节点看看是否该key已存在,如果存在那就直接结束不用再插入了。
4.判断一下我们的负载是否超过负载因子,超过的话就需要扩容。
5.采用链表的头插法将当前节点插入哈希表中。
代码:
//放入元素的操作public void put(int key,int val) {int index = key% array.length;//找到我们对应的数组下标Node node = new Node(key, val);Node cur = array[index];//找到数组所对应链表的首地址//首先遍历一遍链表如果key相同的话,我们要更新key的值while (cur!=null) {if (cur.key == key) {cur.val = val;return;}cur = cur.next;}//考虑扩容问题,如果我们当前的负载因子达到了阈值,就开始扩容if (getDefaultLoadFactor()>DEFAULT_LOAD_FACTOR) {resize();}//将当前的节点连接到链表上去,采用头插法node.next = array[index];array[index] = node;this.userSize++;}//返回我们当前的负载因子private double getDefaultLoadFactor() {return 1.0*userSize/this.array.length;}//扩容操作private void resize() {//首先new一个新的数组Node[] newArray = new Node[2 * array.length];for (int i = 0; i < array.length; i++) {Node cur = array[i];while (cur!=null) {Node curNext = cur.next;//记录一下我们的下一个节点防止后面插入后丢失int index = cur.key % newArray.length;//记录当前的下标//一样还是采用头插法cur.next = newArray[index];newArray[index] = cur;cur = curNext;}}this.array = newArray;}
get操作
get操作就比较简单了,获取我们的hash值,然后找到数组下标,接着遍历链表找到我们的key.
代码:
//获取操作public int get(int key) {int index = key % array.length;Node cur = array[index];while (cur!=null) {if (cur.key==key) {return cur.val;}}return -1;}
整体代码
public class HashBuck {//哈希表中的节点static class Node {public int key;public int val;public Node next;public Node(int key, int val) {this.key = key;this.val = val;}}Node[] array;//哈希表public int userSize = 0;//我们哈希表里面的元素个数public static final double DEFAULT_LOAD_FACTOR = 0.75;//负载因子public HashBuck() {this.array = new Node[10];}//放入元素的操作public void put(int key,int val) {int index = key% array.length;//找到我们对应的数组下标Node node = new Node(key, val);Node cur = array[index];//找到数组所对应链表的首地址//首先遍历一遍链表如果key相同的话,我们要更新key的值while (cur!=null) {if (cur.key == key) {cur.val = val;return;}cur = cur.next;}//考虑扩容问题,如果我们当前的负载因子达到了阈值,就开始扩容if (getDefaultLoadFactor()>DEFAULT_LOAD_FACTOR) {resize();}//将当前的节点连接到链表上去,采用头插法node.next = array[index];array[index] = node;this.userSize++;}//返回我们当前的负载因子private double getDefaultLoadFactor() {return 1.0*userSize/this.array.length;}//扩容操作private void resize() {//首先new一个新的数组Node[] newArray = new Node[2 * array.length];for (int i = 0; i < array.length; i++) {Node cur = array[i];while (cur!=null) {Node curNext = cur.next;//记录一下我们的下一个节点防止后面插入后丢失int index = cur.key % newArray.length;//记录当前的下标//一样还是采用头插法cur.next = newArray[index];newArray[index] = cur;cur = curNext;}}this.array = newArray;}//获取操作public int get(int key) {int index = key % array.length;Node cur = array[index];while (cur!=null) {if (cur.key==key) {return cur.val;}}return -1;}}
考虑泛型
前面我们因为我们的key值是整型所以我们在计算哈希值的时候直接用key%数组长度,那么当我们的key不是整型而是其它的类型,例如是一个String类型或者,其它应用类型时候该怎么办呢?
这时候就要用到我们的hashCode方法,该方法就是根据我们的引用来生成一个hash值,例如我们有一个Person的类。
class Person {public int ID;public Person(int ID) {this.ID = ID;}
}
public static void main(String[] args) {Person person1 = new Person(340);Person person2 = new Person(340);Person person3 = person1;System.out.println(person1.hashCode());//460141958System.out.println(person2.hashCode());//1163157884System.out.println(person3.hashCode());//460141958}
这里我们调用hashCode的方法可以看到我们生成一个hash值,这样就解决了我们hsah值的问题了,那么问题又来了,我们new的这两个对象本质上是一样的,都是ID=340,但是其hash值却不一样,当我们想要其hash值一样的时候就需要重写其hashCode,但是在我们重写hashCode的过程中往往也要重写equals,这是为什么呢?
hashCode和equals为何要同时重写
这是因为我们的hashCode所生成的hash值在是根据对象的地址来生成就如同上述的代码,我们的person1和person2不相等(没有重写equals,此时判断是否相等比较的是地址)而person1和person3是相等的,所以我们person1和person3所生成的hash值都是一样的。
现在我们不需要根据地址来生成哈希值,因为这样没有太大的意义,我们要根据我们对象里面的成员来生成我们的hash值,比如我们的Person类,我们要根据我们的ID来生成我们想要的hash值,此时我们就要去重写hashCode了,重写完之后:
class Person {public int ID;public Person(int ID) {this.ID = ID;}@Overridepublic int hashCode() {return Objects.hash(ID);}
}
public static void main(String[] args) {Person person1 = new Person(340);Person person2 = new Person(340);Person person3 = person1;System.out.println(person1.hashCode());//371System.out.println(person2.hashCode());//371System.out.println(person3.hashCode());//371}
此时我们得到了我们想要的东西,hash都一样了,但是当我们向里面put元素和get元素的时候,我们就会发现问题:
我们会发现无论是put还是get我们都会有一个equals,比较当前对象是否一致才行,如果不重写还是默认比较地址,那么既然是比较地址就行了何必重写我们的hashCode呢,我们的hash值能让我们找到我们想要的元素在数组的哪一个下标,但是每个下标下面又是一个链表(或者红黑树)所以想要找到具体的元素还需要去比较,所以就得重写equals。
代码:
public class HashBuck2<K,V> {static class Node<K,V>{public K key;public V val;public Node<K,V> next;public Node(K key,V val){this.key = key;this.val = val;}}public Node<K,V>[] array = (Node<K,V>[])(new Node[10]);//哈希表public int userSize = 0;//我们哈希表里面的元素个数public static final double DEFAULT_LOAD_FACTOR = 0.75;//负载因子//放入元素的操作public void put(K key,V val) {int hash = key.hashCode();int index = hash% array.length;//找到我们对应的数组下标Node<K,V> node = new Node(key, val);Node<K,V> cur = array[index];//找到数组所对应链表的首地址//首先遍历一遍链表如果key相同的话,我们要更新key的值while (cur!=null) {if (cur.key.equals(key)) {cur.val = val;return;}cur = cur.next;}//考虑扩容问题,如果我们当前的负载因子达到了阈值,就开始扩容if (getDefaultLoadFactor()>DEFAULT_LOAD_FACTOR) {resize();}//将当前的节点连接到链表上去,采用头插法node.next = array[index];array[index] = node;this.userSize++;}//返回我们当前的负载因子private double getDefaultLoadFactor() {return 1.0*userSize/this.array.length;}//扩容操作private void resize() {//首先new一个新的数组Node<K,V>[] newArray = new Node[2 * array.length];for (int i = 0; i < array.length; i++) {Node<K,V> cur = array[i];while (cur!=null) {Node<K,V> curNext = cur.next;//记录一下我们的下一个节点防止后面插入后丢失int hash = cur.key.hashCode();int index = hash % newArray.length;//记录当前的下标//一样还是采用头插法cur.next = newArray[index];newArray[index] = cur;cur = curNext;}}this.array = newArray;}//获取操作public V get(K key) {int hash = key.hashCode();int index = hash % array.length;Node<K,V> cur = array[index];while (cur!=null) {if (cur.key.equals(key)) {return cur.val;}}return null;}}
相关文章:
测试数据不再难,人工智能批量生成给你用!
简介 测试数据是指一组专注于为测试服务的数据,既可以作为功能的输入去验证输出,也可以去触发各类异常场景。 测试数据的设计尤为重要,等价类、边界值、正交法等测试用例设计方法都是为了更全面的设计对应的测试数据集。 实践演练 在批量生成测试数据中,我们需要明确数据的…...
modbus怎么写多个保持寄存器
近期,在做项目的时候,用到了modbus协议,有一个校时功能,就是需要定时发送时间到相应的设备,给相应的设备校时,协议里给出了寄存器地址和数据格式,如下 这个在程序里就需要写多个连续的保持寄存器,报文格式如下: 串口modbus报文格式 11 10 13 27 00 04 08 18 04 1C 0F …...
03-JAVA设计模式-策略模式
策略模式 什么是策略模式 策略模式(Strategy Pattern)是行为设计模式之一,它使你能在运行时改变对象的行为。在策略模式中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为模式。 在策略模式中,…...
reactivity api
reactivity api: https://v3.vuejs.org/api/reactivity-api获取响应式数据API 传入 返回 备注reactive plain-object 对象代理 深度代理对象中的所有成员readonly plain-object or proxy 对象代理 只能读取代理对象中的成员,不可修改ref any { value: ... } 对value的访问是响…...
HarmonyOS 自定义装饰器
1. 引言 在软件工程中,日志记录是监控和调试应用程序的重要工具。鸿蒙操作系统(HarmonyOS)支持自定义装饰器,这使得开发者可以方便地向类的方法添加日志记录功能。本文将介绍两个用于记录方法执行的自定义装饰器:LogMethod 和 logDecorator。 2. 装饰器基础 装饰器是一种特…...
SystemVerilog -- 6.4 Interface ~ Clocking Block Part II
SystemVerilog Clocking Block Part II 时钟模块允许在指定的时钟事件对输入进行采样并驱动输出。如果提到时钟模块的输入skew,则该模块中的所有输入信号都将在时钟事件之前以skew时间单位进行采样。如果提到时钟模块的输出skew,则该模块中的输出信号都将在相应的时钟事件之后…...
认识哈希表
作者:~小明学编程 文章专栏:Java数据结构 格言:目之所及皆为回忆,心之所想皆为过往 目录 为什么我们需要哈希表? 哈希表的原理 什么是哈希值 冲突 负载因子 解决冲突 闭散列 开散列/哈希桶 代码实现 不考虑…...
Vue学习:Hello小案例
使用Vue的目的:构建用户界面(需要使用容器 摆放这个界面的内容) favicon.ico:1 GET http://127.0.0.1:5500/favicon.ico 404 (Not Found) 没有页签图标 在者服务器中 http://127.0.0.1:5500没有/favicon.ico 强制刷新网页:s…...
IDEA创建Java Web项目
✅作者简介:热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏:JAVA开发者…...
C++11中可变参数模板使用
在看同事编写的代码,发现有如下的代码,因为没用过,所以查了一下这是什么语法,通过查询资料知道了这是C11中增加的可变参数模板。 template<class T, class ...Args> bool GetValue(T &value, Args &&...args) c…...
MySQL 中的 sql_mode 选项以及配置
MySQL 中的 sql_mode 选项以及配置 目录MySQL 中的 sql_mode 选项以及配置一、查询与设置 sql_mode1、查询 sql_mode2、设置 sql_mode(1)通过命令设置(2)在配置文件中设置二、sql_mode 支持的模式1、ANSI 模式(宽松模式…...
【C语言航路】第六站:指针初阶
目录 一、指针是什么 二、指针和指针类型 1.指针类型的意义 2.指针-整数 3.指针解引用 三、野指针 1.野指针的成因 (1)指针未初始化 (2)指针越界访问 (3)指针指向的空间释放 2.如何规避野指针 &a…...
从 JPA 2.x 迁移到 3.0
我最近收到了很多关于JPA 3.0的问题,由于EclipseLink和Hibernate现在提供了对它的全面支持,现在是时候仔细看看规范的最新更新了。作为从Java EE到Jakarta EE转换的一部分,Java Persistence API(JPA)更名为Jakarta Per…...
Allegro如何锁定器件操作指导
Allegro如何锁定器件操作指导 Allegro上可以锁定器件,避免误操作被移动,具体操作如下 选择fix命令 Find选择Symbols 框选需要锁定的器件 可以看到器件被锁住了 除了这个方法之外,还有另外一种方法锁定器件,选择edit-property Find选择Symbols...
第三章:SpringBoot的配置文件-核心技术
目录 1、文件类型 1.1、properties 1.2、yaml 1.2.1、简介 1.2.2、基本语法 1.2.3、数据类型 1.2.4、示例 2、配置提示 1、文件类型 1.1、properties 同以前的properties用法 1.2、yaml 1.2.1、简介 YAML 是 "YAML Aint Markup Language"(YA…...
Vue中的计算属性
计算属性:实际上是把vm中的属性进行计算加工,最后能够返回给页面一个结果,它是实时的,所以不能做异步操作。 细想一下,其实methods方法也能实现1中描述的现象,但是计算属性最大的优势是缓存!&a…...
HTML+CSS个人电影网页设计——电影从你的全世界路过(4页)带音乐特效
HTML实例网页代码, 本实例适合于初学HTML的同学。该实例里面有设置了css的样式设置,有div的样式格局,这个实例比较全面,有助于同学的学习,本文将介绍如何通过从头开始设计个人网站并将其转换为代码的过程来实践设计。 文章目录一、网页介绍一…...
业务开发时,接口不能对外暴露的解决方案
1.内外网接口微服务隔离 将对外暴露的接口和对内暴露的接口分别放到两个微服务上,一个服务里所有的接口均对外暴露,另一个服务的接口只能内网服务间调用。 该方案需要额外编写一个只对内部暴露接口的微服务,将所有只能对内暴露的业务接口聚合到这个微服务里,通过这个聚合…...
「点燃我,温暖你」用Python制作一个动态爱心效果
最近「点燃我,温暖你」这部剧非常火,讲述的是程序员的爱情故事。 其中陈飞宇饰演的男主李峋,在剧中用程序做出的爱心跳动效果,非常炫。 网上各个大佬也是纷纷给出看法,综合就是不太可能用C语言来实现的。 大概率是AE…...
初识猿如意开发工具
嗨,大家好,我是异星球的小怪同志 一个想法有点乱七八糟的小怪 如果觉得对你有帮助,请支持一波。 希望未来可以一起学习交流。 一、初遇猿如意 第一次听说猿如意开发工具,于是抱着试试的心态,开始下载尝试。 首先是…...
PyTorch 2.0发布了,一行代码提速76%
PyTorch 官方:我们这次的新特性太好用了,所以就直接叫 2.0 了。 前段时间,PyTorch 团队在官方博客宣布 Pytorch 1.13 发布,包含 BetterTransformer 稳定版等多项更新。在体验新特性的同时,不少人也在期待下一个版本的推…...
栈的基本操作
一,自定义函数 #include<bits/stdc.h> using namespace std; const int N 1000;//N是常量 int s[N 1];//栈 int top;//栈顶的位置(栈内有多少个元素) //入栈 void push(int x){ //非满栈 if(top < N){ //将栈顶上移并存入 top…...
windows内核编程-文件操作
文章目录前言背景知识点介绍字符串内存分配与回收文件操作自旋锁win内核编程-日志实现文件操作的封装日志功能的实现简单的测试日志功能其他前言 本文完整代码见:demo/12-win-driver-log 我们必须先搞定,DebugView可以看到DbgPrintDbgPrint的输出。否则…...
Hadoop原理与技术——Linus命令行基本操作
点击链接查看文档 一、实验目的 Hadoop运行在Linux系统上,因此,需要学习实践一些常用的Linux命令。本实验旨在熟悉常用的Linux操作,为顺利开展后续其他实验奠定基础。 二、实验环境 Windows 10 VMware Workstation Pro虚拟机 Hadoop环境 J…...
目标检测算法——YOLOv5/YOLOv7改进之结合特征提取网络RFBNet(涨点明显)
>>>深度学习Tricks,第一时间送达<<< 🚀🚀🚀NEW!!!魔改YOLOv5/v7目标检测算法来啦 ~ 计算机视觉——致力于目标检测领域科研Tricks改进与推荐 | 主要包括Backbone、Neck、Head、普通注意力机制、自注意力机制Transformer、Swin Transformer v2,各…...
anaconda使用系列教程--4)环境迁移
概述 跨平台尽量避免,比如windows和linux就不要跨平台,就在linux之间跨还是可以的 直接copy整体环境文件,适合于无法联网或网速不佳的新环境 anaconda最好是同版本的 迁移方法 使用requirement文件 A机器: pip freeze > …...
Kotlin高仿微信-第57篇-VIP管理列表
Kotlin高仿微信-项目实践58篇详细讲解了各个功能点,包括:注册、登录、主页、单聊(文本、表情、语音、图片、小视频、视频通话、语音通话、红包、转账)、群聊、个人信息、朋友圈、支付服务、扫一扫、搜索好友、添加好友、开通VIP等众多功能。 Kotlin高仿…...
贪心算法-- 纪念品分组
问题描述元旦快到了,校学生会让乐乐负责新年晚会的纪念品发放工作。为使得参加晚会的同学所获得的纪念品价值 相对均衡,他要把购来的纪念品根据价格进行分组,但每组最多只能包括两件纪念品,并且每组纪念品的价格之和不能超过一个给…...
java-php-net-python-代驾网站计算机毕业设计程序
java-php-net-python-代驾网站计算机毕业设计程序 java-php-net-python-代驾网站计算机毕业设计程序本源码技术栈: 项目架构:B/S架构 开发语言:Java语言 开发软件:idea eclipse 前端技术:Layui、HTML、CSS、JS、JQ…...
简洁自增ID实现方案
简介 从数据库性能角度考虑,我们经常需要数字型的自增主键,有时候我们并不想用像MySQL自带的自增,因为从1开始很数据位数不一样,对有点强迫症的人来说,不是很友好。 另外,别人也容易根据这种从1开始的自增…...
JMeter入门教程(14)——场景设计
1.JMeter中场景设计是通过线程组来实现的 如图: 控制面板中各元素介绍: 名称:可以随意设置,最好有业务意义。 注释:可以随意设置,可以为空。 在取样器错误后要执行的动作:其中的某一个请求出错后…...
SVM 用于将数据分类为两分类或多分类(Matlab代码实现)
👨🎓个人主页:研学社的博客 💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜…...
转行软件测试我后悔了
很多时候,都在想当初做的转行软件测试行业的决定是对的吗?现在后悔还来得及吗? 记得在求职的时候,面试官经常问我:“为什么要选择软件测试工作?” 而我也会经常说一堆自己有的没的优势去应付。 工作这么久了&#x…...
k8s教程(15)-pod之亲和性与互斥性调度
文章目录01 引言02 pod亲和性调度与互斥性调度2.1 拓扑域2.2 举例2.2.1 参照目标pod2.2.2 pod的亲和性调度2.2.3 pod的互斥性调度03 其它04 文末01 引言 声明:本文为《Kubernetes权威指南:从Docker到Kubernetes实践全接触(第5版)》…...
浅谈降维实操,一种用于处理特征的方式——后附Python代码
👦👦一个帅气的boy,你可以叫我Love And Program 🖱 ⌨个人主页:Love And Program的个人主页 💖💖如果对你有帮助的话希望三连💨💨支持一下博主 降维实操前言线性降维低…...
深度学习中的正则化——L1、L2 和 Dropout
正则化是一组技术,可以防止神经网络中的过度拟合,从而在面对来自问题域的全新数据时提高深度学习模型的准确性。 在本文中,我们将介绍最流行的正则化技术,称为 L1、L2 和 dropout。 文章目录1. 回顾:过拟合2.什么是正则…...
数据结构(王卓)(4)附:链表的销毁与清空
销毁 Status 销毁单链表(LinkList L) {LinkList p;while (L){p L;L->next;delete p;}return OK; } 运行逻辑: (1):设定一个指针,让指针指向链表的头指针L (2):让头指针等于头指针里面指向下…...
C++图书管理系统(管理员-读者)
C图书管理系统(管理员-读者) 一、设计一款文字式交互的图书管理系统,要求具备注册登录、浏览图书、借还图书等基本功能; 二、要求以外部文件的形式存储书籍信息、馆藏记录、借阅记录、用户信息等。【可参考提供的书籍清单】 三…...
永磁同步电机恒压频比(V/F)开环控制系统Matlab/Simulink仿真分析及代码生成到工程实现
文章目录前言一、 恒压频比(V/F)控制原理二、永磁同步电机恒压频比开环控制系统Matlab/Simulink仿真分析2.1.仿真电路分析2.1.1.恒压频比控制算法2.1.2.输出处理2.1.3.主电路2.2.仿真结果分析2.2.1.设定目标转速为1200r/min2.2.1.设定目标转速为变化值三…...
基于JSP网上书城的设计与实现
项目描述 临近学期结束,还是毕业设计,你还在做java程序网络编程,期末作业,老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下,你想解决的问…...
java计算机毕业设计-学生宿舍故障报修管理信息系统-源程序+mysql+系统+lw文档+远程调试
java计算机毕业设计-学生宿舍故障报修管理信息系统-源程序mysql系统lw文档远程调试 java计算机毕业设计-学生宿舍故障报修管理信息系统-源程序mysql系统lw文档远程调试本源码技术栈: 项目架构:B/S架构 开发语言:Java语言 开发软件…...
vue学习笔记——简单入门总结(四)
文章目录1.Vue3的特性和变化1.1.创建vue3项目1.2.分析main.js变化:1.3.setup--组合式api的开端1.4.ref函数和reactive函数:1.5.watch监视属性1.5.watchEffect函数1.6.vue3生命周期:1.Vue3的特性和变化 1.1.创建vue3项目 1.这里我们使用脚手架…...
数据结构与算法—数组栈和链表栈
数据结构与算法—数组栈和链表栈 🌈一览众山小数据结构与算法—数组栈和链表栈栈介绍栈图解栈实现数组实现栈实现思路实现代码单链表实现栈实现思路(图解)实现代码栈总结栈力扣栈介绍 栈,存储货物或供旅客住宿的地方,可引申为仓库、中转站,所以引入到计算…...
【应用】Kubernetes
Kubernetesk8s 安装流程安装前配置安装 docker 以及 k8s 组件初始化 k8s 集群测试使用:安装 kubernetes-dashboardk8s 基础概念k8s 核心技术概念k8s 内部组件k8s 中的 IP 地址K8S 服务暴露的三种方式k8s 安装流程 k8s-masterk8s-node01k8s-node02192.168.86.140192…...
GEE:关系、条件和布尔运算
ee.Image对象具有一组用于构建决策表达式的关系、条件和布尔运算方法。这些方法可以用来掩膜、绘制分类地图和重新赋值。 本文记录了在GEE(Google Earth Engine)平台上的关系运算符和布尔运算符,分别应用到了三个不用的场景(筛选低…...
Java项目:SSM的KTV管理系统
作者主页:源码空间站2022 简介:Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 主要功能包括: 登陆页,房间信息,房间管理,开取房间,房间查询,会员管理,食物管理,查看订单,查询订单,查看房间消费使用情况等功能。…...
包装类-Wrapper
包装类的分类 针对八种基本数据类型相应的引用类型-包装类有了类的特点,就可以调用对应的类中的方法 装箱和拆箱 Java是一种面向对象的编程语言,学习Java时就被明确灌输了一个概念:OOP,即面向对象编程。一切皆对象。但是基本…...
计算机网络——运输层【重点】
运输层概述 概念 进程之间的通信 从通信和信息处理的角度看,运输层向它上面的应用层提供通信服务,它属于面向通信部分的最高层,同时也是用户功能中的最低层。当网络的边缘部分中的两个主机使用网络的核心部分的功能进行端到端的通信时&…...
ADSP-21569/ADSP-21593的开发入门(上)
作者的话 ADI的SHARC系列DSP,目前已经出到5系列了,最新的一颗叫2159x,按照ADI的说法,这颗DSP的性能是21569的两倍,但又能和21569做P2P的替换,所以下面我们就以21593为例,写一点资料,…...
【Android App】在线直播之搭建WebRTC的服务端(图文解释 简单易懂)
有问题或需要源码请点赞关注收藏后评论区留言私信~~~ 一、WebRTC的系统架构 WebRTC(网页即时通信)是一个支持浏览器之间实时音视频对话的新型技术,WebRTC体系由应用于实时通信的编程接口和一组通信协议组成,已成为互联网流媒体通…...
x265 帧间预测
帧间编码入口函数: 从 Analysis::compressCTU 是ctu编码的入口函数,根据 slice 类型判断是 I 还是 BP,如果是BP则执行帧间编码函数 Analysis::compressInterCU_rdx_x::/*压缩分析CTU过程:1.为当前CTU加载QP…...
【sciter】安全应用列表控件总结
一、效果图 二、功能点 实现电脑文件拖拽进入到安全桌面,读取文件路径,生成应用。可以配置允许拖拽进入安全桌面的文件应用。点击添加图标,可以添加应用到安全桌面中。在安全桌面列表中每一个应用实现双击、失去焦点,获取焦点、右键事件在安全桌面列表中每一个应用可以实现…...
一篇文章让你搞懂Java顺序表
目录 一、 线性表的基本介绍 二、顺序表 1、顺序表的概念 2. 创建顺序表类(ArrayList) 2. 增加元素 3. 删除元素 4. 修改某个元素 5. 查找元素 Main类 在数据结构体系中我们将整个数据结构分为两类,一类是线性结构; 线性…...
小白必知必会的几个IP协议知识
小白必知必会的几个IP协议知识1.IP地址属于网络层协议2.路由控制3.数据链路的抽象化4.IP属于面向无连接型1.IP地址属于网络层协议 在计算机通信中,为了识别通信对端,必须要有一个类似于地址的识别码进行标识。 MAC地址是用来标识同一个链路中不同计算机…...
【45-线程的实现方式-线程池的创建方式-线程池的执行顺序-CompletableFutrue异步处理】
一.知识回顾 【0.三高商城系统的专题专栏都帮你整理好了,请点击这里!】 【1-系统架构演进过程】 【2-微服务系统架构需求】 【3-高性能、高并发、高可用的三高商城系统项目介绍】 【4-Linux云服务器上安装Docker】 【5-Docker安装部署MySQL和Redis服务】…...
前馈神经网络与支持向量机实战 --- 手写数字识别
前馈神经网络与支持向量机实战 — 手写数字识别 文章目录前馈神经网络与支持向量机实战 --- 手写数字识别一、前馈神经网络介绍二、支持向量机介绍三、数据集说明四、环境准备五、实验要求六、Python代码tutorial_minst_fnn-keras.py:使用TensorFlow的Sequential实现…...
【C++类和对象】探索static成员、友元以及内部类
💞💞 前言 hello hello~ ,这里是大耳朵土土垚~💖💖 ,欢迎大家点赞🥳🥳关注💥💥收藏🌹🌹🌹 💥个人主页&#x…...
如何从0深入PostgreSQL内核写一个执行器算子?
如何从0深入PostgreSQL内核写一个执行器算子? 大家好,我叫光城,昨天分享了一个主题:如何从0深入PostgreSQL内核写一个执行器算子?今天来总结一下,本篇文章的直播回放可以在b站观看,点击原文或者…...
【go零基础】go-zero从零基础学习到实战教程 - 0环境配置
是个前端,最近开始学习go,后端除node外基本0基础,所以学习曲线有点绕,目标是个基础的服务端demo,搞个api服务后台,包含基础的用户登录、文章发布和写文章、权限控制,差不多就是个完整博客系统。…...
Fork for Mac v2.42 激活版 Git客户端
Fork for Mac是一款运行在Mac平台上的Git客户端,Fork Mac版具备基本的取、推、提交、修改、创建和删除分支和标签、创建和删除远程备份等功能,还有实用的差异查看器,你可以通过清晰的视图快速发现源代码中的更改。 Fork for Mac v2.42 激活版…...
在no branch上commmit后,再切换到其他分支,找不到no branch分支的修改怎么办?
解决办法 通过git reflog我们可以查看历史提交记录,这里的第二条提交(fbd3ea8)就是我在no branch上的提交。 再通过git checkout -b backup fbd3ea8,恢复到上次提交的状态,并且为其创建个分支backup,此时…...
SpringBoot学习之SpringBoot3集成OpenApi(三十八)
Springboot升级到Springboot3以后,就彻底放弃了对之前swagger的支持,转而重新支持最新的OpenApi,今天我们通过一个实例初步看看OpenApi和Swagger之间的区别. 一、POM依赖 我的POM文件如下,仅作参考: <?xml version="1.0" encoding="UTF-8"?>…...