哈希表

Redis的五大数据类型

徘徊边缘 提交于 2020-01-23 22:11:38
Redis支持5种数据类型:String(字符串),Hash(哈希),List(列表),Set(集合),Zset(有序集合) 1.String string是redis最基本的数据类型。一个key对应一个value。 string是二进制安全的,也就是说redis的string可以包含任何数据,比如jpg图片或者序列化的对象。 string类型是redis最基本的数据类型,string类型的值最大能存储512MB。 理解:string就像是Java中的map一样,一个key对应一个value 在以上实例中我们使用了 SET 和 GET 命令,键为 hello,值为world。 序号 命令及描述 1 SET key value 设置指定 key 的值 2 GET key获取指定 key 的值。 3 GETRANGE key start end返回 key 中字符串值的子字符 4 GETSET key value将给定 key 的值设为 value ,并返回 key 的旧值(old value)。 5 GETBIT key offset对 key 所储存的字符串值,获取指定偏移量上的位(bit)。 6 MGET key1 [key2…]获取所有(一个或多个)给定 key 的值。 7 SETBIT key offset value对 key 所储存的字符串值,设置或清除指定偏移量上的位

漫画 | 什么是散列表(哈希表)?

谁说我不能喝 提交于 2020-01-23 13:39:46
创建与输入数组相等长度的新数组,作为直接寻址表。两数之和的期望是Target,将Target依次减输入数组的元素,得到的值和直接寻址表比较,如果寻址表存在这个值则返回;如果不存在这个值则将输入数组中的元素插入寻址表,再进行输入数组中的下一个元素。 再进一步优化可以将输入数组直接作为直接寻址表,控制对应的下标就好,代码如下: Code:直接寻址表 class Solution { public int[] twoSum(int[] nums, int target) { for (int i = 1; i < nums.length; i++) { int temp = target - nums[i]; for (int j = 0; j < i; j++) { if (temp == nums[j]) return new int[]{j, i}; } } return null; } } 动画:直接寻址表 数组里面每一个槽位放的是8个字节,用于一个指向外部类的引用。这个外部类可以是链表对象,也可以是红黑树对象,都可以存一个或者一个以上的元素,也可以是空链表或空树。散列表在某种意义上需要的数组空间可以比直接寻址表要少的很多。 散列函数是将所有元素的键转换为自然数,自然数的数集是{0,1,2,……}。 如果所有元素的键是正整数,最常用的方法是求模(除留余数法)

HashMap以及源码详解

天涯浪子 提交于 2020-01-23 10:28:30
HashMap实现接口以及继承类 实现了Map,Cloneable,Serializable接口,继承自AbstractMap类。 允许 null 值和 null 键,无序,不允许重复的集合 HashMap底层结构 HashMap底层接口是哈希表,也就是所谓的散列表。 简单介绍一下散列表,散列表的出现是为了解决链表和数组的缺陷,链表增删快,查询慢,数组查询快,增删慢。而散列表基于数组和列表进行演变,使得查询和增删的速度都非常快。 散列表的结构如下。 hashMap中的散列表是用数组+链表+红黑树去实现的 。 好的散列方式,会把数据散列到不同的位置,哪怕散列到同一个位置(这就是所谓的 哈希冲突 ),我们可以把它链起来变成链表(Java采用 链地址法 ),只要这个链表足够的短,我们就可以最快的查询数据,因为遍历两三个节点的时间非常短,近似于O(1)。 当链表足够长( 链表长度 >= 8)并且,节点足够多(节点数 >= 64)的时候,我们就把当前的链表变成红黑树。 (为什么节点 >=8 才变成红黑树,<=6变成链表? 因为根据泊松分布,当节点树大于等于 8 的时候,红黑树查询会比链表查询要快,而当节点数小于等于 6 的时候,会链表查询回避红黑树要快。7的时候是相当。) HashMap常用方法以及源码解析 简单介绍以下变量以及初始值: HashMap的最大容量(MAXIMUM

2.8python如何实现LRU环存方案

点点圈 提交于 2020-01-22 20:00:48
题目描述: LRU是 Least Recently Used 的缩写,指“最近最少使用”,LRU环存就是使用这种原理实现,简单地说就是 缓存一定量的数据,当超过设定的阈值时就把一些过期的数据删除掉 。常用于页面置换算法,是虚拟页式存储管理中常用的算法。 思路: 使用两个数据结构实现一个LRU环存: (1) 使用双向链表实现的队列,队列的最大容量为缓存的大小。在使用的过程中,把 最近使用的页面移动到队列头,最近没有使用的页面将被放在队列尾的位置 ; (2) 使用一个哈希表,把页号作为键,把缓存在队列中的结点的地址作为值;(不是很理解为什么要用一个哈希表,下面代码中未使用哈希表,仅是使用了一个双向的队列) 当引用一个页面时, 如果 所需的页面在内存中,只需要把这个页对应的结点移动到队列的前面。 如果 所需要的页面不在内存中,此时需要把这个页面加载到内存中。简单地说,就是 将一个新结点添加到队列的前面(最近使用) ,并在哈希表中更新相应的结点地址。如果队列是满的,那么就从队列尾部移除一个结点(队尾表示距离现在久远),并将新结点添加到队列的前面( 队头表示现在,队尾表示过去 )。 代码实现: #!/usr/bin/env python3 # -*- coding: utf-8 -*- # @Time : 2020/1/22 16:53 # @Author : buu # @Software

模拟散列表

走远了吗. 提交于 2020-01-22 18:15:53
将一个大的空间的数据或者无法处理的空间的数据通过映射函数映射到一个小的容易处理的空间,但是在映射之后可能会出现不同的元素映射之后值相同的情况,这时就需要处理冲突,有两种方法分别是拉链法和开放寻址法    维护一个集合,支持如下几种操作: “I x”,插入一个数x; “Q x”,询问数x是否在集合中出现过; 现在要进行N次操作,对于每个询问操作输出对应的结果。 输入格式 第一行包含整数N,表示操作数量。 接下来N行,每行包含一个操作指令,操作指令为”I x”,”Q x”中的一种。 输出格式 对于每个询问指令“Q x”,输出一个询问结果,如果x在集合中出现过,则输出“Yes”,否则输出“No”。 每个结果占一行。 数据范围 1 ≤ N ≤ 10 5 1≤N≤105 − 10 9 ≤ x ≤ 10 9 −109≤x≤109 输入样例: 5 I 1 I 2 I 3 Q 2 Q 5 输出样例: Yes No#################################################### 1 #include <bits/stdc++.h> 2 using namespace std; 3 //拉链法处理哈希冲突,冲突指的是比如: 5 % 3 = 2,8 % 3 = 2,那么5和8就是冲突元素,所以把5和8挂在一个单链表上 4 const int N = 1e5+3;/

哈希表

巧了我就是萌 提交于 2020-01-22 05:32:56
1.什么是哈希表? 哈希表也叫散列表,是一种运算时用空间换取时间的数据结构,那么他是如何实现高效的数据处理的呢?举个例子,我们在做查找操作时,通常是需要对数据结构进行遍历,例如数组或者链表,通过比较相同的值,若相同则返回该值的下标,因此这样做查找的时间复杂度是O(n),哈希表是通过对key进行哈希函数的处理得到索引(index),然后将索引和数据一并存入该数据结构,这就是哈希表。 2.哈希表的复杂度 1.利用哈希函数生成key对应的index(O(1)) 2.根据index操作定位数组元素(O(1)) 由此可见,哈希表的运算过程时间复杂度降低,但是由于需要额外的空间存索引等数据,因此需要牺牲空间复杂度。 3.哈希表的特点 1.哈希碰撞(哈希冲突) 数据在进行哈希函数处理后,有时不同的数据会产生相同的结果,这就是哈希碰撞 这样就使得不同的值对应到相同的索引上,造成数据的冲突。解决哈希碰撞的常见方法有: 1.开放地址法(Open Addressing) 按照一定规则向其他地址探测,直到遇到空桶。 2.再哈希法 设计多个哈希函数。 3.链地址法 比如通过链表将同一index的值串起来。 4.良好的哈希函数特点 让哈希值更加均匀分布->减少哈希冲突次数->提升哈希表的性能 让哈希值均匀的目的是减少哈希碰撞,当多个值集中分布到相同索引时,造成哈希碰撞的可能性大大提高

PTA 乙级 JAVA实现 1005 继续(3n+1)猜想

我怕爱的太早我们不能终老 提交于 2020-01-22 01:08:30
卡拉兹(Callatz)猜想已经在1001中给出了描述。在这个题目里,情况稍微有些复杂。 当我们验证卡拉兹猜想的时候,为了避免重复计算,可以记录下递推过程中遇到的每一个数。例如对 n=3 进行验证的时候,我们需要计算 3、5、8、4、2、1,则当我们对 n=5、8、4、2 进行验证的时候,就可以直接判定卡拉兹猜想的真伪,而不需要重复计算,因为这 4 个数已经在验证3的时候遇到过了,我们称 5、8、4、2 是被 3“覆盖”的数。我们称一个数列中的某个数 n 为“关键数”,如果 n 不能被数列中的其他数字所覆盖。 现在给定一系列待验证的数字,我们只需要验证其中的几个关键数,就可以不必再重复验证余下的数字。你的任务就是找出这些关键数字,并按从大到小的顺序输出它们。 输入格式: 每个测试输入包含 1 个测试用例,第 1 行给出一个正整数 K (<100),第 2 行给出 K 个互不相同的待验证的正整数 n (1<n≤100)的值,数字间用空格隔开。 输出格式: 每个测试用例的输出占一行,按从大到小的顺序输出关键数字。数字间用 1 个空格隔开,但一行中最后一个数字后没有空格。 输入样例: 6 3 5 6 7 8 11 输出样例: 7 6 作者: CHEN, Yue 单位: 浙江大学 时间限制: 400 ms 内存限制: 64 MB 代码长度限制: 16 KB import java .

散列表

匆匆过客 提交于 2020-01-22 00:14:23
散列表 又叫 哈希表 (hash table)。 通过访问key而直接访问存储的value值 。它的key - value之间存在一个映射函数,我们可以通过key值和“看不到”的 映射函数 (散列函数)访问对应的value值。这加快了查找的速度!存放记录的数组称做 散列表。散列方法不同于顺序查找、二分查找、二叉排序树及B-树上的查找。它不以关键字的比较为基本操作, 采用直接寻址技术 (就是说,它是直接通过key 映射[映射函数,实现的方式有多种] 到内存地址上去的) 。在理想情况下,无须任何比较就可以找到待查关键字,查找的期望时间为O(1)(面试的时候犯了这个错误)。 举个形象的例子来说:为了查找电话簿中某人的号码,可以创建一个按照人名首字母顺序排列的表(即建立人名 到首字母 的一个 函数 关系),在首字母为W的表中查找“王”姓的电话号码,显然比直接查找就要快得多。这里使用人名作为 关键字 ,“取首字母”是这个例子中 散列函数 的函数法则 ,存放首字母的表对应 散列表 。关键字和函数法则理论上可以任意确定。[维基百科] 散列表  设所有可能出现的关键字集合记为U(简称全集)。实际发生(即实际存储)的关键字集合记为K(|K|比|U|小得多)。  散列方法是使用函数h将U映射到表T[0..m-1]的下标上(m=O(|U|))。这样以U中关键字为自变量

【数据结构与算法】HashTable相关操作实现 -- 基于Java的实现

会有一股神秘感。 提交于 2020-01-22 00:09:58
哈希表 哈希表又叫散列表,是实现字典操作的一种有效数据结构。哈希表的查询效率极高,在理想情况下,查找一个元素的平均时间为O(1)。 哈希表就是描述key—value对的映射问题的数据结构,即在记录的存储位置和它的关键字之间建立一个确定的对应关系f,使每个关键字与哈希表中唯一一个存储位置相对应。我们称这个对应关系f为哈希函数,这个存储结构即为哈希表。 直接寻 址表 当关键字的全域U比较小时,直接寻址是一种简单而有效的技术,它的哈希函数很简单:f(key) = key,即关键字大小直接与元素所在的位置序号相等。另外,如果关键字不是自然数,我们需要通过某种手段将其转换为自然数,比如可以将字符关键字转化为其在字母表中的序号作为关键字。直接寻址法不会出现两个关键字对应到同一个地址的情况,既不会出现f(key1) = f(key2)的情况,因此不用处理冲突,这便是其优点所在。 散列表 直接寻址的缺点非常明显,如果全域U很大,则在一台标准的计算机可用内存容量中,要存储大小为U的一张表也许不太实际,而且,实际需要存储的关键字集合K可能相对U来说很小,这时散列表需要的存储空间要比直接表少很多。散列表通过散列函数f计算出关键字key在槽的位置。散列函数f将关键字域U映射到散列表T[0...m-1]的槽位上。但是这里会存在一个问题:若干个关键字可能映射到了表的同一个位置处(算法导论上名其曰“槽”)

散列表(一).散列表基本内容介绍

耗尽温柔 提交于 2020-01-21 23:57:01
  一说到散列表,大家脑子想到的词就是:Hashmap、key-value、查找速度快、增删速度快等等。确实,在我们平常的学习生活中,散列表是很常见、也是用的很多的数据结构。那么散列表是怎样设计出来的,为什么它既可以和数组一样查询快,又可以和链表一样快增删,本节让我们一起了解一下什么是散列表、什么是散列函数、它究竟是如何设计出来的。 散列思想   什么是散列思想呢?散列表还有一个英文名叫做Hashtable,也叫做“哈希表”、“hash表”,hash我们都了解,是同过一定的算法、hash算法得到一个对象的散列值,用来标识对象本身的算法。   我们来举一个例子,假如有50个同学参加数学竞赛,为了能快速方便地找到每一个人,所以每个人都设立一个编号,从1到50,代表50个学生。现在如果我们用代码去实现这一功能的话,我们可以将这50个学生放到数组中去,从数组下标为1的位置开始,放入编号为1的学生,以此类推,将学生的编号和数组的下标一一对应,当我们要找第32个学生的时候,直接arr[32]就可以找到这个学生了,这样,就达成了O(1)的时间复杂度。实际上,这个例子已经用到了散列思想,能够快速地找到我们想找的学生,如果你觉得不够明显的话我们可以稍加改造一下。   假如,老师说编号这样太简单了,无法明显地表面这个学生的信息,需要再加上年级、班级这些信息,变成了6位数字,比如020433