【算法数据结构初阶篇】:位图bitMap
在java中,一個(gè)int類型占4個(gè)字節(jié),也就是32bit,我們用一個(gè)int數(shù)組來表示時(shí) new int[32],總計(jì)占用內(nèi)存大概32*32bit,如果說我們存放的海量數(shù)據(jù),億萬(wàn)級(jí)非常大,那么這些基本數(shù)據(jù)類型都不夠用的,則可以用int字節(jié)碼的每一位表示一個(gè)數(shù)字,比如int類型32位,可以存放0-31共32個(gè)數(shù)值,那么32個(gè)數(shù)字只需要一個(gè)int類型所占內(nèi)存空間大小就夠了,這樣在大數(shù)據(jù)量的情況下會(huì)節(jié)省很多內(nèi)存。
?一、位圖作用
存放海量數(shù)據(jù),節(jié)省存儲(chǔ)空間有明顯優(yōu)勢(shì)
二、位圖實(shí)現(xiàn)
一、思路分析
位圖的定義我們大概了解,就是通過定義一個(gè)整形數(shù)值后,將原本只表示1個(gè)數(shù)值的情況下,擴(kuò)大了可以存放幾十個(gè)數(shù)及以上的結(jié)構(gòu),比如我們要存放0-63的數(shù),共64個(gè)數(shù),那么我們就定義一個(gè)long型變量,有8個(gè)字節(jié),64位,二進(jìn)制就是64位,那么每一位從左到右就可以表示0,1,2..,63,如果有數(shù)則可以賦值1 沒有則表示0 比如保存1,那么就是第二位賦值1 ,以此類推
下面我們演示下,傳遞一個(gè)數(shù)值,保存到一個(gè)long[] arr數(shù)組中,簡(jiǎn)單了解下:
arr[0]存放的值: 0 - 63? ? ? ? ??
arr[1]存放的值: 64 - 127
arr[2]存放的值: 128 - 191
.....
num =4? 存放的位置就是 arr[0] 第一個(gè)元素 因?yàn)?num /64 = 0 ,元素二進(jìn)制?00..10000 第五位賦值1
?二、代碼演示
package class05;import java.util.HashSet;public class Code02_BitMap2 {// 這個(gè)類的實(shí)現(xiàn)是正確的public static class BitMap {//定義long數(shù)組,一個(gè)元素可以存放64個(gè)數(shù),因?yàn)閘ong類型是8字節(jié) 64位private long[] bits;//定義數(shù)組長(zhǎng)度,需要先給需要存儲(chǔ)的數(shù)集的最大值 (max+64/64) 表示需要多少個(gè),如 max是63 那個(gè)得 1 只需一個(gè)元素就可以//如果是64 得 2,就需要2個(gè)元素 因?yàn)橐粋€(gè)Long64位 存放0-63的數(shù)值, 接著是64-127public BitMap(int max) { bits = new long[(max + 64) >> 6];}/*保存數(shù)值1.num>>6 表示先將目標(biāo)數(shù)值除以64 得到該數(shù)值是位于bits數(shù)組的第幾個(gè),比如63 / 64 = 0 在bit[0] 64/64=1 bit[1]..2.num & 63 表示num % 64 , 即看在該元素的第幾位, 2的6次方=64 第7位1000000 所以可以知道求模后肯定余數(shù)是1-6位的數(shù),那么與運(yùn)算 111111 即 63 就能表示1-6的值,也就是余數(shù),也就得到是位于該元素中的第幾位了 比如余數(shù)0 那么就是第一位 ,1 就是第二位... 確定了這個(gè)余數(shù) 即第幾位,那么我們就用 1l << 余數(shù)(1必須要為long型 1L 取值長(zhǎng)度才不會(huì)越界,int是32位,所以右移63肯定位數(shù)不夠) 將1右移余數(shù)位,比如余數(shù)1 那么就1L右移一位,表示在這個(gè)位置標(biāo)1了。3.前面得到了對(duì)應(yīng)在第幾個(gè)元素中的第幾位,最后就是需要在這個(gè)元素的這個(gè)位置賦值1. 那么就是可以將元素位置bits[num >>6] =bits[num >>6] | (1L << (num & 64) 即或運(yùn)算 前面得到的具體位置,有1 則表示1 所以就給元素的對(duì)于位置賦值1了*/public void add(int num) {bits[num >> 6] |= (1L << (num & 63));}/*刪除數(shù)值, 就是將對(duì)應(yīng)的元素中的第幾位 將其1改成01.bits[num >> 6] 元素所在數(shù)組的元素, 1L << (num & 63) 64位元素中的第幾位 表示存放著num2.對(duì)1L << (num & 63) 取反, 就得到一個(gè) 1111...01111 即將存放位賦值0 其他為13.將取反后的數(shù) 與bits[num >> 6] 所在元素就行 與運(yùn)算, 此時(shí)其他位都位1 與完元素不變,而num所在位是0 與完則為0,則表示將數(shù)組刪除*/public void delete(int num) {bits[num >> 6] &= ~(1L << (num & 63));}/*判斷數(shù)值是否包含,那么就是判斷 bits[num >> 6] 所在元素的(1L << (num & 63)) 所在位 進(jìn)行與運(yùn)算,(1L << (num & 63))所在位為1 其他位都為0 所以與運(yùn)算后 如果為一 表示bits[num >> 6] 的所在位也是1 那么就返回true*/public boolean contains(int num) {return (bits[num >> 6] & (1L << (num & 63))) != 0;}}public static void main(String[] args) {System.out.println("測(cè)試開始!");int max = 10000;BitMap bitMap = new BitMap(max);HashSet<Integer> set = new HashSet<>();int testTime = 10000000;for (int i = 0; i < testTime; i++) {int num = (int) (Math.random() * (max + 1));double decide = Math.random();if (decide < 0.333) {bitMap.add(num);set.add(num);} else if (decide < 0.666) {bitMap.delete(num);set.remove(num);} else {if (bitMap.contains(num) != set.contains(num)) {System.out.println("Oops!");break;}}}for (int num = 0; num <= max; num++) {if (bitMap.contains(num) != set.contains(num)) {System.out.println("Oops!");}}System.out.println("測(cè)試結(jié)束!");}}三、核心總結(jié)?
總結(jié)
以上是生活随笔為你收集整理的【算法数据结构初阶篇】:位图bitMap的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: macOS 13 Ventura后,打开
- 下一篇: 寻求APP合伙人