算法通过村第五关-队列和Hash青铜笔记|队列和Hash

news2024/11/16 16:00:21

文章目录

  • 前言
  • 1. Hash基础
    • 1.1 Hash的概念和基本特征
    • 1.2 碰撞处理方法
      • 1.2.1 开放地址法
      • 1.1.2 链地址法
  • 2. 队列的基础
    • 2.1 队列的概念和基本特征
    • 2.2 队列的实现
  • 总结


前言


提示:幸福的秘密是尽量扩大自己的兴趣范围对感兴趣的人和物尽可能的友善 --波特兰·罗素

谈完栈,我们今天就来聊聊队列和Hash,这也是很常见的数据结构,尤其是Hash。

1. Hash基础

哈希(Hash)也称为是散列表,就是把任意长度的输入,通过散列算法,变成固定长度的输出,这个输出也称为散列值。

1.1 Hash的概念和基本特征

很多人对于映射这个东西,很难理解,为啥就说Hash的访问时间复杂度就是O(1)?我们今天就来谈谈这个东西是真么回事。🥰

假设我们现在要将1-15存放如数组长度为7的array中,我们应该怎么存储呢?我给你一个公式:

index = number % 7

这个时候我们先将1-6出入的时候,看图:
在这里插入图片描述
这里没有问题吧,那我们接着存储7-17,如下图:
在这里插入图片描述
不是还有14、15呢,是这样的,看图:
在这里插入图片描述
这个时候我们会发现有些数据被存放在同一个位置了,我们后面再讨论这个问题,接下来我们看看,我们将如何取值?

假如我要测试13在不在结构,我是不是还需要上面的公式,计算一下index = 13 % 7 6 ,我么你直接访问array[6]这个位置就可以拿到结果,然后返回true;

同样的我想知道20在不在呢?也是用上面的公式,即 index = 20 % 7 6 这是我们再访问array[6]这个位置,但是这里面只有6和13 没有20,我们就返回 false。

理解了这个例子我们就理解了Hash是如何做最基本的映射的,还有就是说问什么它的访问时间复杂度为O(1)。

1.2 碰撞处理方法

上面的例子重构,我们发现有些Hash中很多位置要存储两个甚至多个元素,很明显单纯的数组是行不通的,这种两个不同的输入值,根据统一的散列函数计算出的散列值相同的现象就叫做碰撞啦

那我我们要怎么解决呢?常见的方法:

  • 开放地址法(Java中的Threadlocal)
  • 链地址法(Java里的ConcurrentHashMap)
  • 再哈希法(布隆过滤器)
  • 建立公共溢出区

后面两种方法目前不常见,我们重点看看前面的两个。

1.2.1 开放地址法

开放地址法就是一旦发生冲突,就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总是可以找到的,并记录存入的。
在这里插入图片描述
如上图:存储7,8,9的时候,对于7的话,可以直接存储在索引的位置0,8应该存储在1的位置,但是现在满了怎么办呢?就继续向后寻找,找到3的位置是空,所以8存储在3的位置上,同理9的位置也是这样。

这里你是否有一个疑问:这样的话鸠占鹊巢的方法会不会引起混乱?不如再存3和6的话,本来自己的位置好好的,但是现在却被占用了,我们该怎么处理呢?这个问题Java里的ThreadLocal会有答案,感兴趣的话可以学习一下。ThreadLocal有一个专门存储元素的ThreadLocalMap,每次在get和set元素的时候,会将目标位置前后的空间搜索一下,将标记为null的位置回收掉,这样大部分不用的位置就收回了。还有一点Hash处理该问题的过程也是非常复杂,设计弱引用等等,这些也都是Java技术面试的高频考点。

1.1.2 链地址法

将哈希表的每个单元作为链表的头节点,所有的哈希地址为i的元素构成一个同义词链表。即发生冲突时就把该关键词链在该单元为头节点的链表的尾部。比如:
在这里插入图片描述
这种处理的方法问题在于处理起来的代价有点高,要落地还需要很多优化,比如在Java里ConcurrentHashMap中就使用了这种方式,其中涉及元素尽量均匀,访问和操作速度要快,线程安全,扩容等等。

我们来看看这个Hash结构,限免的图有两处很严重的错误,麻烦找出来:
在这里插入图片描述
首先数组的长度必须时2的n次幂,长度9,明显有问题,然后Entry的个数不能大于数组长度的75%,如果大于就要触发扩容机制,这里明显发育75%,正确的呢?应该是下面这样:
在这里插入图片描述
记住一下两点:

  1. 数组的长度即是2的n次幂
  2. Size不是超过数组长度的75%

顺便说一下,Hash的实现原理是先找到存放数组的下标,如果是空着就存进去,如果不是空的就判断key值是否一样,如果一样就替换掉,如果不一样就一链表的形式存储在后面(从JDK8开始,根据元素数量选择使用链表是红黑树存储)

2. 队列的基础

2.1 队列的概念和基本特征

队列的特点是节点的排序次序和出队次序按照入队时间先后确定,也就是常说的先进先出呗。【FIFO】。队列的实现有两种方法(形式),基于数组的实现和基于链表的实现,由于链表的长度可以随时改变,实现起来也比较简单。相反基于数组就比较麻烦,这里后面再来实现,我们先看一下基于链表的实现。

2.2 队列的实现

基于链表实现队列还是比较好处理的,只要在尾部插入元素,在front删除元素就可以了。

public class LinkQueue {
    private Node front;
    private Node rear;
    private int size;

    public LinkQueue() {
        // 带头尾节点的遍历
        front = new Node(0);
        rear = new Node(0);
    }

    /**
     * 入队
     */
    public void push(int value) {
        Node newNode = new Node(value);
        Node temp = front;
        while(temp.next != null){
            temp = temp.next;
        }
        temp.next = newNode;
        rear = newNode;
        size++;
    }

    /**
     * 出队
     */
    public int pull() {
        if (front.next == null){
            throw new IllegalStateException("front.next is null");
        }
        Node firstNode = front.next;
        front.next = firstNode.next;
        size--;
        return firstNode.data;
    }

    /**
     * 遍历队列
     */
    public void traverse() {
        Node temp = front.next;
        while (temp.next != null){
            System.out.println(temp.data + "\t");
            temp = temp.next;
        }
    }

    static class Node {
        public int data;
        public Node next;

        public Node(int data) {
            this.data = data;
        }
    }

    //测试main方法
    public static void main(String[] args) {
        LinkQueue linkQueue = new LinkQueue();
        linkQueue.push(1);
        linkQueue.push(2);
        linkQueue.push(3);
        System.out.println("第一个出队的元素为:" + linkQueue.pull());
        System.out.print("队列中的元素为:");
        linkQueue.traverse();
    }
}


总结

提示:对Hash的理解和认识,掌握解决哈希冲突的两种方法,使用链表实现对列。

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

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

相关文章

【人工智能】—_深度神经网络、卷积神经网络(CNN)、多卷积核、全连接、池化

深度神经网络、卷积神经网络(CNN)、多卷积核、全连接、池化) 文章目录 深度神经网络、卷积神经网络(CNN)、多卷积核、全连接、池化)深度神经网络训练训练深度神经网络参数共享 卷积神经网络(CNN)卷积多卷积…

7.(Python数模)消防站的选址问题

Python解决消防站的选址问题 原文参考该博文 问题描述 源代码 import pulp # 导入 pulp 库# 主程序 def main():# 问题建模:"""决策变量:x(j) 0, 不选择第 j 个消防站x(j) 1, 选择第 j 个消防站, j1,8目标函数:min fx …

【C++心愿便利店】No.4---C++初谈类和对象

文章目录 前言一、面向过程和面向对象初步认识二、类的引用三、类的定义四、类的访问限定符及封装五、类的作用域六、类的实例化七、类对象模型八、this指针 前言 👧个人主页:小沈YO. 😚小编介绍:欢迎来到我的乱七八糟小星球&…

PVZ紫卡植物排名

前言 此文章为“植物大战僵尸”专栏中的第003刊(2023年9月第一刊)。 无名版中有很多紫卡植物,分别是忧郁菇、玉米加农炮、猫尾草、机枪射手、地刺王、冰西瓜投手、双子向日葵、吸金菇。 提示:双子向日葵(向日葵的升…

300行代码,教你用Python写个飞机大战

闲赋在家,甚是无聊,便萌发了研究经典小游戏:飞机大战的念头,想必大家可能玩过微信的这款小游戏,给我的感觉是这款游戏怎么可以做得这么好呢,操作简单,容易上手,简直是“老少皆宜”啊…

2023-09-02 LeetCode每日一题(最多可以摧毁的敌人城堡数目)

2023-09-02每日一题 一、题目编号 2511. 最多可以摧毁的敌人城堡数目二、题目链接 点击跳转到题目位置 三、题目描述 给你一个长度为 n ,下标从 0 开始的整数数组 forts ,表示一些城堡。forts[i] 可以是 -1 ,0 或者 1 ,其中&…

Android 1.1 背景相关与系统架构分析

目录 1.1 背景相关与系统架构分析 分类 Android 基础入门教程 1.Android背景与当前的状况 2.Android系统特性与平台架构 系统特性: 平台架构图: 架构的简单理解: 3.本节小结: 1.1 背景相关与系统架构分析 分类 Android 基础…

C++ 分割字符串数据

使用stringstream流&#xff08;已验证&#xff09; 引入头文件 #include <sstream> 功能实现&#xff1a; string keyValue "WTH01#WTH02#WTH03#WTH04#WTH05" string keys[6] { "" }; stringstream is(keyValue); string temp; int index 0;…

stable diffusion实践操作-采样sample

系列文章目录 stable diffusion实践操作 文章目录 系列文章目录前言一、采样是什么&#xff1f;1.1 SD原理图1.2 SD中采样工作流程1.3 SD重复预测采样结果1.4 SD中采样方法列表1.4 SD中采样方法功能总结1.5 SD中常用采样方法 二、 SD中常用采样方法对比2.1 二次元-第一组2.1.…

YOLOv5训练自己的数据集并测试(以及踩坑记录)

YOLOv5是一个非常流行的图像识别框架&#xff0c;这里介绍一下使用YOLOv5给自己的数据集进行训练和测试 官方介绍文档&#xff1a;YOLOv5官方文档 基本流程&#xff1a; 下载必要的库和包&#xff0c;以及yolov5框架自制数据集&#xff1a;收集图像、视频数据&#xff0c;la…

从零开发JavaWeb入门项目--十天掌握

原文网址&#xff1a;从零开发JavaWeb入门项目--十天掌握_IT利刃出鞘的博客-CSDN博客 简介 这是一个靠谱的JavaWeb入门项目实战&#xff0c;名字叫蚂蚁爱购。从零开发项目&#xff0c;视频加文档&#xff0c;十天就能学会开发JavaWeb项目&#xff0c;教程路线是&#xff1a;搭…

Super Resolve Dynamic Scene from Continuous Spike Streams论文笔记

摘要 近期&#xff0c;脉冲相机在记录高动态场景中展示了其优越的潜力。不像传统相机将一个曝光时间内的视觉信息进行压缩成像&#xff0c;脉冲相机连续地输出二的脉冲流来记录动态场景&#xff0c;因此拥有极高的时间分辨率。而现有的脉冲相机重建方法主要集中在重建和脉冲相…

Windows 重新映射 CapsLock 大写锁定到 Ctrl

Windows 重新映射 CapsLock 大写锁定到 Ctrl 本要点中的这些方法适用于我的美国键盘布局。我不确定其他布局。如果出现问题&#xff0c;请恢复您的更改&#xff1b;删除您创建的注册表项&#xff08;并重新启动&#xff09;。 强烈推荐 方法5 ctrl2cap&#xff0c;因为不会影…

代码随想录第35天|860.柠檬水找零 , 406.根据身高重建队列(很多细节点注意一下),452. 用最少数量的箭引爆气球

860.柠檬水找零 思路比较简单 class Solution {public boolean lemonadeChange(int[] bills) {//然后向你付 5 美元、10 美元或 20 美元//如果收到5&#xff0c;直接收下//如果收到10&#xff0c;需要付回去5//如果收到20&#xff0c;需要付回去105或者555//开始时我手上拥有…

java基础-----第八篇

系列文章目录 文章目录 系列文章目录一、Java类加载器二、双亲委托模型 一、Java类加载器 JDK自带有三个类加载器&#xff1a;bootstrap ClassLoader、ExtClassLoader、AppClassLoader。 BootStrapClassLoader是ExtClassLoader的父类加载器&#xff0c;默认负责加载%JAVA_HOME…

Ops实践 | 国产化KylinOS系统中快速部署企业内部高性能DNS服务器、时间同步服务器 (精选)...

各位看友&#xff0c;由于微信公众号推送机制改变&#xff0c;现在需要设置为星标才能收到的本公众号推送消息哟。关注回复【学习交流群】加入【安全开发运维】答疑交流群 请朋友们【多多点击文中的广告】&#xff0c;支持作者更新更多文章。 目录: 本文为作者原创文章&#xf…

c++数据结构之 队列

c数据结构 --- 队列 队列的特点队列的相关概念&#xff1a;队列的操作&#xff1a;队列的分类&#xff1a;演示例子简单的例子例子2、循环队列的C实现 队列的特点 队列&#xff08;Queue&#xff09;与栈一样&#xff0c;是一种线性存储结构&#xff0c;它具有如下特点&#x…

学习振弦采集模块的开发基本原理

飞讯教学篇&#xff1a;学习振弦采集模块的开发基本原理 振弦采集模块是一种用于测量物体振动、形变、压力等物理量的电子设备。它通过测量物体的振动变化&#xff0c;可以得出物体在不同条件下的动态特性&#xff0c;对于工程设计、科学研究、医学检测等领域都有广泛应用。本…

代码随想录笔记--二叉树篇

1--递归遍历 1-1--前序遍历 前序遍历&#xff1a;根→左→右&#xff1b; #include <iostream> #include <vector>struct TreeNode {int val;TreeNode *left;TreeNode *right;TreeNode() : val(0), left(nullptr), right(nullptr) {}TreeNode(int x) : val(x), le…

6400万美元:苹果与SpaceX达成合作协议,推进苹果 SOS 卫星服务

根据最新披露的文件&#xff0c;苹果卫星服务提供商Globalstar近期与马斯克旗下的SpaceX达成一项重要合作协议&#xff0c;向SpaceX支付了6400万美元&#xff0c;用于在2023-2025年期间发射卫星&#xff0c;以进一步扩展苹果iPhone系列的SOS卫星服务。 这项卫星服务的主要目的是…