整型数组压缩算法

目的

将整型数组进行压缩及检索的方法,将长整型数字按指定的位数进行位运算,将具有相同特性的一组数据填充到一个64位二进制数中实现数据的压缩,然后将压缩后的数据存入数组中。提供O(1)的时间复杂度对数据进行快速检索。

具体实现

一、压缩

初始化压缩数组,该数组用于存放压缩后的数据,该数组的最大度为源数据(文中提到的源数据为需要压缩的整型数组)中的最大值在压缩数组中的索引下标+1,计算源数据中的元素在压缩数组中的索引下标(索引的值从0开始)公式如下:

index = ((maxValue>>> 6) + ((maxValue & (Long.SIZE-1)) > 0 ? 1 : 0) - 1)

索引下标计算公式参数说明:index为源数据中的元素在压缩数组中的索引下标,targetNum为源数据中的元素,Long.SIZE = 64为java中long类型数据的最大位数。

索引下标计算公式计算说明:

①,该公式对需要压缩的数据先进行6位右移运算(高6位补0,低位移除6位,相当于将数据除以64)。

②,然后再对需要压缩的数据对63(Long.SIZE-1=63)进行按位与运算(63用64位二进制数表示,底6位全部为1,高位全部为1,与63进行按位与运算相当于对64取余运算),得到余数如果大于0,则((targetNum & (Long.SIZE-1)) > 0 ? 1 : 0) 运算的结果为 1 否则 ((targetNum & (Long.SIZE-1)) > 0 ? 1 : 0) 运算结果为0。

③,将①,②得到的结果相加,然后再减1,计算出索引下标 index。此处计算思想为如果②计算结果有余数则计算索引时不需要减1,否则需要减去1。以下通过两个示例来说明位移运算以及按位与运算的过程:

示例1:128进行右移6位(除以64)后得到的结果为2(如下图),然后对128和63按位与运算(对64进行取余)得到的结果为0,因此((128 & (Long.SIZE-1)) > 0 ? 1 : 0) = 0,最终index = 2 + 0 - 1 = 1。
在这里插入图片描述
示例2:129进行右移6位(除以64,见下图)后得到的结果为2,然后对128和63按位与运算(对64进行取余)得到的结果为1,因此((129 & (Long.SIZE-1)) > 0 ? 1 : 0) = 1,最终index = 2 + 1 - 1 = 2。
在这里插入图片描述
2,获取到源数据中最大值在压缩数组中的索引下标后,即可计算出压缩数组的长度,即length = index + 1 ,其中length表示压缩数组的长度,index为源数据中最大元素在数组中的索引下标,此时就可以对数组进行初始化。

3,初始化完数组后,开始对源数据中的每一项元素进行压缩,具体实现分为以下两个步骤:

①,如上所述,根据索引下标计算公式算出要压缩的元素在压缩数组中的位置index,如上述128在索引值为1的位置,129位索引值为2的位置。

②,将要压缩的元素对63按位与运算(相当于对64取余),然后将与运算后的结果减1,得到被压缩的的元素在64位二进制数中的位置。然后将1(用64位二进制数表示)进行左移操作,左移的步长既为上述与运算后减1的结果。如:128对63按位与运算,得到结果为0,此时需要左移的步长为 0 -1 = -1 对1(64位二进制数表示)进行左移-1位,既1 <<- 1 和左移63位结果一样,既1 << -1 = 1 << 63,此时1落在64位二进制数中的第64位上,得到结果如下:
在这里插入图片描述
③,通过①,②,得到128被压缩的元素在压缩数组中的索引位置以及压缩过后的数据(1左移-1位后的二进制数)后,将压缩数据存入其在压缩数组中的位置处。如果后续被压缩的元素,和当前被压缩的元素,在压缩数组中的下标相同时,则取出该索引处已经压缩后的数据和后续压缩数据进行或运算,如127在压缩数组中的索引也是1,127对63按位与运算,得到63,左移步长为63 - 1,将1左移62位,既1 << 62后得到压缩数据,此时需要将该索引处已经压缩的数据和当前压缩数据进行或运算,得到新的压缩结果,如下图:
在这里插入图片描述

④,上述数据压缩时,根据操作系统的核心数和被压缩元素的索引下标,动态的开启多个线程池(核心线程数为1,待处理的任务提交到队列中)并行的对源数据进行压缩,保证压缩数组下标相同的元素只由同一个线程来处理,保证多线程并发带来的安全问题的同时也提升了cpu的使用及源数据的压缩效率。假设操作系统的核心数为4,则此时开启四个线程池,每个线程池的核心线程数都为1,压缩数组的索引对4取余,将每一个元素的压缩任务分配到相对于的线程池中,如1对4取余得1此时将压缩元素索引下标为1的任务都提交给线程1,实现多线程并行压缩,提高压缩效率。
在这里插入图片描述

解压缩

数组压缩的解压缩方案技术实现如下:

1,遍历数组中值不为0的元素。

2,将该元素转换成64位二进制数进行表示。

3,获取该64位二进制数中所有1的索引下标。

压缩数组的索引下标index 乘以 64 ,再加上64位二进制数中的1所在的索引下标即可得到压缩前的数据,公式如下:

source = index * 64 +binaryIndex

公式参数说明:source 解压后的数据,index压缩数组元素在数组中的索引,binaryIndex 压缩数据用64位二进制数表示,其中1所在的索引下标。

为了更好的说明解压缩过程,下面给出示例:

假设压缩后的数组第一个元素为18,此时对该元素进行解压缩。

①,将索引0处的18转为64位二进制数,如下所示。

在这里插入图片描述
②,获取二进制数中的1所在的位置 binaryIndex(2和5),压缩数组索引下标index乘以64 + binaryIndex 得到解压缩后的数据。
在这里插入图片描述

检索

检索数据的实现,既通过查找,判断该数据是否存在压缩数组中。

1,通过公式计算出要检索的元素在压缩数组中的位置index。

2,计算出该元素与63按位与运算的结果 binaryIndex,将1进行左移binaryIndex位,得到value1。

3,从压缩数组中取出index位置的压缩数据vaule2与步骤2左移后的结果进行按位与运算,如果得到的结果还是value1,则说明该元素在压缩数组中。

检索公式:

exist = indexZipValue &  binaryZipValue

公式说明:exist 元素是否存在,indexZipValue 压缩数组中的压缩数据,binaryZipValue 要检索的元素压缩后的数据 ,&为按位与运算符

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值