位图法

     判断集合中存在重复是常见编程任务之一,当集合中数据量比较大时我们通常希望少进行几次扫描,这时双重循环法就不可取了。位图法比较适合于这种情况,它的做法是按照集合中最大元素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…

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;如下图 鼠标右键点…

第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-…

对GCD的一些理解和实践

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

[Buzz Today]2012.08.08

# Dark Reign 2 源代码现身Google Code Pandemic工作室开发的即时战略游戏《Dark Reign 2》源代码被泄露到了Google Code http://code.google.com/p/darkreign2/ # Warsow 1.0发布 Set in a futuristic cartoonish world, Warsow is a completely free fast-paced first-person…

PyTorch训练中Dataset多线程加载数据,比Dataloader里设置多个workers还要快

PyTorch训练中Dataset多线程加载数据&#xff0c;而不是在DataLoader 背景与需求 现在做深度学习的越来越多人都有用PyTorch&#xff0c;他容易上手&#xff0c;而且API相对TF友好的不要太多。今天就给大家带来最近PyTorch训练的一些小小的心得。 大家做机器学习、深度学习都…

python调用摄像头人脸识别代码_利用face_recognition,dlib与OpenCV调用摄像头进行人脸识别...

用已经搭建好 face_recognition&#xff0c;dlib 环境来进行人脸识别 未搭建好环境请参考&#xff1a; 使用opencv 调用摄像头 import face_recognition import cv2 video_capture cv2.videocapture(0) # videocapture打开摄像头&#xff0c;0为笔记本内置摄像头&#xff0c;1…

【转】彻底搞清计算结构体大小和数据对齐原则

数据对齐: 许多计算机系统对基本数据类型合法地址做出了一些限制&#xff0c;要求某种类型对象的地址必须是某个值K(通常是2&#xff0c;4或8)的倍数。这种对齐限制简化了形成处理器和存储器系统之间的接口的硬件设计。例如&#xff0c;假设一个处理器总是从存储器中取出8个字节…

Pytorch 学习率衰减 之 余弦退火与余弦warmup 自定义学习率衰减scheduler

学习率衰减&#xff0c;通常我们英文也叫做scheduler。本文学习率衰减自定义&#xff0c;通过2种方法实现自定义&#xff0c;一是利用lambda&#xff0c;另外一个是继承pytorch的lr_scheduler import math import matplotlib.pyplot as plt import numpy as np import torch i…

c++ 字符串赋给另一个_7.2 C++字符串处理函数

点击上方“C语言入门到精通”&#xff0c;选择置顶第一时间关注程序猿身边的故事作者闫小林白天搬砖&#xff0c;晚上做梦。我有故事&#xff0c;你有酒么&#xff1f;C字符串处理函数C语言和C提供了一些字符串函数&#xff0c;使得用户能很方便地对字符串进行处理。这些是放在…

如何检测远程主机上的某个端口是否开启

有时候我们要测试远程主机上的某个端口是否开启&#xff0c;无需使用太复杂的工作&#xff0c;windows下就自带了工具&#xff0c;那就是telnet。怎么检测呢&#xff0c;按下面的步骤&#xff1a; 1、安装telnet。我的win7下就没有telnet&#xff0c;在cmd下输入telnet提示没有…

Windows10 + WSL (Ubuntu) + Anaconda + vscode 手把手配置python运行环境(含虚拟环境)

配置WSL windows桌面下&#xff0c;按下面顺序可以找到 "启动或关闭windows功能” &#xff0c; 开始 -> 设置 -> 应用 -> 应用和功能 -> 可选功能 -> 相关设置下 更多Windows功能&#xff08;滚动鼠标到底部&#xff09;点击后&#xff0c;会弹出 启动或…

2019编译ffepeg vs_如何在windows10下使用vs2017编译最新版本的FFmpeg和ffplay

该文章描述了如何在windows10 64位系统下面编译出FFmpeg的库及其自带的ffplay播放器&#xff0c;而且全部采用最新的版本&#xff0c;这样我们可以在vs2017的ide下调试ffplay&#xff0c;能使我们更容易学习FFmpeg的架构以及音视频播放器的原理。步骤&#xff1a;1.安装vs2017在…

训练集山准确率高测试集上准确率很低_推荐算法改版前的AB测试

编辑导语&#xff1a;所谓推荐算法就是利用用户的一些行为&#xff0c;通过一些数学算法&#xff0c;推测出用户可能喜欢的东西&#xff1b;如今很多软件都有这样的操作&#xff0c;对于此系统的设计也会进行测试&#xff1b;本文作者分享了关于推荐算法改版前的AB测试&#xf…