位圖法

???? 判斷集合中存在重復是常見編程任務之一,當集合中數據量比較大時我們通常希望少進行幾次掃描,這時雙重循環法就不可取了。位圖法比較適合于這種情況,它的做法是按照集合中最大元素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.pswp.cn/news/260537.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/260537.shtml
英文地址,請注明出處:http://en.pswp.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…