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

认识哈希表

作者~小明学编程 

文章专栏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;}}

相关文章:

认识哈希表

作者&#xff1a;~小明学编程 文章专栏&#xff1a;Java数据结构 格言&#xff1a;目之所及皆为回忆&#xff0c;心之所想皆为过往 目录 为什么我们需要哈希表&#xff1f; 哈希表的原理 什么是哈希值 冲突 负载因子 解决冲突 闭散列 开散列/哈希桶 代码实现 不考虑…...

Vue学习:Hello小案例

使用Vue的目的&#xff1a;构建用户界面&#xff08;需要使用容器 摆放这个界面的内容&#xff09; favicon.ico:1 GET http://127.0.0.1:5500/favicon.ico 404 (Not Found) 没有页签图标 在者服务器中 http://127.0.0.1:5500没有/favicon.ico 强制刷新网页&#xff1a;s…...

IDEA创建Java Web项目

✅作者简介&#xff1a;热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏&#xff1a;JAVA开发者…...

C++11中可变参数模板使用

在看同事编写的代码&#xff0c;发现有如下的代码&#xff0c;因为没用过&#xff0c;所以查了一下这是什么语法&#xff0c;通过查询资料知道了这是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&#xff08;1&#xff09;通过命令设置&#xff08;2&#xff09;在配置文件中设置二、sql_mode 支持的模式1、ANSI 模式&#xff08;宽松模式…...

【C语言航路】第六站:指针初阶

目录 一、指针是什么 二、指针和指针类型 1.指针类型的意义 2.指针-整数 3.指针解引用 三、野指针 1.野指针的成因 &#xff08;1&#xff09;指针未初始化 &#xff08;2&#xff09;指针越界访问 &#xff08;3&#xff09;指针指向的空间释放 2.如何规避野指针 &a…...

从 JPA 2.x 迁移到 3.0

我最近收到了很多关于JPA 3.0的问题&#xff0c;由于EclipseLink和Hibernate现在提供了对它的全面支持&#xff0c;现在是时候仔细看看规范的最新更新了。作为从Java EE到Jakarta EE转换的一部分&#xff0c;Java Persistence API&#xff08;JPA&#xff09;更名为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"&#xff08;YA…...

Vue中的计算属性

计算属性&#xff1a;实际上是把vm中的属性进行计算加工&#xff0c;最后能够返回给页面一个结果&#xff0c;它是实时的&#xff0c;所以不能做异步操作。 细想一下&#xff0c;其实methods方法也能实现1中描述的现象&#xff0c;但是计算属性最大的优势是缓存&#xff01;&a…...

HTML+CSS个人电影网页设计——电影从你的全世界路过(4页)带音乐特效

HTML实例网页代码, 本实例适合于初学HTML的同学。该实例里面有设置了css的样式设置&#xff0c;有div的样式格局&#xff0c;这个实例比较全面&#xff0c;有助于同学的学习,本文将介绍如何通过从头开始设计个人网站并将其转换为代码的过程来实践设计。 文章目录一、网页介绍一…...

业务开发时,接口不能对外暴露的解决方案

1.内外网接口微服务隔离 将对外暴露的接口和对内暴露的接口分别放到两个微服务上,一个服务里所有的接口均对外暴露,另一个服务的接口只能内网服务间调用。 该方案需要额外编写一个只对内部暴露接口的微服务,将所有只能对内暴露的业务接口聚合到这个微服务里,通过这个聚合…...

「点燃我,温暖你」用Python制作一个动态爱心效果

最近「点燃我&#xff0c;温暖你」这部剧非常火&#xff0c;讲述的是程序员的爱情故事。 其中陈飞宇饰演的男主李峋&#xff0c;在剧中用程序做出的爱心跳动效果&#xff0c;非常炫。 网上各个大佬也是纷纷给出看法&#xff0c;综合就是不太可能用C语言来实现的。 大概率是AE…...

初识猿如意开发工具

嗨&#xff0c;大家好&#xff0c;我是异星球的小怪同志 一个想法有点乱七八糟的小怪 如果觉得对你有帮助&#xff0c;请支持一波。 希望未来可以一起学习交流。 一、初遇猿如意 第一次听说猿如意开发工具&#xff0c;于是抱着试试的心态&#xff0c;开始下载尝试。 首先是…...

PyTorch 2.0发布了,一行代码提速76%

PyTorch 官方&#xff1a;我们这次的新特性太好用了&#xff0c;所以就直接叫 2.0 了。 前段时间&#xff0c;PyTorch 团队在官方博客宣布 Pytorch 1.13 发布&#xff0c;包含 BetterTransformer 稳定版等多项更新。在体验新特性的同时&#xff0c;不少人也在期待下一个版本的推…...

栈的基本操作

一&#xff0c;自定义函数 #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内核编程-日志实现文件操作的封装日志功能的实现简单的测试日志功能其他前言 本文完整代码见&#xff1a;demo/12-win-driver-log 我们必须先搞定&#xff0c;DebugView可以看到DbgPrintDbgPrint的输出。否则…...

Hadoop原理与技术——Linus命令行基本操作

点击链接查看文档 一、实验目的 Hadoop运行在Linux系统上&#xff0c;因此&#xff0c;需要学习实践一些常用的Linux命令。本实验旨在熟悉常用的Linux操作&#xff0c;为顺利开展后续其他实验奠定基础。 二、实验环境 Windows 10 VMware Workstation Pro虚拟机 Hadoop环境 J…...

目标检测算法——YOLOv5/YOLOv7改进之结合特征提取网络RFBNet(涨点明显)

>>>深度学习Tricks,第一时间送达<<< 🚀🚀🚀NEW!!!魔改YOLOv5/v7目标检测算法来啦 ~ 计算机视觉——致力于目标检测领域科研Tricks改进与推荐 | 主要包括Backbone、Neck、Head、普通注意力机制、自注意力机制Transformer、Swin Transformer v2,各…...

anaconda使用系列教程--4)环境迁移

概述 跨平台尽量避免&#xff0c;比如windows和linux就不要跨平台&#xff0c;就在linux之间跨还是可以的 直接copy整体环境文件&#xff0c;适合于无法联网或网速不佳的新环境 anaconda最好是同版本的 迁移方法 使用requirement文件 A机器&#xff1a; pip freeze > …...

Kotlin高仿微信-第57篇-VIP管理列表

Kotlin高仿微信-项目实践58篇详细讲解了各个功能点&#xff0c;包括&#xff1a;注册、登录、主页、单聊(文本、表情、语音、图片、小视频、视频通话、语音通话、红包、转账)、群聊、个人信息、朋友圈、支付服务、扫一扫、搜索好友、添加好友、开通VIP等众多功能。 Kotlin高仿…...

贪心算法-- 纪念品分组

问题描述元旦快到了&#xff0c;校学生会让乐乐负责新年晚会的纪念品发放工作。为使得参加晚会的同学所获得的纪念品价值 相对均衡&#xff0c;他要把购来的纪念品根据价格进行分组&#xff0c;但每组最多只能包括两件纪念品&#xff0c;并且每组纪念品的价格之和不能超过一个给…...

java-php-net-python-代驾网站计算机毕业设计程序

java-php-net-python-代驾网站计算机毕业设计程序 java-php-net-python-代驾网站计算机毕业设计程序本源码技术栈&#xff1a; 项目架构&#xff1a;B/S架构 开发语言&#xff1a;Java语言 开发软件&#xff1a;idea eclipse 前端技术&#xff1a;Layui、HTML、CSS、JS、JQ…...

简洁自增ID实现方案

简介 从数据库性能角度考虑&#xff0c;我们经常需要数字型的自增主键&#xff0c;有时候我们并不想用像MySQL自带的自增&#xff0c;因为从1开始很数据位数不一样&#xff0c;对有点强迫症的人来说&#xff0c;不是很友好。 另外&#xff0c;别人也容易根据这种从1开始的自增…...

JMeter入门教程(14)——场景设计

1.JMeter中场景设计是通过线程组来实现的 如图&#xff1a; 控制面板中各元素介绍&#xff1a; 名称&#xff1a;可以随意设置&#xff0c;最好有业务意义。 注释&#xff1a;可以随意设置&#xff0c;可以为空。 在取样器错误后要执行的动作&#xff1a;其中的某一个请求出错后…...

SVM 用于将数据分类为两分类或多分类(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…...

转行软件测试我后悔了

很多时候&#xff0c;都在想当初做的转行软件测试行业的决定是对的吗&#xff1f;现在后悔还来得及吗&#xff1f; 记得在求职的时候&#xff0c;面试官经常问我&#xff1a;“为什么要选择软件测试工作?” 而我也会经常说一堆自己有的没的优势去应付。 工作这么久了&#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 引言 声明&#xff1a;本文为《Kubernetes权威指南&#xff1a;从Docker到Kubernetes实践全接触&#xff08;第5版&#xff09;》…...

浅谈降维实操,一种用于处理特征的方式——后附Python代码

&#x1f466;&#x1f466;一个帅气的boy&#xff0c;你可以叫我Love And Program &#x1f5b1; ⌨个人主页&#xff1a;Love And Program的个人主页 &#x1f496;&#x1f496;如果对你有帮助的话希望三连&#x1f4a8;&#x1f4a8;支持一下博主 降维实操前言线性降维低…...

深度学习中的正则化——L1、L2 和 Dropout

正则化是一组技术&#xff0c;可以防止神经网络中的过度拟合&#xff0c;从而在面对来自问题域的全新数据时提高深度学习模型的准确性。 在本文中&#xff0c;我们将介绍最流行的正则化技术&#xff0c;称为 L1、L2 和 dropout。 文章目录1. 回顾&#xff1a;过拟合2.什么是正则…...

数据结构(王卓)(4)附:链表的销毁与清空

销毁 Status 销毁单链表(LinkList L) {LinkList p;while (L){p L;L->next;delete p;}return OK; } 运行逻辑&#xff1a; &#xff08;1&#xff09;:设定一个指针&#xff0c;让指针指向链表的头指针L &#xff08;2&#xff09;&#xff1a;让头指针等于头指针里面指向下…...

C++图书管理系统(管理员-读者)

C图书管理系统&#xff08;管理员-读者&#xff09; 一、设计一款文字式交互的图书管理系统&#xff0c;要求具备注册登录、浏览图书、借还图书等基本功能&#xff1b; 二、要求以外部文件的形式存储书籍信息、馆藏记录、借阅记录、用户信息等。【可参考提供的书籍清单】 三…...

永磁同步电机恒压频比(V/F)开环控制系统Matlab/Simulink仿真分析及代码生成到工程实现

文章目录前言一、 恒压频比&#xff08;V/F&#xff09;控制原理二、永磁同步电机恒压频比开环控制系统Matlab/Simulink仿真分析2.1.仿真电路分析2.1.1.恒压频比控制算法2.1.2.输出处理2.1.3.主电路2.2.仿真结果分析2.2.1.设定目标转速为1200r/min2.2.1.设定目标转速为变化值三…...

基于JSP网上书城的设计与实现

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…...

java计算机毕业设计-学生宿舍故障报修管理信息系统-源程序+mysql+系统+lw文档+远程调试

java计算机毕业设计-学生宿舍故障报修管理信息系统-源程序mysql系统lw文档远程调试 java计算机毕业设计-学生宿舍故障报修管理信息系统-源程序mysql系统lw文档远程调试本源码技术栈&#xff1a; 项目架构&#xff1a;B/S架构 开发语言&#xff1a;Java语言 开发软件&#xf…...

vue学习笔记——简单入门总结(四)

文章目录1.Vue3的特性和变化1.1.创建vue3项目1.2.分析main.js变化&#xff1a;1.3.setup--组合式api的开端1.4.ref函数和reactive函数&#xff1a;1.5.watch监视属性1.5.watchEffect函数1.6.vue3生命周期&#xff1a;1.Vue3的特性和变化 1.1.创建vue3项目 1.这里我们使用脚手架…...

数据结构与算法—数组栈和链表栈

数据结构与算法—数组栈和链表栈 &#x1f308;一览众山小数据结构与算法—数组栈和链表栈栈介绍栈图解栈实现数组实现栈实现思路实现代码单链表实现栈实现思路(图解)实现代码栈总结栈力扣栈介绍 栈,存储货物或供旅客住宿的地方,可引申为仓库、中转站&#xff0c;所以引入到计算…...

【应用】Kubernetes

Kubernetesk8s 安装流程安装前配置安装 docker 以及 k8s 组件初始化 k8s 集群测试使用&#xff1a;安装 kubernetes-dashboardk8s 基础概念k8s 核心技术概念k8s 内部组件k8s 中的 IP 地址K8S 服务暴露的三种方式k8s 安装流程 k8s-masterk8s-node01k8s-node02192.168.86.140192…...

GEE:关系、条件和布尔运算

ee.Image对象具有一组用于构建决策表达式的关系、条件和布尔运算方法。这些方法可以用来掩膜、绘制分类地图和重新赋值。 本文记录了在GEE&#xff08;Google Earth Engine&#xff09;平台上的关系运算符和布尔运算符&#xff0c;分别应用到了三个不用的场景&#xff08;筛选低…...

Java项目:SSM的KTV管理系统

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 主要功能包括&#xff1a; 登陆页,房间信息,房间管理,开取房间,房间查询,会员管理,食物管理,查看订单,查询订单,查看房间消费使用情况等功能。…...

包装类-Wrapper

包装类的分类 针对八种基本数据类型相应的引用类型-包装类有了类的特点&#xff0c;就可以调用对应的类中的方法 装箱和拆箱 Java是一种面向对象的编程语言&#xff0c;学习Java时就被明确灌输了一个概念&#xff1a;OOP&#xff0c;即面向对象编程。一切皆对象。但是基本…...

计算机网络——运输层【重点】

运输层概述 概念 进程之间的通信 从通信和信息处理的角度看&#xff0c;运输层向它上面的应用层提供通信服务&#xff0c;它属于面向通信部分的最高层&#xff0c;同时也是用户功能中的最低层。当网络的边缘部分中的两个主机使用网络的核心部分的功能进行端到端的通信时&…...

ADSP-21569/ADSP-21593的开发入门(上)

作者的话 ADI的SHARC系列DSP&#xff0c;目前已经出到5系列了&#xff0c;最新的一颗叫2159x&#xff0c;按照ADI的说法&#xff0c;这颗DSP的性能是21569的两倍&#xff0c;但又能和21569做P2P的替换&#xff0c;所以下面我们就以21593为例&#xff0c;写一点资料&#xff0c…...

【Android App】在线直播之搭建WebRTC的服务端(图文解释 简单易懂)

有问题或需要源码请点赞关注收藏后评论区留言私信~~~ 一、WebRTC的系统架构 WebRTC&#xff08;网页即时通信&#xff09;是一个支持浏览器之间实时音视频对话的新型技术&#xff0c;WebRTC体系由应用于实时通信的编程接口和一组通信协议组成&#xff0c;已成为互联网流媒体通…...

x265 帧间预测

帧间编码入口函数&#xff1a; 从 Analysis::compressCTU 是ctu编码的入口函数&#xff0c;根据 slice 类型判断是 I 还是 BP&#xff0c;如果是BP则执行帧间编码函数 Analysis::compressInterCU_rdx_x&#xff1a;&#xff1a;/*压缩分析CTU过程&#xff1a;1.为当前CTU加载QP…...

【sciter】安全应用列表控件总结

一、效果图 二、功能点 实现电脑文件拖拽进入到安全桌面,读取文件路径,生成应用。可以配置允许拖拽进入安全桌面的文件应用。点击添加图标,可以添加应用到安全桌面中。在安全桌面列表中每一个应用实现双击、失去焦点,获取焦点、右键事件在安全桌面列表中每一个应用可以实现…...

一篇文章让你搞懂Java顺序表

目录 一、 线性表的基本介绍 二、顺序表 1、顺序表的概念 2. 创建顺序表类&#xff08;ArrayList&#xff09; 2. 增加元素 3. 删除元素 4. 修改某个元素 5. 查找元素 Main类 在数据结构体系中我们将整个数据结构分为两类&#xff0c;一类是线性结构&#xff1b; 线性…...

小白必知必会的几个IP协议知识

小白必知必会的几个IP协议知识1.IP地址属于网络层协议2.路由控制3.数据链路的抽象化4.IP属于面向无连接型1.IP地址属于网络层协议 在计算机通信中&#xff0c;为了识别通信对端&#xff0c;必须要有一个类似于地址的识别码进行标识。 MAC地址是用来标识同一个链路中不同计算机…...

【45-线程的实现方式-线程池的创建方式-线程池的执行顺序-CompletableFutrue异步处理】

一.知识回顾 【0.三高商城系统的专题专栏都帮你整理好了&#xff0c;请点击这里&#xff01;】 【1-系统架构演进过程】 【2-微服务系统架构需求】 【3-高性能、高并发、高可用的三高商城系统项目介绍】 【4-Linux云服务器上安装Docker】 【5-Docker安装部署MySQL和Redis服务】…...

前馈神经网络与支持向量机实战 --- 手写数字识别

前馈神经网络与支持向量机实战 — 手写数字识别 文章目录前馈神经网络与支持向量机实战 --- 手写数字识别一、前馈神经网络介绍二、支持向量机介绍三、数据集说明四、环境准备五、实验要求六、Python代码tutorial_minst_fnn-keras.py&#xff1a;使用TensorFlow的Sequential实现…...

“超级智能轿车”智己L6开启全国用户交付

继昨天智己L6官宣公布,新增上市权益价为22.69万元的Max 长续航欧;今日又添重磅好消息!新晋爆品智己L6在北京、上海、广州、深圳、杭州、苏州、南京等十余座城市,将首批新车交付用户,正式拉开全国交付的帷幕。同时,智己L6的IM AD“去高精地图城市NOA”在上海、深圳、广州、…...

Linux驱动开发笔记(二) 基于字符设备驱动的I/O操作

文章目录 前言一、设备驱动的作用与本质1. 驱动的作用2. 有无操作系统的区别 二、内存管理单元MMU三、相关函数1. ioremap( )2. iounmap( )3. class_create( )4. class_destroy( ) 四、GPIO的基本知识1. GPIO的寄存器进行读写操作流程2. 引脚复用2. 定义GPIO寄存器物理地址 五、…...

WebService的wsdl详解

webservice服务的wsdl内容详解&#xff0c;以及如何根据其内容编写调用代码 wsdl示例 展示一个webservice的wsdl&#xff0c;及调用这个接口的Axis客户端 wsdl This XML file does not appear to have any style information associated with it. The document tree is shown…...

分布式拒绝服务解决方式

在网络安全领域中&#xff0c;分布式拒绝服务&#xff08;DDoS&#xff09;攻击始终占据着举足轻重的地位&#xff0c;其影响力不容忽视。随着网络技术的日新月异和网络环境的日益复杂化&#xff0c;DDoS攻击不仅变得愈发频繁&#xff0c;而且其破坏性和影响力也呈现出惊人的增…...

【Java】流程控制(条件语句、循环语句、分支语句和异常处理)

1、简介 流程控制是编程中非常重要的一部分&#xff0c;它决定了程序执行的顺序和逻辑。在Java中&#xff0c;有几种主要的流程控制结构&#xff0c;包括条件语句、循环语句、分支语句和异常处理。 2、条件语句 2.1简介 条件语句用于根据某个条件是否成立来决定执行哪段代码…...

Flutter 中的 FractionalTranslation 小部件:全面指南

Flutter 中的 FractionalTranslation 小部件&#xff1a;全面指南 在 Flutter 的丰富布局库中&#xff0c;FractionalTranslation 是一个允许你将子组件沿着一个轴或两个轴进行部分平移的动画小部件。这种类型的平移通常用于创建滑动效果&#xff0c;如卡片的滑动删除或滑动展…...