位图法

     判断集合中存在重复是常见编程任务之一,当集合中数据量比较大时我们通常希望少进行几次扫描,这时双重循环法就不可取了。位图法比较适合于这种情况,它的做法是按照集合中最大元素max创建一个长度为max+1的新数组,然后再次扫描原数组,遇到几就给新数组的第几位置上1。如遇到5就给新数组的第六个元素置1,这样下次再遇到5想置时发现新数组的第六个元素已经是1了,这说明这次的数据肯定和以前的数据存在着重复。这种给新数组初始化时置零其后置一的做法类似于位图的处理方法故称位图法。它的运算次数最坏的情况为2N。如果已知数组的最大值即能事先给新数组定长的话效率还能提高一倍。Bloom filter可以看做是对bit-map的扩展。下面为利用位图法实现整形数组的排序代码。

   1: public class BitmapSort {
   2:  
   3: /** 
   4:  * 使用位图法进行排序
   5:  * 找到最小值和最大值,申请位图数组,对应位赋值为1,最后依次输出。
   6:  *  @param  arr
   7:  */
   8: public static void bitmapSort(int[] arr) {
   9:     int max = arr[0];
  10:     int min = max;
  11:     for (int i : arr) {
  12:         if (max < i) {
  13:             max = i;
  14:         }
  15:         if (min > i) {
  16:             min = i;
  17:         }
  18:     }
  19:     System.out.println("最大最小元素分别为:"+max + " " + min);
  20:  
  21:     int[] bitArr = new int[max - min + 1];
  22:     for (int i : arr) {
  23:         int index = i - min;
  24:         bitArr[index]++;
  25:     }
  26:     
  27:     System.out.println("bitmap后的数组元素为:");
  28:     for (int i : bitArr) {
  29:         System.out.print(i+" ");
  30:     }
  31:     System.out.println();
  32:  
  33:     int index = 0;
  34:     for (int i = 0; i < bitArr.length; i++) {
  35:         while (bitArr[i] > 0) {
  36:             arr[index] = i + min;
  37:             index++;
  38:             bitArr[i]--;
  39:         }
  40:     }
  41: }
  42:  
  43: public static void main(String[] args) {
  44:     int[] arr = { 1, 7, -3, 0, 0, 6, 6, 9, -11 };
  45:     bitmapSort(arr);
  46:     System.out.println("Bitmap排序后的结果:");
  47:     for (int i : arr) {
  48:         System.out.print(i + " ");
  49:     }
  50: }    
  51: }
位图法存数据
     Bit-map是用一个bit位来标记某个元素对应的Value, 而Key即是该元素。由于采用了Bit为单位来存储数据,因此在存储空间方面,可以大大节省。 在 8K 字节的内存空间内,如何存 unsigned short 类型数据?

一般做法:

定义一个数组: unsigned short arrNormal[4096]; 这样做,最多只能存 4K 个 unsigned short 数据。

利用位图法:

定义一个数组: unsigned char arrBit[4096]; 这样做,能存 4K*8=32K 个 unsigned short 数据。

     写数据元素:计算待写入数据在 arrBit 存放的字节位置和位位置(字节 0~4095 ,位 0~7 )

比如首先写 1234 ,字节序: 1234/8 = 154; 比特位序: 1234 & 0b111 = 2 ,那么 1234 放在 arrBit 数组的下标为 154 处,把该字节的 2 号位( 0~7)置为 1。

字节位置: int nBytePos = 1234/8 = 154;

位位置: int nBitPos = 1234 & 7 = 2;

// 把数组下标为 154 的 第2 个bit位置为 1

unsigned short val = 1<<nBitPos;

arrBit[nBytePos] = arrBit[nBytePos] | val;    // 写入 1234 得到 arrBit[154]=0b00000100

此时再写入 1236 ,

字节位置: int nBytePos = 1236/8 = 154;

位位置: int nBitPos = 1236 & 7 = 4

// 把数组下标为 154 的 第4 个bit位置为 1

val = 1<<nBitPos;

arrBit[nBytePos] = arrBit[nBytePos] | val;    // 再写入 1236 得到 arrBit[154]=0b00010100

获取插入数据后的value值为:
   1: int bytepos = data/8;
   2: int bitpos = data&7;
   3:  
   4: bitarr[bytepos] = bitarr[bytepos]|(1<<(7-bitpos));
   5:  
   6: int i = bitarr[bytepos];        
   7: byte[] b = toByteArray(i, 4);   //整型到字节
   8:  
   9: System.out.println(Integer.toBinaryString(i));
   1: byte[] toByteArray(int iSource, int iArrayLen) {  
   2:     byte[] bLocalArr = new byte[iArrayLen];  
   3:     for ( int i = 0; (i < 4) && (i < iArrayLen); i++) {  
   4:         bLocalArr[i] = (byte)( iSource>>8*i & 0xFF );           
   5:     }  
   6:     return bLocalArr;  
   7: }     
具体事例
    结合上述代码,我们来看一个具体的例子。假设我们要对0-7内的5个元素(4,7,2,5,3)排序(这里假设这些元素没有重复)。那么我们就可以采用Bit-map的方法来达到排序的目的。要表示8个数,我们就只需要8个Bit(1Bytes),首先我们开辟1Byte的空间,将这些空间的所有Bit位都置为0(如下图:)

然后遍历这5个元素,首先第一个元素是4,那么就把4对应的位置为1(可以这样操作 p+(i/8)|(0×01<<(i%8)) 当然了这里的操作涉及到Big Endian 和 Little Endian的情况,这里默认为Big Endian ),因为是从零开始的,所以要把第五位置为一(如下图):

然后再处理第二个元素7,将第八位置为1,,接着再处理第三个元素,一直到最后处理完所有的元素,将相应的位置为1,这时候的内存的Bit位的状态如下:

然后我们现在遍历一遍Bit区域,将该位是一的位的编号输出(2,3,4,5,7),这样就达到了排序的目的。

位图法的缺点:

1. 可读性差。

2. 位图存储的元素个数虽然比一般做法多,但是存储的元素大小受限于存储空间的大小。

     位图存储性质:存储的元素个数等于元素的最大值。比如, 1K 字节内存,能存储 8K 个值大小上限为 8K 的元素。(元素值上限为 8K ,这个局限性很大!)比如,要存储最大值为 65535 的数,就必须要 65535/8=8K 字节的内存。导致了位图法根本不适合数组中元素差异较大的情况。{1,1000,1000000}

3. 位图对有符号类型数据的存储,需要 2 位来表示一个有符号元素。这会让位图能存储的元素个数,元素值大小上限减半。比如 8K 字节内存空间存储 short 类型(有符号short)数据只能存 8K*4=32K 个,元素值大小范围为 -32K~32K 。

Big endian与little endian区别附录:

big endian是指低地址存放最高有效字节(MSB),而little endian则是低地址存放最低有效字节(LSB)。

比如0x12345678在两种不同字节序中的存储顺序如下所示:
Big Endian

低地址                                                           高地址
   ----------------------------------------->
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     12     |      34    |     56      |     78    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Little Endian

低地址                                                           高地址
   ----------------------------------------->
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     78     |      56    |     34      |     12    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

转载于:https://www.cnblogs.com/ttltry-air/archive/2012/08/04/2622832.html

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

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

相关文章

CentOS查看和修改PATH环境变量的方法

为什么80%的码农都做不了架构师&#xff1f;>>> 查看PATH&#xff1a;echo $PATH 以添加mongodb server为列 修改方法一&#xff1a; export PATH/usr/local/mongodb/bin:$PATH //配置完后可以通过echo $PATH查看配置结果。 生效方法&#xff1a;立即生效 有效期限…

IOS简单的登陆界面

主要需要注意的几个问题&#xff1a; 1.导入图片方式最好用文件导入 代码: 在ViewController.m文件中 2.UILable常用属性 property(nonatomic,copy) NSString *text; //设置文本内容 property(nonatomic,retain) UIFont *font; //设置字体 …

第6章 Python 数字图像处理(DIP) - 彩色图像处理3 -色彩变换、彩色校正、彩色图像平滑和锐化、HSI彩色空间中的分割、RGB空间中的分割、彩色边缘检测

这里写目录标题色彩变换彩色图像平滑和锐化使用彩色分割图像HSI 彩色空间中的分割RGB空间中的分割彩色边缘检测彩色图像中的噪声色彩变换 # 图像颜色分量的显示 from PIL import Imageimg_ori Image.open(DIP_Figures/DIP3E_Original_Images_CH06/Fig0630(01)(strawberries_f…

javascript 在对象中使用 定时器_如何使用JavaScript 面向对象编程

学习目标理解面向对象开发思想掌握 JavaScript 面向对象开发相关模式面向对象介绍什么是对象Everything is object (一切皆对象)我们可以从两个层次来理解对象&#xff1a;(1) 对象是单个事物的抽象。一本书、一辆汽车、一个人都可以是对象&#xff0c;一个数据库、一张网页、一…

char数组转string_String类和其它数据类型的相互转换

对于上面的这些包装类&#xff0c;除了Character以外&#xff0c;都有可以直接使用字符串参数的构造函数&#xff0c;这也就使得我们将String类转换为这些数据类型变得相当之简单&#xff0c;即&#xff1a;Boolean(String s)、Integer(String s)、Long(String s)、Float(Strin…

ORACLE 各种闪回操作

1、Flashback Database&#xff08;利用闪回日志恢复&#xff09; Oracle Flashback Database特性允许通过SQL语句Flashback Database语句&#xff0c;让数据库前滚到当前的前一个时间点或者SCN&#xff0c;而不需要做时间点的恢复。闪回数据库可以迅速将数据库回到误操作或人为…

【转】介绍设置Session失效的几种方法

转载地址&#xff1a;http://developer.51cto.com/art/201106/269493.htm Session对象是HttpSessionState的一个实例。该类为当前用户会话提供信息&#xff0c;还提供对可用于存储信息会话范围的缓存的访问&#xff0c;以及控制如何管理会话的方法。下面介绍设置session失效的几…

mysql导入数据load data infile用法整理

有时候我们需要将大量数据批量写入数据库&#xff0c;直接使用程序语言和Sql写入往往很耗时间&#xff0c;其中有一种方案就是使用MySql Load data infile导入文件的形式导入数据&#xff0c;这样可大大缩短数据导入时间。 假如是从MySql客户端调用&#xff0c;将客户端的文件导…

python3循环一直到一个值结束_一步一步学Python3(小学生也适用) 第十七篇:循环语句for in循环...

一、Python for in循环Python for in 循环&#xff0c;是用来遍历任何数据序列&#xff0c;如一个列表&#xff0c;一个字符串&#xff0c;一个字典&#xff0c;一个元组等。for in 循环的一般语法如下&#xff1a;for item in 序列:语句块else:语句块for in 字符串&#xff1…

设置Jupyter notebook 默认工作路径,修改Jupyter notebook 默认浏览器为Chrome

这里写目录标题一 设置Jupyter notebook 默认工作路径二 修改Jupyter notebook 默认浏览器为Chrome一 设置Jupyter notebook 默认工作路径 安装好anaconda 后&#xff0c;jupyter notebook默认是有安装好的。在windows的菜单栏找到anaconda目录&#xff0c;如下图 鼠标右键点…

python调用c#注意事项_Python调用C#编写的DLL

起因是工作中需要用的开发编写的DLL&#xff0c;但是它是使用C#编写的&#xff0c;本人不想使用C#去写测试代码&#xff0c;所以需要使用Python来掉这个DLL内的方法 就用这个就很好&#xff0c;不要问为啥不用微软的Ironpython和别的啥&#xff0c;好用就行了&#xff0c;解决问…

jquery实战--定宽

大家有没有遇到过一个问题&#xff0c;就是一个列表&#xff0c;或是一段文字过多时&#xff0c;截取多余的部分用省略号&#xff0c;好吧&#xff0c;证明你实力的时候到了&#xff0c;我下面先分解一下方法&#xff0c;再用插件写出来,首先我们说的是&#xff0c;用到的第一个…

struts2 Action获取表单数据

1.通过属性驱动式 1.首先设置 表单中的数据的name值 如&#xff1a;<input type"text" name"username" value""> 2.你用的是struts2&#xff0c;那么就在java类中写一个变量&#xff1a;变量名和页面上的name值一致 并有这个变量的get 和…

python 计算器 eval ctf_CTF逆向--.NET与Python篇

题目(来源&#xff1a;Jarvis-OJ)&#xff1a;Classical CrackmeClassical CrackMe2FindKeyLoginClassical Crackme首先查壳没有壳&#xff0c;不过发现这是一个.net的程序&#xff0c;将其拖进dnSpy中&#xff0c;找到主程序&#xff0c;同时发现关键代码&#xff0c;如下所示…

2016年秋季个人阅读计划

阅读书目&#xff1a;《软件需求十步走》 读后感发表日期&#xff1a;阅读书目&#xff1a;《用户故事与敏捷方法》 读后感发表日期&#xff1a;第一篇&#xff1a;10月1日 第二篇&#xff1a;10月3日 第三篇&#xff1a;10月7日 第四篇&#xff1a;10月15日 第五篇&#xff1a…

第10章 Python 数字图像处理(DIP) - 图像分割 基础知识 标准差分割法

This Chapter is all about image segmentation. I still not finished whole chapter, but here try to publish some for reference. 这里写目录标题基础知识import sys import numpy as np import cv2 import matplotlib import matplotlib.pyplot as plt import PIL from …

OFBiz的探索进阶

主要参照https://cwiki.apache.org/OFBIZ/ofbiz-tutorial-a-beginners-development-guide.html这个教程&#xff0c;实现的过程教程上很详细&#xff0c;故这里不多说 还参考了下http://www.hotwaxmedia.com/apache-ofbiz-blog/ofbiz/ofbiz-tutorials/ofbiz-tutorial-building-…

python3语法都相同吗_python2 与 python3 语法区别--转

原文地址&#xff1a;http://old.sebug.net/paper/books/dive-into-python3/porting-code-to-python-3-with-2to3.html 使用2to3将代码移植到Python 3 ❝ Life is pleasant. Death is peaceful. It’s the transition that’s troublesome. ❞ — Isaac Asimov (attributed) 概…

对GCD的一些理解和实践

对GCD的一些理解和实践GCD GCD&#xff0c;全程Grand Central Dispatch&#xff0c;是苹果为了多核并行提出的解决方案。它是使用C语言实现&#xff0c;但是由于用了block来处理回调&#xff0c;所以使用起来十分方便。并且GCD会自动管理线程的生命周期&#xff0c;不需要我们去…

python scrapy爬虫遇见301_在Pycharm中运行Scrapy爬虫项目的基本操作

目标在Win7上建立一个Scrapy爬虫项目&#xff0c;以及对其进行基本操作。运行环境&#xff1a;电脑上已经安装了python(环境变量path已经设置好)&#xff0c;以及scrapy模块&#xff0c;IDE为Pycharm 。操作如下&#xff1a;一、建立Scrapy模板。进入自己的工作目录&#xff0c…