数据结构(Java实现)-Map和Set

搜索树
概念
二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:
若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
它的左右子树也分别为二叉搜索树


二叉搜索树的实现
建立基本的节点
在这里插入图片描述


在搜索树中查找 key,如果找到,返回 key 所在的结点,否则返回 null
在这里插入图片描述


操作-插入
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
利用插入操作建立一颗搜索树
在这里插入图片描述
在这里插入图片描述


删除元素
分为三种情况
前两种情况

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
自己画图分析,更好理解
第3种情况
在这里插入图片描述
上述的意思是找到右分支的最左边的元素target,将要删除的元素用target替换
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
测试
在这里插入图片描述

运行结果如下
在这里插入图片描述


TreeMap 和 TreeSet 即 java 中利用搜索树实现的 Map 和 Set;实际上用的是红黑树


Map和set是一种专门用来进行搜索的容器或者数据结构,其搜索的效率与其具体的实例化子类有关。
以前常见的搜索方式有:

  1. 直接遍历,时间复杂度为O(N),元素如果比较多效率会非常慢
  2. 二分查找,时间复杂度为O(logN) ,但搜索前必须要求序列是有序的

上述排序比较适合静态类型的查找,即一般不会对区间进行插入和删除操作了
而现实中的查找比如:

  1. 根据姓名查询考试成绩
  2. 通讯录,即根据姓名查询联系方式
  3. 不重复集合,即需要先搜索关键字是否已经在集合中

可能在查找时进行一些插入和删除的操作,即动态查找
Map和Set是一种适合动态查找的集合容器。


模型
一般把搜索的数据称为关键字(Key),和关键字对应的称为值(Value),将其称之为Key-value的键值对,所以模型会有两种:

  1. 纯 key 模型,比如:
    有一个英文词典,快速查找一个单词是否在词典中
    快速查找某个名字在不在通讯录中
  2. Key-Value 模型,比如:
    统计文件中每个单词出现的次数,统计结果是每个单词都有与其对应的次数:<单词,单词出现的次>
    梁山好汉的江湖绰号:每个好汉都有自己的江湖绰号

Map中存储的就是key-value的键值对,Set中只存储了Key。


Map 的使用
Map是一个接口类,该类没有继承自Collection,该类中存储的是<K,V>结构的键值对,并且K一定是唯一的,不能重复。
Map 的常用方法说明
在这里插入图片描述

在这里插入图片描述
上述说明,相同的key的情况下,会更新value
在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


Set 的说明
Set与Map主要的不同有两点:Set是继承自Collection的接口类,Set中只存储了Key。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述


注意:

  1. Set是继承自Collection的一个接口类
  2. Set中只存储了key,并且要求key一定要唯一
  3. TreeSet的底层是使用Map来实现的,其使用key与Object的一个默认对象作为键值对插入到Map中的
  4. Set最大的功能就是对集合中的元素进行去重
  5. Set中的Key不能修改,如果要修改,先将原来的删除掉,然后再重新插入
  6. TreeSet中不能插入null的key
    在这里插入图片描述

哈希表
顺序结构以及平衡树中,元素关键码与其存储位置之间没有对应的关系,因此在查找一个元素时,必须要经过关键码的多次比较。顺序查找时间复杂度为O(N),平衡树中为树的高度,即O( ),搜索的效率取决于搜索过程中元素的比较次数。
理想的搜索方法:可以不经过任何比较,一次直接从表中得到要搜索的元素。 如果构造一种存储结构,通过某种函数(hashFunc)使元素的存储位置与它的关键码之间能够建立一一映射的关系,那么在查找时通过该函数可以很快找到该元素。

当向该结构中:
插入元素
根据待插入元素的关键码,以此函数计算出该元素的存储位置并按此位置进行存放
搜索元素
对元素的关键码进行同样的计算,把求得的函数值当做元素的存储位置,在结构中按此位置取元素比较,若关键码相等,则搜索成功

该方式即为哈希(散列)方法,哈希方法中使用的转换函数称为哈希(散列)函数,构造出来的结构称为哈希表(HashTable)(或者称散列表)


在这里插入图片描述


按照上述哈希方式,向集合中插入元素44,会出现什么问题?
在这里插入图片描述


不同关键字通过相同哈希哈数计算出相同的哈希地址,该种现象称为哈希冲突或哈希碰撞。
由于我们哈希表底层数组的容量往往是小于实际要存储的关键字的数量的,这就导致一个问题,冲突的发生是必然的,但我们能做的应该是尽量的降低冲突率。


冲突-避免-哈希函数设计
引起哈希冲突的一个原因可能是:哈希函数设计不够合理。 哈希函数设计原则:

哈希函数的定义域必须包括需要存储的全部关键码,而如果散列表允许有m个地址时,其值域必须在0到m-1之间
哈希函数计算出来的地址能均匀分布在整个空间中
哈希函数应该比较简单


常见哈希函数

  1. 直接定制法–(常用)
    取关键字的某个线性函数为散列地址:Hash(Key)= A*Key + B 优点:简单、均匀 缺点:需要事先知道关键字的分布情况 使用场景:适合查找比较小且连续的情况
    如下
    在这里插入图片描述

在这里插入图片描述


  1. 除留余数法–(常用)
    设散列表中允许的地址数为m,取一个不大于m,但最接近或者等于m的质数p作为除数,按照哈希函数:Hash(key) = key% p(p<=m),将关键码转换成哈希地址

冲突-避免-负载因子调节
在这里插入图片描述


负载因子和冲突率的关系粗略演示
在这里插入图片描述
已知哈希表中已有的关键字个数是不可变的,那我们能调整的就只有哈希表中的数组的大小。


冲突-解决
解决哈希冲突两种常见的方法是:闭散列和开散列
闭散列:也叫开放定址法,当发生哈希冲突时,如果哈希表未被装满,说明在哈希表中必然还有空位置,那么可以把key存放到冲突位置中的“下一个” 空位置中去。那如何寻找下一个空位置呢?


  1. 线性探测:从发生冲突的位置开始,依次向后探测,直到寻找到下一个空位置为止。
    在这里插入图片描述

二次探测
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
闭散列最大的缺陷就是空间利用率比较低


冲突-解决-开散列/哈希桶
开散列法又叫链地址法(开链法),首先对关键码集合用散列函数计算散列地址,具有相同地址的关键码归于同一子集合,每一个子集合称为一个桶,各个桶中的元素通过一个单链表链接起来,各链表的头结点存储在哈希表中。

在这里插入图片描述
从上图可以看出,开散列中每个桶中放的都是发生哈希冲突的元素。
开散列,可以认为是把一个在大集合中的搜索问题转化为在小集合中做搜索了。


哈希桶的实现
在这里插入图片描述
放入数据 :put
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
结果如下:

在这里插入图片描述


取数据 get
在这里插入图片描述

在这里插入图片描述


哈希表泛型的实现
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在没有重写hashcode之前,我们看到,两个对象的hashcode的值是不一样的
在这里插入图片描述
当我们将id看作身份证件时,那么两者的hanshcode应该是相同的,因此,这里我们改写hashcode方法
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述


通常意义下,我们认为哈希表的插入/删除/查找时间复杂度是O(1) 。


可以利用hashSet进行去重,去掉重复的数据
在这里插入图片描述


在这里插入图片描述

在这里插入图片描述


在这里插入图片描述

将新的节点和旧的节点放到一个hashmap中,用来搭建新旧节点之间的联系;
在这里插入图片描述
在复制的过程中,val值可以直接复制到新的节点中,next和random的值可以通过以下方式确定
map.get(cur).next=map.get(cur.next)
map.get(cur).random=map.get(cur.random)
在这里插入图片描述
在这里插入图片描述


在这里插入图片描述

在这里插入图片描述


在这里插入图片描述
在这里插入图片描述


在这里插入图片描述


在这里插入图片描述

class Test23{public static List<String> topKFrequent(String[] words, int k) {//1、每个单词出现的次数Map<String,Integer> map = new HashMap<>();for(String s : words) {if(map.get(s) == null) {map.put(s,1);}else {//以前有int val = map.get(s);map.put(s,val+1);}}//2、已经统计完毕,创建小根堆PriorityQueue<Map.Entry<String,Integer>> minHeap = new PriorityQueue<>(new Comparator<Map.Entry<String, Integer>>() {@Overridepublic int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {if(o1.getValue().compareTo(o2.getValue()) == 0) {return o2.getKey().compareTo(o1.getKey());//根据字母顺序 变成大根堆}return o1.getValue().compareTo(o2.getValue());}});//3.遍历mapfor (Map.Entry<String,Integer> entry: map.entrySet()) {if(minHeap.size()<k){minHeap.offer(entry);}else{//小根堆已满Map.Entry<String,Integer> top=minHeap.peek();if(top.getValue().compareTo(entry.getValue())==0){//频率一样的情况下,判断key值,key小的入if(top.getKey().compareTo(entry.getKey())>0){//entry 进minHeap.poll();minHeap.offer(entry);}}else{//val值不等,只有大于堆顶元素的频率,才有资格入堆if(top.getValue().compareTo(entry.getValue())<0){minHeap.poll();minHeap.offer(entry);}}}}//4 将小根堆中的元素拿出,放到一个集合里,之后逆置List<String> list=new ArrayList<>();for (int i = 0; i <k; i++) {String s=minHeap.poll().getKey();list.add(s);}Collections.reverse(list);return list;}public static void main(String[] args) {String[] strings={"a","b","c","c"};List<String> ret=topKFrequent(strings,3);System.out.println(ret);}}

在这里插入图片描述


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

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

相关文章

快速上手GIT命令,现学也能登堂入室

系列文章目录 手把手教你安装Git&#xff0c;萌新迈向专业的必备一步 GIT命令只会抄却不理解&#xff1f;看完原理才能事半功倍&#xff01; 快速上手GIT命令&#xff0c;现学也能登堂入室 系列文章目录一、GIT HELP1. 命令文档2. 简要说明 二、配置1. 配置列表2. 增删改查3. …

python自动化测试-自动化基本技术原理

1 概述 在之前的文章里面提到过&#xff1a;做自动化的首要本领就是要会 透过现象看本质 &#xff0c;落实到实际的IT工作中就是 透过界面看数据。 掌握上面的这样的本领可不是容易的事情&#xff0c;必须要有扎实的计算机理论基础&#xff0c;才能看到深层次的本质东西。 …

【C++深入浅出】类和对象上篇(类的基础、类的模型以及this指针)

目录 一. 前言 二. 面向对象与面向过程 2.1 面向过程 2.2 面向对象 三. 类的基础知识 3.1 类的引入 3.2 类的定义 3.3 成员变量的命名规则 3.4 封装 3.5 类的访问限定符 3.6 类的作用域 3.7 类的实例化 四. 类的对象模型 4.1 类对象的大小 4.2 类对象的存储方式 …

从Matrix-ResourceCanary看内存快照生成-ForkAnalyseProcessor(2)

不同于LeakCanary,在Matrix中,主要是通过Resource Canary来监控内存泄漏问题的,且监听的泄漏对象只支持Activity,官方说明如下: 结合分析LeakCanary的经验可知,要实现Activity内存泄漏监听,总体上应该要实现两大功能: Activity生命周期监控查找泄漏对象并得到GC Root P…

【Apollo学习笔记】——规划模块TASK之RULE_BASED_STOP_DECIDER

文章目录 前言RULE_BASED_STOP_DECIDER相关配置RULE_BASED_STOP_DECIDER总体流程StopOnSidePassCheckClearDoneCheckSidePassStopIsPerceptionBlockedIsClearToChangeLaneCheckSidePassStopBuildStopDecisionELSE:涉及到的一些其他函数NormalizeAngleSelfRotate CheckLaneChang…

macOS上制作arm64的jdk17镜像

公司之前一直用的openjdk17的镜像&#xff0c;docker官网可以直接下载&#xff0c;但是最近对接的一个项目&#xff0c;对方用的是jdk17&#xff0c;在对接的时候有加解密异常的问题&#xff0c;为了排查是不是jdk版本的问题&#xff0c;需要制作jdk17的镜像。docker官网上的第…

iOS开发Swift-4-IBAction,group,音乐播放器-木琴App

1.使用素材创建木琴App的UI。 2.连接IBAction。 其余按钮直接拖拽到play里边。 当鼠标置于1处时2处显示如图&#xff0c;表示成功。当用户按下任一按钮都会触发play中的内容。 3.将7个按钮的View中的Tag值分别调为1、2、3、4、5、6、7. 4.将音频文件拖入项目文件中。 Create gr…

Leetcode19 删除链表指定节点

思路&#xff1a;用列表保存链表&#xff0c;然后分情况讨论。 class Solution:def removeNthFromEnd(self, head, n: int):node_list[head]while head.next:headhead.nextnode_list.append(head)remove_loclen(node_list)-n#要移除的位置if len(node_list)1:return Noneif re…

Python小知识 - 一个简单的Python爬虫实例

一个简单的Python爬虫实例 这是一个简单的Python爬虫实例&#xff0c;我们将使用urllib库来下载一个网页并解析它。 首先&#xff0c;我们需要安装urllib库&#xff1a; pip install urllib接下来&#xff0c;我们来看看如何使用urllib库来下载一个网页&#xff1a; import url…

运行命令出现错误 /bin/bash^M: bad interpreter: No such file or directory

在系统上运行一个 Linux 的命令的时候出现下面的错误信息&#xff1a; -bash: ./build.sh: /bin/bash^M: bad interpreter: No such file or directory 这个是在 Windows 作为 WSL 的时候出的错误。 原因和解决 出现问题的原因在于脚本在 Windows 中使用的回车换行和 Linux …

从零开始搭建AI网站(6):如何使用响应式编程

响应式编程&#xff08;Reactive Programming&#xff09;是一种编程范式&#xff0c;旨在处理异步数据流和事件流。它通过使用观察者模式和函数式编程的概念&#xff0c;将数据流和事件流抽象为可观察的序列&#xff0c;然后通过操作这些序列来实现各种功能。 在响应式编程中…

Navicat连接数据库报2003错误解决办法

是防火墙还没有开启 查看防火墙管理的端口 设置3306防火墙开启&#xff0c;重载防火墙 连接成功

睿趣科技:抖音开小店大概多久可以做起来

随着移动互联网的快速发展&#xff0c;社交媒体平台成为了人们分享生活、交流信息的主要渠道之一。在众多社交平台中&#xff0c;抖音以其独特的短视频形式和强大的用户粘性受到了广泛关注。近年来&#xff0c;越来越多的人通过在抖音上开设小店来实现创业梦想&#xff0c;这种…

XSS漏洞及分析

目录 1.什么是xss漏洞 1&#xff09;存储型XSS漏洞 2&#xff09;反射型XSS漏洞 3&#xff09;DOM型XSS漏洞 2.什么是domcobble破环 3.案例一 1&#xff09;例题链接 2&#xff09;代码展示 3&#xff09;例题分析 4.案例二 1&#xff09;例题链接 2&#xff09;代…

【ArcGIS Pro二次开发】(65):进出平衡SHP转TXT、TXT转SHP

最近一个小伙伴提了这么一个需求&#xff0c;需要把TXT和SHP进行互转。 这种TXT文件其实遇到了好几个版本&#xff0c;都有一点小差异。之前已经做过一个TXT转SHP的工具&#xff0c;但好像不适用。于是针对这个版本&#xff0c;做了互转的2个工具。 【SHP转TXT】 一、要实现的…

用于设计和分析具有恒定近心点半径的低推力螺旋轨迹研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

【LeetCode】剑指 Offer <二刷>(3)

目录 题目&#xff1a;剑指 Offer 06. 从尾到头打印链表 - 力扣&#xff08;LeetCode&#xff09; 题目的接口&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 过啦&#xff01;&#xff01;&#xff01; 题目&#xff1a;剑指 Offer 07. 重建二叉树 - 力扣&#xf…

A 股个股资金流 API 数据接口

A 股个股资金流 API 数据接口 全量股票资金流数据&#xff0c;全量A股数据&#xff0c;最长30日历史数据 1. 产品功能 支持所有A股资金流数据查询&#xff1b;每日定时更新数据&#xff1b;支持多达 30 日历史数据查询&#xff1b;超高的查询效率&#xff0c;数据秒级返回&am…

探索树堆Treap和红黑树的优势和劣势

探索树堆Treap和红黑树的优势和劣势 一、背景知识二、树堆&#xff08;Treap&#xff09;的介绍三、红黑树&#xff08;RB-Tree&#xff09;的介绍四、树堆&#xff08;Treap&#xff09;与红黑树&#xff08;RB-Tree&#xff09;的比较总结 博主简介 &#x1f4a1;一个热爱分享…

【Mysql问题集锦】:Can‘t create table ‘#sql-58d7_431d‘ (errno: 28)

问题描述&#xff1a; 问题原因&#xff1a; OSError: [Errno 28] No space left on device&#xff0c;即&#xff1a;磁盘空间不足&#xff0c;无法创建文件。因此&#xff0c;导致Mysql无法执行SQL语句。 问题解法&#xff1a; Step 1&#xff0c;查看有哪些目录占用了大量…