哈希表 | 哈希查找 | 哈希函数 | 数据结构 | 大话数据结构 | Java

🙋大家好!我是毛毛张!
🌈个人首页: 神马都会亿点点的毛毛张

📌毛毛张今天分享的内容🖆是数据结构中的哈希表,毛毛张主要是依据《大话数据结构📖》的内容来进行整理,不同之处是使用Java语言来介绍其中的代码实现,同时也为后面介绍Java中的集合做铺垫🛤️

文章目录

  • 1.散列表查找(哈希表)概述
    • 1.1 散列表查找定义
    • 1.2 散列表查找步骤
  • 2.散列函数的构造方法
    • 2.1 直接定址法(了解)
    • 2.2 数字分析法(了解)
    • 2.3 平方取中法(了解)
    • 2.4 折叠法(了解)
    • 2.5 除留余数法(掌握)
    • 2.6 随机数法(了解)
  • 3.处理散列冲突
    • 3.1 开放定址法
    • 3.2 链地址法
    • 3.3 公共溢出区法
  • 4.散列表查找实现
    • 4.1 散列表查找的算法Java实现
    • 4.2 性能分析
  • 参考文献

1.散列表查找(哈希表)概述

1.1 散列表查找定义

  • 散列技术: 是在记录的存储位置和它的关键字之间建立一个确定的对应关系 f f f,使得每个关键字key对应一个存储位置 f ( k e y ) f(key) f(key)。查找时,根据这个确定的对应关系找到给定值key的映射 f ( k e y ) f(key) f(key),若查找集合中存在这个记录,则必定在 f ( k e y ) f(key) f(key)的位置上。我们把这种对应关系 f f f称为散列函数,又称哈希(Hash)函数
    存储位置 = f ( 关键字 ) 存储位置 = f(关键字) 存储位置=f(关键字)
  • 散列表/哈希表(Hash table): 采用散列技术将记录存储在一块连续的存储空间中,这块连续存储空间称为散列表哈希表(Hash table)。而关键字对应的记录存储位置我们称为散列地址
  • 总结:
    • 散列表通过建立关键字和存储地址之间的一种直接映射关系,是一种根据关键字而直接进行访问的数据结构
    • 散列技术使得我们可以通过查找关键字不需要比较就可获得需要的记录的存储位置

1.2 散列表查找步骤

  • 散列过程步骤: 如下图
    • 第一步: 通过散列函数计算记录的散列地址,并按此散列地址存储记录
    • 第二步: 当查找记录时,我们通过同样的散列函数计算记录的散列地址,按此散列地址访问该记录,由于存取用的是同一个散列函数,因此结果当然也是相同的
      image-20240627154931051
  • 散列技术既是一种存储方法, 也是一种查找方法,而散列技术的记录之间不存在什么逻辑关系,它只与关键字有关联,因此散列主要是面向查找的存储结构
  • 散列技术最合适的求解问题是查找与给定值相等的记录
    • 不适合那种同样关键字,它能对应很多记录的情况,就不适合用散列技术
    • 散列表也不适合范围查找,比如查找一个班级18~22岁的同学,在散列表中没法进行
  • 冲突(collision): 散列函数可能会把两个或两个以上的不同关键字映射到同一地址,称这种情况为冲突,这些发生碰撞的不同关键字称为同义词
    • 一方面,设计得好的散列函数应尽量减少这样的冲突
    • 另一方面,由于这样的冲突总是不可避免的,所以还要设计好处理冲突的方法
  • 设计一个简单、均匀、存储利用率高的散列函数是散列技术中最关键的问题,一个好的散列表在理想情况下,对散列表进行查找的时间复杂度为$O(1) $,即与表中元素的个数无关

2.散列函数的构造方法

  • 好的散列函数设计原则:
    • 计算简单: 散列函数的计算应尽量简单,能够在较短的时间内计算出任一关键字对应的散列地址
    • 散列地址分布均匀: 散列函数计算出来的地址应该能等概率、均匀地分布在整个地址空间中,从而减少冲突的发生
    • 散列函数的定义域必须包含全部需要存储的关键字,而值域的范围则依赖于散列表的大小或地址范围
  • 下面介绍接种常用的散列函数构造方法

2.1 直接定址法(了解)

  • 直接取关键字的某个线性函数值为散列地址,散列函数为:其中a、b为常数
    f ( k e y ) = a × k e y + b f(key)=a×key + b f(key)=a×key+b
    image-20240627160121771
  • 这种方法计算最简单,且不会产生冲突,但并不常用。它适合关键字的分布基本连续的情况,若关键字分布不连续,空位较多,则会造成存储空间的浪费。

2.2 数字分析法(了解)

  • 例如当手机号码为关键字时,其11位数字是有规则的,此时是无需把11位数值全部当做散列地址,这时我们给关键词抽取, 抽取方法是使用关键字的一部分来计算散列存储位置的方法,这在散列函数中是常常用到的手段
  • 数字分析法通常适合处理关键字位数比较大的情况,如果事先知道关键字的分布且关键字的若干位分布较均匀,就可以考虑用这个方法。

2.3 平方取中法(了解)

  • 这个方法计算很简单,假设关键字是1234,那么它的平方就是1522756,再抽取中间的3位就是227,用做散列地址。
  • 再比如关键字是4321,那么它的平方就是18671041,抽取中间的3位就可以是671,也可以是710,用做散列地址。
  • 平方取中法比较适合于不知道关键字的分布,而位数又不是很大的情况

2.4 折叠法(了解)

  • 折叠法 是将关键字从左到右分割成位数相等的几部分(最后一部分位数可以短些),然后将这几部分叠加求和,并按散列表表长,取后几位作为散列地址。
  • 折叠法适合事先不需要知道关键字的分布,适合关键字位数比较多的情况

2.5 除留余数法(掌握)

  • 除留取余法对于散列表长为m的散列函数公式为:f(key)= key mod p (p ≤ m)mod是取模(求余数)的意思,这方法不仅可以对关键字直接取模,也可在折叠、平方取中后再取模。
  • 除留余数法的关键是就在于选择合适的 p p p p p p如果选择不好,就有可能产生同义词,根据前辈门的经验,若散列表表长为 m m m,通常 p p p为小于或等于表长(最好接近 m m m)的最小质数或不包含小于20质因子的合数
  • 图例:
    image-20240627161944061
  • 此方法是最常用的构造散列函数的方法

2.6 随机数法(了解)

  • 选择一个随机数,取关键字的随机函数值为它的散列地址。也就是 f ( k e y ) = r a n d o m ( k e y ) f(key)=random(key) f(key)=random(key)这里 r a n d o m random random是随机函数。
  • 当关键字的长度不等时,采用这个方法构造散列函数是比较合适的

3.处理散列冲突

  • 任何设计出来的散列函数都不可能绝对地避免冲突,因此,必须考虑在发生冲突时应该如何处理,即为产生冲突的关键字寻找下一个空的Hash地址
  • H i H_i Hi表示处理冲突中第 i i i次探测得到的散列地址,假设得到的另一个散列地址 H 1 H_1 H1仍然发生冲突,只得继续求下一个地址 H 2 H_2 H2,以此类推,直到 H k H_k Hk不发生冲突为止,则 H k H_k Hk为关键字在表中的地址

3.1 开放定址法

  • 开放定址法就是一旦发生了冲突,就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到,并将记录存入
  • 计算公式: H i ( k e y ) = ( f ( k e y ) + d i ) % m ( d i = 1 , 2 , 3 , . . . , m − 1 ) H_i(key)=(f(key)+d_i) \% m\ (d_i=1,2,3,...,m-1) Hi(key)=(f(key)+di)%m (di=1,2,3,...,m1),式中, H ( k e y ) H(key) H(key)为散列函数 i = 0 , 1 , 2 , . . . , k ( k < = m − 1 ) i=0,1,2,...,k\ (k<=m-1) i=0,1,2,...,k (k<=m1) m m m表示散列列表表长; d i d_i di​​为增量序列
  • 取定某一增量序列后,对应的处理方法就是确定的,通常有以下4种方法:
  • 线性探测法:当 d i = 0 , 1 , 2 , . . . , m − 1 d_i=0,1,2,..., m-1 di=0,1,2,...,m1时,称为线性探测法
    • 特点: 当冲突发生时,顺序查看表中下一个单元(探测到表尾地址 m − 1 m-1 m1时,下一个探测地址是表首地址 0 0 0),直到找出一个空闲单元(当表未填满时一定能找到一个空闲单元)或查遍全表
    • 缺点: 线性探测法可能使第 i i i个散列地址的同义词存入第 i + 1 i+1 i+1个散列地址,这使得本应存入第 i + 1 i+1 i+1个散列地址的元素就争夺第 i + 2 i + 2 i+2个散列地址的元素的地址,从而造成大量元素在相邻的散列地址上堆积,大大降低了查找效率。
  • 平方探测法: d i = 0 2 , 1 2 , − 1 2 , 2 2 , − 2 2 , . . , k 2 , − k 2 d_i=0^2,1^2,-1^2,2^2,-2^2,..,k^2, -k^2 di=02,12,12,22,22,..,k2,k2时,称为平方探测法,其中 k < m / 2 k<m/2 k<m/2,散列表长度 m m m必须是一个可以表示成 4 k + 3 4k+ 3 4k+3​的素数,又称二次探测法
    • 平方探测法是一种较好的处理冲突的方法,可以避免出现堆积问题
    • 缺点: 不能探测到散列表上的所有单元,但至少能探测到一半单元
  • 再散列法: d i = H a s h 2 ( k e y ) d_i= Hash_2(key) di=Hash2(key)时,称为再散列法,又称双散列法,需要使用两个或者多个散列函数,当通过第一个散列函数 H ( k e y ) H(key) H(key)得到的地址发生冲突时,则利用第二个散列函数 H a s h 2 ( k e y ) Hash_2(key) Hash2(key)计算该关键字的地址增量
    • 具体散列函数形式为: H i = ( H ( k e y ) + i ∗ H a s h 2 ( k e y ) ) % m H_i= (H(key) + i*Hash_2(key)) \% m Hi=(H(key)+iHash2(key))%m,初始探测位置 H 0 = H ( k e y ) H_0 = H(key)% m H0=H(key) i i i是冲突的次数,初始为 0 0 0
    • 使用该方法,最多经过 m − 1 m-1 m1次探测就会遍历表中所有位置,回到 H 0 H_0 H0​位置
    • 这种方法使得关键字不产生剧集,相应地也增加了计算的时间
  • 伪随机数探测法: 在发生冲突时,对于位移量 d i d_i di​采用随机函数计算得到,称为伪随机探测法
    • 伪随机数是说,如果我们设置随机种子相同,则不断调用随机函数可以生成不会重复的数列,我们在查找时,用同样的随机种子,它每次得到的数列是相同的,相同的 d i d_i di当然可以得到相同的散列地址

注意:

  • 在开放定址的情形下,不能随便物理删除表中的已有元素,因为若删除元素,则会截断其他具有相同散列地址的元素的查找地址。
  • 因此,要删除一个元素时,可给它做一个删除标记,进行逻辑删除。
  • 但这样做的副作用是:执行多次删除后,表面上看起来散列表很满,实际上有许多位置未利用,因此需要定期维护散列表,要把删除标记的元素物理删除。

3.2 链地址法

  • 将所有关键字为同义词的记录存储在一个单链表中,我们称这种表为同义词子表,在散列表中只存储所有同义词子表的头指针
  • 示例: 有关键字序列为 { 12 , 67 , 56 , 16 , 25 , 37 , 22 , 29 , 15 , 47 , 48 , 34 } \{12, 67, 56, 16, 25, 37, 22, 29,15, 47,48, 34\} {12,67,56,16,25,37,22,29,15,47,48,34},我们用除留余数法构造散列函数 H ( k e y ) = k e y % 12 H(key)=key\%12 H(key)=key%12,用链地址法处理冲突,建立的表如下图所示
    image-20240627173927852
  • 链地址法对于可能会造成很多冲突的散列函数来说,提供了绝不会出现找不到地址的保障。当然,这也就带来了查找时需要遍历单链表的性能损耗

3.3 公共溢出区法

  • 这个方法其实就更加好理解,就是把凡是冲突的家伙额外找个公共场所待着,我们为所有冲突的关键字建立了一个公共的溢出区来存放
  • 示例:我们共有三个关键字 37 , 48 , 34 {37,48,34} 37,48,34与之前的关键字位置有冲突,那么就将它们存储到溢出表中,如下图所示
    在这里插入图片描述
  • 查找步骤:
    • 在查找时,对给定值通过散列函数计算出散列地址后,先与基本表的相应位置进行对比,如果相等,则查找成功;
    • 如果不相等,则到溢出表去进行顺序查找
  • 如果相对于基本表而言,有冲突的数据很少的情况下,公共溢出区的结构对查找性能来说还是非常高的

4.散列表查找实现

4.1 散列表查找的算法Java实现

  • 首先是需要定义一个散列表的结构以及一些相关的常数,其中HashTable就是散列表类,结构当中的elem为一个动态数组
public class HashTable {public static final int SUCCESS = 1;public static final int UNSUCCESS = 0;public static final int HASHSIZE = 12;    // 定义散列表表长为数组的长度public static final int NULLKEY = -32768; // 代表空地址private int[] elem;  // 数组元素存储基址,动态分配数组private int count;   // 当前数据元素个数private static int m = HASHSIZE; // 散列表表长,全局变量
}
  • 利用构造函数对散列表进行初始化
 public HashTable() {m = HASHSIZE;this.count = m;this.elem = new int[m];for (int i = 0; i < m; i++) {this.elem[i] = NULLKEY; // 初始化为空地址}
}
  • 为了插入时计算地址,我们需要定义散列函数,散列函数可以根据不同情况更改算法
// 散列函数
public int hash(int key) {return key % m;  // 除留余数法
}
  • 初始化完成后,我们可以对散列表进行插入操作,假设我们插入的关键字集合为 12 , 67 , 56 , 16 , 25 , 37 , 22 , 29 , 15 , 47 , 48 , 34 {12,67,56,16,25,37,22,29,15,47, 48,34} 12,67,56,16,25,37,22,29,15,47,48,34
 // 插入关键字进散列表
public void insertHash(int key) {int addr = hash(key);  // 通过散列函数求散列地址// 如果不为空,则冲突while (this.elem[addr] != NULLKEY) {addr = (addr + 1) % m;  // 开放定址法的线性探测}this.elem[addr] = key;  // 直到有空位后插入关键字
}
  • 代码中插入关键字时,首先算出散列地址,如果当前地址不为空关键字,则说明有冲突。此时我们应用开放定址法的线性探测进行重新寻址,此处也可更改为链地址法等其他解决冲突的办法。
  • 散列表存在后,我们在需要时就可以通过散列表查找要的记录
// 散列表查找关键字,找到后用addr保存地址
public boolean searchHash(int key, int[] addr) {addr[0] = hash(key);  // 通过散列函数求得散列地址// 如果不为空,则有同义词冲突while (this.elem[addr[0]] != key) {addr[0] = (addr[0] + 1) % m;  // 开放地址法的线性探测if (this.elem[addr[0]] == NULLKEY || addr[0] == hash(key)) {// 如果循环到空址或回到原点return false;  // 则说明关键字不存在}}return true;
}
  • 查找的代码与插入的代码非常类似,只需做一个不存在关键字的判断而已
  • 完整的测试代码如下:
public class HashTable {public static final int SUCCESS = 1;public static final int UNSUCCESS = 0;public static final int HASHSIZE = 12;    // 定义散列表表长为数组的长度public static final int NULLKEY = -32768; // 代表空地址private int[] elem;  // 数组元素存储基址,动态分配数组private int count;   // 当前数据元素个数private static int m = HASHSIZE; // 散列表表长,全局变量public HashTable() {this.elem = new int[HASHSIZE];this.count = HASHSIZE;for (int i = 0; i < HASHSIZE; i++) {this.elem[i] = NULLKEY; // 初始化为空地址}}// 初始化散列表public boolean initHashTable() {m = HASHSIZE;this.count = m;this.elem = new int[m];for (int i = 0; i < m; i++) {this.elem[i] = NULLKEY; // 初始化为空地址}return true;}// 散列函数public int hash(int key) {return key % m;  // 除留余数法}// 插入关键字进散列表public void insertHash(int key) {int addr = hash(key);  // 通过散列函数求散列地址// 如果不为空,则冲突while (this.elem[addr] != NULLKEY) {addr = (addr + 1) % m;  // 开放定址法的线性探测}this.elem[addr] = key;  // 直到有空位后插入关键字}// 散列表查找关键字,找到后用addr保存地址public boolean searchHash(int key, int[] addr) {addr[0] = hash(key);  // 通过散列函数求得散列地址// 如果不为空,则有同义词冲突while (this.elem[addr[0]] != key) {addr[0] = (addr[0] + 1) % m;  // 开放地址法的线性探测if (this.elem[addr[0]] == NULLKEY || addr[0] == hash(key)) {// 如果循环到空址或回到原点return false;  // 则说明关键字不存在}}return true;}public static void main(String[] args) {HashTable hashTable = new HashTable();boolean isInitialized = hashTable.initHashTable();System.out.println("HashTable initialized: " + isInitialized);// 插入一些关键字hashTable.insertHash(10);hashTable.insertHash(22);hashTable.insertHash(31);hashTable.insertHash(4);// 查找关键字int[] addr = new int[1];boolean found = hashTable.searchHash(22, addr);System.out.println("Key 22 found: " + found + ", at address: " + addr[0]);found = hashTable.searchHash(15, addr);System.out.println("Key 15 found: " + found);}
}

4.2 性能分析

  • 虽然散列表在关键字与记录的存储位置之间建立了直接映像,但由于冲突的产生,使得散列表的查找过程仍然是一个给定值和关键字进行比较的过程,因此,仍需要以平均查找长度作为衡量散列表的查找效率的度量。如果没有冲突,散列查找的时间复杂度是最高的,时间复杂度为 O ( 1 ) O(1) O(1)
  • 若用 c i c_i ci表示每一个关键字查找的次数,则平均查找次数可表示为: A S L = ( ∑ i = 0 m c i ) / m ASL=(\displaystyle\sum_{i=0}^{m}c_i)/m ASL=(i=0mci)/m
  • 散列表的查找效率取决于三个因素:
    • 散列函数是否均匀:散列函数的好坏直接影响着出现冲突的频繁程度,不过,由于不同的散列函数对同一组随机的关键字,产生冲突的可能性是相同的,因此我们可以不考虑它对平均查找长度的影响
    • 处理冲突的方法:相同的关键字、相同的散列函数,但处理冲突的方法不同,会使得平均查找长度不同。比如线性探测处理冲突可能会产生堆积,显然就没有二次探测法好,而链地址法处理冲突不会产生任何堆积,因而具有更佳的平均查找性能
    • 散列表的装填因子
  • 装填因子: 散列表的装填因子一般记为 α \alpha α,它用来表征散列表的装满程度,其计算公式为: α = n ( 表中填入的记录个数 ) / m ( 散列表长度 ) \alpha=n_{(表中填入的记录个数)}/m_{(散列表长度)} α=n(表中填入的记录个数)/m(散列表长度)
  • 散列表的平均查找长度取决于散列表的装填因子 α \alpha α,而不直接依赖于 n n n m m m
    • 直观地看, α \alpha α越大,表示装填的记录越,发生冲突的可能性越大,反之发生冲突的可能性越小
  • 不管记录个数 n n n有多大,我们总可以选择一个合适的装填因子以便将平均查找长度限定在一个范围之内,此时我们散列查找的时间复杂度就真的是 O ( 1 ) O(1) O(1)了。 为了做到这一点,通常我们都是将散列表的空间设置得比查找集合大,此时虽然是浪费了一定的空间,但换来的是查找效率的大大提升,总的来说,还是非常值得的。

参考文献

  • 《大话数据结构》
  • https://blog.csdn.net/Real_Fool_/article/details/114359564
  • https://blog.csdn.net/qq_56884023/article/details/123072671

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

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

相关文章

上午写的博客,下午就上了bing首页,惊不惊喜,意不意外

今天上午写了一篇《用免费的“山水博客”来管理你的离线文章》的博客&#xff0c;没想到下午在必应就搜到了&#xff0c;而且还是首页第四个。 不由的让人感概&#xff0c;以前写了那么多的博客&#xff0c;想将排名排前点&#xff0c;在网上找了不少秘籍&#xff0c;都没成功&…

神经网络学习笔记9-简单的反向传播和线性回归

tensor在pytorch中是一个非常重要的类型 假如需要计算梯度&#xff0c;就将tensor中 requires_grad设为true loss是一个张量&#xff0c;在做运算时构建运算图&#xff0c;因此不要直接进行&#xff0c;会将将梯度存入w&#xff0c;当反向传播完成 后&#xff0c;该计算图会…

计算机的错误计算(十四)

摘要 解读 GPU和CPU计算上的精度差异&#xff1a;GPU 的 3个输出的相对误差分别高达 62.5%、50%、62.5%。 例1. 计算下列两个矩阵的乘积&#xff1a; 显然&#xff0c;其结果为第一列&#xff1a; 这个结果是准确的。 例2. 已知上面 3 个矩阵是由下面代码产生或输出&…

奔驰汽车的通信如此固若金汤的原因

随着摄像系统、距离控制、航线保持等功能以及制动辅助系统、制动力分配系统、车身侧倾干预与缓解系统等功能的飞速发展,汽车的系统功能之间已经不再独立,而是呈现互相合作的关系,各功能之间的无缝集成更是各大整车厂追求的目标。俗话说,外练筋骨皮,内练一口气,有了各式安…

HexPlane代码复现(十几分钟就复现成功的一篇论文代码!!!!!)

https://caoang327.github.io/HexPlane/ 一、 python setup.py develop命令用不了了 running develop /home/uriky/anaconda3/envs/hexplane/lib/python3.8/site-packages/setuptools/command/easy_install.py:144: EasyInstallDeprecationWarning: easy_install command is d…

ISO 50001能源管理体系:激活绿色动能和共塑可持续发展

在当今全球化加速和工业化水平不断提高的背景下&#xff0c;能源消费呈现出前所未有的增长趋势。然而&#xff0c;能源资源的有限性、能源价格的波动以及能源消费对环境造成的影响&#xff0c;尤其是温室气体排放导致的全球气候变化问题&#xff0c;已经成为全球关注的焦点。为…

怎么在必应bing上投放搜索广告?

搜索引擎已成为企业获取潜在客户、提升品牌曝光度的关键平台&#xff0c;微软必应&#xff08;Bing&#xff09;以其庞大的用户基数、精准的定位能力以及与微软生态系统的深度整合&#xff0c;为企业提供了极具价值的广告投放渠道。云衔科技助力企业实现必应bing广告的精准投放…

私接路由器导致部分终端(电脑、手机等)无法上网问题分析

【1】私接路由器场景 某公司办公网可以上互联网&#xff0c;网络终端通过公司路由器上的DHCP服务器自动获取IP地址&#xff0c;对终端设备接入没有做Mac地址绑定等策略限制&#xff0c;交换机也没有划分vlan。员工张三所在办公室网口太少或者WiFi信号差&#xff0c;私自找了一台…

前端实现 海浪(波浪)进度条效果(支持自定义长度;调节速度,2s缓冲结束)

实现海浪进度条 文章目录 实现海浪进度条效果图如下(投入使用的版本)背景和过程一、调试和探索过程(下面都会给出来对应代码)二、类似Element-plus的进度条样式1. CSS的样式如下2. HTML结构如下 二、电涌效果的进度条如下1. CSS的样式如下2. HTML的结构如下:3. JavaScript代码如…

推荐两款电脑文件处理工具,强大到你不舍得卸载

EasyFileCount EasyFileCount是一款基于Java开发的多功能文件管理工具&#xff0c;旨在帮助用户更轻松地管理和优化他们的文件存储。以下是EasyFileCount的主要功能和特点&#xff1a; 查看文件夹大小&#xff1a;用户可以快速统计和查看文件夹的总大小&#xff0c;实时显示各…

40.设计HOOK引擎的好处

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 上一个内容&#xff1a;39.右键弹出菜单管理游戏列表 以 39.右键弹出菜单管理游戏列表 它的代码为基础进行修改 效果图&#xff1a; 实现步骤&#xff1a; 首…

【海思Hi3403V100】多目拼接相机套板硬件规划方案

海思Hi3403V100 是专业超高清智能网络摄像头 SoC。该芯片最高支持四路 sensor 输入&#xff0c;支持最高 4K60fps 的 ISP 图像处理能力&#xff0c;支持 3F 、WDR、多级降噪、六轴防抖、硬件拼接、多光谱融合等多种传统图像增强和处理算法&#xff0c;支持通过AI 算法对输入图像…

视觉灵感的探索和分享平台

做设计没灵感&#xff1f;大脑一片空白&#xff1f;灵感是创作的源泉&#xff0c;也是作品的灵魂所在。工作中缺少灵感&#xff0c;这是每个设计师都会经历的苦恼&#xff0c;那当我们灵感匮乏的时候&#xff0c;该怎么办呢&#xff1f;别急&#xff0c;即时设计、SurfCG、Lapa…

基于sivaco设计仿真PT型IGBT和NPT型IGBT结构

本项目基于使用仿真软件SIVACO来仿真研究PT型和NPT型的IGBT结构特点&#xff0c;并且通过仿真研究对于不同的掺杂浓度、沟道宽度等对器件的特性产生不同的影响。 资料获取到咸&#x1f41f;&#xff1a;xy591215295250 \\\或者联系wechat 号&#xff1a;comprehensivable &…

HTML(15)——盒子模型

盒子模型组成 内容区域 -width&height内边距-padding &#xff08;出现在内容与盒子边缘之间&#xff09;边框线-border外边距-margin &#xff08;出现在盒子外面&#xff09; div { width: 200px; height: 200px; background-color: rgb(85, 226, 193); padding: 20px; …

未来一周比特币价格及数字货币市场预测

荷月的比特币市场就像过山车一样&#xff0c;仅仅六月下旬就跌去-12%&#xff0c;本周更是暴跌-6%&#xff0c;至 58,378美元。在这种市场表现&#xff0c;应有的踩踏如期而至。德国政府今日宣布再出售750 比特币的行为继续打击多头&#xff0c;但是小编认为这恰恰预示着市场可…

【Linux进阶】基础IO函数详解

1.函数open和openat 调用open或openat函数可以打开或创建一个文件。 #include <fcntl.h> int open(const char *path, int ofag, ... /* mode_t mode */);int openat (int fd, const char *path, int oflag, ... /* mode_t mode */); 我们将最后一个参数写为...&#x…

突然!某大客户核心凌晨突然崩溃....

这几天实在太忙&#xff0c;刚弄完文档。业务线的同事就找到我&#xff0c;说一个银行客户的核心系统昨晚出了故障&#xff0c;还没找到原因&#xff0c;希望能帮忙分析下。 从提供的信息来看是业务跑任务报错&#xff0c;遇到了Oracle-00600和ora-07445 错误。 Doing block re…

机器学习-数据预处理-聚类-回归-分类-单车数据集

机器学习-数据预处理-聚类-回归-分类-单车数据集 前言一、数据预处理1. 导入数据集2. 数据预处理3. 处理缺失值4. 生成特征用于后续进一步的分析 二、数据分布可视化1. 骑行时长分布2. 起始站和终点站分布可视化3. 高峰期与非高峰期骑行频次分布 三、聚类分析1. K-means聚类 四…

Vue2 - 首页登录实现随机验证码组件的封装与实现详解(详细的注释及常见问题汇总)

在网站首页等登录时,随机验证码在现代网络应用中扮演着重要的安全角色。为了帮助开发者轻松集成和使用随机验证码功能,本文将介绍如何利用 Vue.js 2 封装一个简单而功能强大的随机验证码组件。让你能够快速理解并应用这一组件到你的项目中。 一、解决方案 本文提供了完美便捷…