1.稀疏数据的例子

  对于网络图对应的节点关联矩阵、数据生成的哈希表等,这些存储起来是稀疏的,这样我们就会想到需要压缩空间。但是在压缩存储空间的同时,还要支持高效的查询操作。

  Rank & Select 就可以对稀疏的数据进行压缩,还能支持高效的查询操作。

2.Rank & Select 操作压缩稀疏数据原理

  以下图为例子,假如是经过哈希后得到的哈希数组:

  

  构造数组A和B:

    Vec-A:1010100110001    (每个位置一个比特位,1:有数据,0:无数据)

     Num-B:12  2  23  11  12  1  (数据按原来的相对顺序,保存为一个数组)

  (1)Rank:

    针对Vec-A数组而言,记录每个位置前面(包括本位)有多少个1,也就是对应之前有多少个有效数字。这样做的目的是使得,数组中的有效数字的排名与在Num-B中的位置一致。

  (2)Select:

    根据查询数据在Vec-A上面的Rank排名,在Num-B中查询数据。

  (3)Rank & Select

    

    eg1:位置4对应的位置没有数据,所以在Vec-A中标记为0;

    eg2:位置5对应的位置有数据23,所以在Vec-A中标记为1。Vec-A(5)对应的rank为3,说明包含自己在内之前一共有3个数据,且在位置5对应的数据保存在Num-B的第3为,即Select(5)=Num-B(Rank(5))

4.使用SSE指令高效计算Rank

  SIMD,单指令多数据,就是一条指令由多个执行单元同时并行执行操作多个数据。

  SSE是指令集的简称,它包括70条指令,其中包含SIMD浮点计算、以及额外的SIMD整数和高速缓存控制指令。就是说SSE中存在指令,是SIMD指令,使得多核CPU可以高效执行。

  SSE指令 int _mm_popcnt_u32 (unsigned int a); 返回32为无符号整形 a 中bit位为1的位的个数。

5.Rank & Select 简单示例

  实例程序就是上面图中的例子,13个位置(1,2,3,..,14),6个有效位置。对其进行使用rank & select,进行压缩、并支持查询。

  例子较小,没有使用SSE指令,只是对rank select操作的简单说明。

 #include <iostream>
#include <string.h>
#include <bitset>
using namespace std; /**
设置原始数组num以及设置对应在ver_A的比特位
num:保存原始数据的数组
n:数组大小
ver_A:标记有效数字位向量
*/
int initNumVer(int *num,int *ver_A,int n){
memset(num,,sizeof(int)*n);
num[] = ; *ver_A |= (<<);
num[] = ; *ver_A |= (<<);
num[] = ; *ver_A |= (<<);
num[] = ; *ver_A |= (<<);
num[] = ; *ver_A |= (<<);
num[] = ; *ver_A |= (<<);
return ;
} /**
ver_A:位向量
rank:排名
num_B:压缩后的数组
pos:要查的位置
*/
int query(int *ver_A,int *rank,int *num_B,int pos){
if((*ver_A&(<<pos)) == )
return ;
else
return num_B[rank[pos]];
} int main (){
const int n = ;
int ver_A = ;
int *num = new int[n];
int *rank = new int[n];
int *num_B = new int[]; ///例子中有效数字6个,num_B[0]不使用 ///设置原始数组num以及设置对应在ver_A的比特位
initNumVer(num,&ver_A,); ///设置rank与压缩后的数组num_B
for(int i=,j=;i<n;i++){
if( (ver_A&(<<i)) != )
num_B[++j] = num[i];
rank[i]=j;
} ///查询第4、5个数
cout<<"第4个数:"<<query(&ver_A,rank,num_B,)<<endl;
cout<<"第5个数:"<<query(&ver_A,rank,num_B,)<<endl; delete [] num;
delete [] rank;
delete [] num_B;
return ;
}

6.注意

  (1)程序中以一维数组为例,其实多维数组也是连续存储,也可以理解为“一维数组”。

  (2)SSE指令时间复杂度为O(1),但是SSE指令操作位数有限。

  (3)如果Vec-A比特向量很长时,可以先计算一些rank数据保存下来(空间换时间),也可以达到计算任意位置rank操作时间复杂度为O(1)。

本文连接:http://www.cnblogs.com/xudong-bupt/p/3787658.html

参考链接:

SIMD : http://en.wikipedia.org/wiki/SIMD

_mm_popcnt_u32: http://msdn.microsoft.com/zh-cn/library/bb514083.aspx

SSE: http://en.wikipedia.org/wiki/SSE5

稀疏数据压缩查询方法:Rank & Select 操作的更多相关文章

  1. thinkphp数据查询方法总结select ,find,getField,query

    thinkphp已经封装好了常用的查询方法,且都比较实用,对于不常用的查询框架也保留了原始查询方法query. 1 2 $Model = new Model() // 实例化一个model对象 没有对 ...

  2. ThinkPHP 数据库操作(三) : 查询方法、查询语法、链式操作

    查询方法 条件查询方法 where 方法 可以使用 where 方法进行 AND 条件查询: Db::table('think_user') ->where('name','like','%th ...

  3. MyBaits一对一的查询方法

    MyBaits一对一的查询方法 一:表数据与表结构 CREATE TABLE teacher( t_id INT PRIMARY KEY AUTO_INCREMENT, t_name ) ); CRE ...

  4. 使用ResultSet,写了一个通用的查询方法

    此方法很烂,以后优化 /** * 通用的查询方法:SELECT */ @SuppressWarnings({ "unchecked", "rawtypes" } ...

  5. SpringBoot05 数据操作03 -> JPA查询方法的规则定义

    请参见<springboot详解>springjpa部分知识 1 按照方法命名来进行查询 待更新... package cn.xiangxu.springboot.repository; ...

  6. Thinkphp中的volist标签(查询数据集(select方法)的结果输出)用法简介

    参考网址:http://camnpr.com/archives/1515.html 通常volist标签多用于查询数据集(select方法)的结果输出,通常模型的select方法返回的结果是一个二维数 ...

  7. 【Java EE 学习 17 下】【数据库导出到Excel】【多条件查询方法】

    一.导出到Excel 1.使用DatabaseMetaData分析数据库的数据结构和相关信息. (1)测试得到所有数据库名: private static DataSource ds=DataSour ...

  8. Thinkphp回顾之(四)查询方法深入学习

    本次讲的查询方法主要有:表达式查询,模糊查询,between语句,in语句,区间查询,统计数据,普通方式查询,但大多数都只是引入数组而已,明白了第一个,其他的也就差不多全明白了,唯一要注意的是在后台中 ...

  9. JAVA 模糊查询方法

    当我们需要开发一个方法用来查询数据库的时候,往往会遇到这样一个问题:就是不知道用户到底会输入什么条件,那么怎么样处理sql语句才能让我们开发的方法不管接受到什么样的条件都可以正常工作呢?这时where ...

随机推荐

  1. CentOS 配置自启动Redis

    第一步: 在/etc/init.d/目录下建立一个名字为 redis 的启动脚本 cd /etc/init.d touch redis 然后在这个脚本中添加如下脚本  <注意修改自己的PIDFI ...

  2. mysql 函数substring_index()

    函数: 1.从左开始截取字符串 left(str, length) 说明:left(被截取字段,截取长度) 例:select left(content,200) as abstract from my ...

  3. 牛客练习赛3 F - 监视任务

    链接:https://www.nowcoder.net/acm/contest/13/F来源:牛客网 题目描述

  4. [SQL]196. Delete Duplicate Emails

    Write a SQL query to delete all duplicate email entries in a table named Person, keeping only unique ...

  5. 使用 Python 读取火狐的 cookies

    这事本来是有个 browsercookie 库可以做的,但是初看它就有不少问题: 不能指定要使用的火狐 profile(后来发现可以指定数据库文件). 找不到 sessionstore.js 文件时会 ...

  6. Redis 连接命令

    1.AUTH password 验证密码是否正确 2.ECHO message 打印字符串 3.PING 查看服务是否运行 4.QUIT 关闭当前连接 5.SELECT index 切换到指定的数据库

  7. 安卓 开机 动画 酷派大神F1开机动画 美化 自定义 修改

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha 酷派大神F1开机动画.rar

  8. FLASK开发简易blog的学习笔记

    首先,学会了如何创建一个新的包.就是在文件夹下创建__init__.py文件,就是在其他地方导入这个包了.

  9. HDU 2553 N皇后问题(深搜DFS)

    N皇后问题 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submi ...

  10. ROS知识(19)----写一个简单的pluginlib例子

    参考资料: 官方教程:Writing and Using a Simple Plugin