經典演算法系列之 一 BitMap

2021-08-15 07:35:28 字數 1801 閱讀 8672

一、問題引入

bitmap從字面的意思,很多人認為是點陣圖,其實準確的來說,翻譯成基於位的對映,怎麼理解呢?
舉乙個例子,有乙個無序有界int陣列,初步估計占用記憶體44=16位元組,這倒是沒什麼奇怪的,但是假如有10億個這樣的數呢,10億4/(1024*1024*1024)=3.72g左右。如果這樣的乙個大的資料做查詢和排序,那估計記憶體也崩潰了,有人說,這些資料可以不用一次性載入,那就是要存檔了,存檔必然消耗io。我們提倡的是高效能,這個方案直接不考慮。

二、問題分析

如果用bitmap思想來解決的話,就好很多,那麼bitmap是怎麼解決的啊,如下:
乙個byte是佔8個bit,如果每乙個bit的值就是有或者沒有,也就是二進位制的0或者1,如果用bit的位置代表陣列值有還是沒有,那麼0代表該數值沒有出現過,1代表該陣列值出現過。不也能描述資料了嗎?具體如下圖:

是不是很神奇,那麼現在假如10億的資料所需的空間就是3.72g/32了吧,乙個占用32bit的資料現在只占用了1bit,節省了不少的空間,排序就更不用說了,一切顯得那麼順利。這樣的資料之間沒有關聯性,要是讀取的,你可以用多執行緒的方式去讀取。時間複雜度方面也是o(max/n),其中max為byte陣列的大小,n為執行緒大小。

三、應用與**

如果bitmap僅僅是這個特點,我覺得還不是它的優雅的地方,接下來繼續欣賞它的魅力所在。下面的計算思想其實就是針對bit的邏輯運算得到,類似這種邏輯運算的應用場景可以用於許可權計算之中。
再看**之前,我們先搞清楚乙個問題,乙個數怎麼快速定位它的索引號,也就是說搞清楚byte[index]的index是多少,position是哪一位。舉個例子吧,例如add(14)。14已經超出byte[0]的對映範圍,在byte[1]範圍之類。那麼怎麼快速定位它的索引呢。如果找到它的索引號,又怎麼定位它的位置呢。index(n)代表n的索引號,position(n)代表n的所在的位置號。

index(n) = n/8 = n >> 3;

position(n) = n%8 = n & 0x07;

(1) add(int num)

你要向bitmap裡add資料該怎麼辦呢,不用擔心,很簡單,也很神奇。

上面已經分析了,add的目的是為了將所在的位置從0變成1.其他位置不變.

例項**:

public void add(int num)
(2) clear(int num)

對1進行左移,然後取反,最後與byte[index]作與操作。
例項**:

public void clear(int num)
(4) contain(int num)

例項**:

public boolean contain(int num)
全部**如下:

package com.chs.alg.bitmap;

public class bitmap

public void add(int num)

public boolean contain(int num)

public void clear(int num)

public static void main(string args)

}

經典演算法系列之 一 BitMap

一 問題引入 bitmap從字面的意思,很多人認為是點陣圖,其實準確的來說,翻譯成基於位的對映,怎麼理解呢?舉乙個例子,有乙個無序有界int陣列,初步估計占用記憶體44 16位元組,這倒是沒什麼奇怪的,但是假如有10億個這樣的數呢,10億4 102410241024 3.72g左右。如果這樣的乙個大...

演算法系列 bitmap演算法詳解和實現

我們可以將bitmap看成是一種資料結構,所謂的bit map就是用乙個 或幾個 bit位來標記某個元素對應的state value 最基本的情況,使用1bit標示乙個關鍵字的狀態 可標示兩種狀態 但根據需要也可以使用2bit 標示4種狀態 3bit 標示8種狀態 當乙個狀態標示需要的位數達到32b...

白話經典演算法系列

堆排序與快速排序,歸併排序一樣都是時間複雜度為o n logn 的幾種常見排序方法。學習堆排序前,先講解下什麼是資料結構中的二叉堆。二叉堆的定義二叉堆是完全二叉樹或者是近似完全二叉樹。二叉堆滿足二個特性 1 父結點的鍵值總是大於或等於 小於或等於 任何乙個子節點的鍵值。2 每個結點的左子樹和右子樹都...