欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++位圖的實現(xiàn)原理與方法

 更新時間:2021年05月30日 16:02:50   作者:WhiteShirtI  
位圖(bitset)是一種常用的數(shù)據(jù)結(jié)構(gòu),常用在給一個很大范圍的數(shù),判斷其中的一個數(shù)是不是在其中。這篇文章主要給大家介紹了關(guān)于C++位圖以及位圖的實現(xiàn)原理與方法,需要的朋友可以參考下

概念

位圖就是bitmap的縮寫,所謂bitmap,就是用每一位來存放某種狀態(tài),適用于大規(guī)模數(shù)據(jù),該數(shù)據(jù)都是不重復(fù)的簡單數(shù)據(jù)。通常是用來判斷某個數(shù)據(jù)存不存在的

例如:給40億個不重復(fù)的unsigned int的整數(shù),沒排過序的,然后再給一個數(shù),如何快速判斷這個數(shù)是否在那40億個數(shù)當(dāng)中

如果不看數(shù)據(jù)量,我們第一想到的肯定就是依次從頭遍歷,但是這個數(shù)據(jù)量是非常大的,有40億,遍歷40億次消耗的時間和內(nèi)存是非常多的。但是引入位圖后,就可以專門解決這種大量數(shù)據(jù)查找是否存在的問題。查找這個數(shù)是否存在所消耗的時間復(fù)雜度為O(1),且節(jié)省了32倍的容量(下面有解釋)。下面我們一起來看看位圖的原理及代碼實現(xiàn)

原理

查找一個數(shù)是否存在,其實答案就是存在或者不存在,這種只需要回答是與否的問題,我們都可以用二進制中的位來表示,1表示該數(shù)存在,反之0表示該數(shù)不存在。而位圖中的每個數(shù)據(jù)單元都是一個bit位,這樣子平時我們都要話32位4字節(jié)來存儲數(shù)據(jù),而現(xiàn)在我們只需要花1個字節(jié)就能“存儲數(shù)據(jù)”,在空間上減少了約32倍的容量。例如40G的數(shù)據(jù)我們只要花1.3G來存儲。但是我們平時操作的數(shù)據(jù)類型最小就是一個字節(jié),我們不能直接對位進行操作,所以我們可以借助位運算來對數(shù)據(jù)進行操作。下面我們來看看數(shù)據(jù)在位圖中是如何存儲的

我們這里給出一個數(shù)組

int arr[] = {1,2,4,5,7,10,11,14,16,17,21,23,24,28,29,31};則我們只需要花1個字節(jié)來存這些數(shù)據(jù)

解釋:我們目前很多的機器都是小端存儲,也就是低地址存低位,一個整形數(shù)據(jù)中,第一個字節(jié)用來存儲0-7的數(shù)字,第二個字節(jié)用來存儲8-15的數(shù)字,第三個字節(jié)用來存儲16-23的數(shù)字,第四個字節(jié)用來存儲24-31的數(shù)字。我們來看看數(shù)字10是如何存儲的。先通過模上32,取余還是10,然后再將4字節(jié)中第10個比特位置為1,則表示該數(shù)字出現(xiàn)過。由于我們的機器是小端存儲,所以我們的每個比特位都是要從右邊開始計算的,如下圖

所以說我們只需要將對應(yīng)的比特位置為1即可。但是如果我們要存儲的數(shù)據(jù)很大呢?其實也很簡單,我們可以定義一個數(shù)組,當(dāng)做一個位圖,如果該數(shù)字在0-31之間,我們就存儲在0號下標(biāo)的元素中進行操作,如果在32-63之間,則就在1號下標(biāo)之間進行操作。計算下標(biāo)我們可以通過模32來獲得下標(biāo)。

我們知道位圖的原理后,我們在通過原理來用代碼實現(xiàn)一個位圖吧

實現(xiàn)

成員變量和構(gòu)造函數(shù):在實現(xiàn)位圖中,我們的成員變量只需要一個數(shù)組就可以實現(xiàn)。而這個數(shù)組有多我們要開多大呢?數(shù)組多開一個整形空間,就能多存32個數(shù)字,所以我們可以讓用戶提供一個準(zhǔn)確的數(shù),這個數(shù)是一個數(shù)據(jù)量,也是數(shù)的最大范圍。我們可以通過該數(shù)模上32,就可以獲得該數(shù)組的大小,但是0~31模上32為0,我們開0個空間那顯然不合適,所以我們要開range/32 + 1個空間大小的數(shù)組

存儲數(shù)據(jù):存儲一個數(shù)字num需要3個步驟,第一是需要計算出該值對應(yīng)的數(shù)組下標(biāo)。計算數(shù)組下標(biāo)方式為idx=num / 32;第二步是計算num在對應(yīng)整數(shù)的比特位的位置bitIdx=num%32;第三步是要將計算出來的bite位置為1。我們之前說過,要操作位,我們可以通過位運算來操作,可以先將1左移bitIdx位后再和整數(shù)進行或運算

例如假設(shè)bitIdx=5,數(shù)據(jù)為10010011

1.將1進行左移5位==>100000

2.將數(shù)據(jù)和第一步計算出來的結(jié)果進行或運算

10010011 | 100000 =10110011,此時我們就將指定位置置位1了

查找數(shù)據(jù):要判斷一個數(shù)據(jù)是否存在,其實和存儲數(shù)據(jù)是類似,也是需要計算出兩個位置idx和bitIdx。然后通過這兩個位置來判斷對應(yīng)位置是否為1,為1則表示該數(shù)字存在。如何判斷呢?我們可以先將數(shù)組下標(biāo)為idx的整數(shù)向右移bitIdx位,然后再和1進行與運算,如果為1則表示存在,否則不存在

例如假設(shè)bitIdx=5,數(shù)據(jù)為10110011

1.將數(shù)據(jù)進行右移5位00000101

2.將第一步計算出來的結(jié)果和1進行與運算

00000101 & 1 = 1,此時表示該數(shù)字存在,返回true

刪除數(shù)據(jù):刪除數(shù)據(jù)和存儲數(shù)據(jù)操作一樣,唯一的區(qū)別就是將對應(yīng)的bit位置為0。我們可以通過先將1進行左移bitIdx位,然后取反,將結(jié)果再和原來數(shù)據(jù)進行與運算

例如假設(shè)bitIdx=5,數(shù)據(jù)為10110011

1.將1進行左移5位后并取反011111

2.將第一步計算出來的結(jié)果和數(shù)據(jù)進行與運算

10110011 & 011111 = 10010011,刪除成功

代碼:

class BitMap
{
public:
	//位圖的內(nèi)存大小和數(shù)據(jù)范圍有關(guān)
	BitMap(size_t range)
		:_bit(range / 32 + 1)
	{}

	void set(const size_t num)
	{
		//計算數(shù)組中的下標(biāo)
		int idx = num / 32;
		//計算num在對應(yīng)下標(biāo)整數(shù)中的下標(biāo)位置
		int bitIdx = num % 32;
		//將對應(yīng)的比特位置1
		_bit[idx] |= 1 << bitIdx;
	}

	bool find(const size_t num)
	{
		int idx = num / 32;
		int bitIdx = num % 32;
		return (_bit[idx] >> bitIdx) & 1;
	}

	void reset(const size_t num)
	{
		int idx = num / 32;
		int bitIdx = num % 32;
		_bit[idx] &= ~(1 << bitIdx);
	}
private:
	vector<int> _bit;
};

測試截圖:

總結(jié)

到此這篇關(guān)于C++位圖的實現(xiàn)原理與方法的文章就介紹到這了,更多相關(guān)C++位圖實現(xiàn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語言實現(xiàn)靜態(tài)鏈表

    C語言實現(xiàn)靜態(tài)鏈表

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)靜態(tài)鏈表,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-07-07
  • Qt學(xué)習(xí)筆記之QPalette調(diào)色板類

    Qt學(xué)習(xí)筆記之QPalette調(diào)色板類

    這篇文章主要為大家詳細介紹了Qt學(xué)習(xí)筆記之QPalette調(diào)色板類,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-07-07
  • 一起來學(xué)習(xí)C++的動態(tài)內(nèi)存管理

    一起來學(xué)習(xí)C++的動態(tài)內(nèi)存管理

    這篇文章主要為大家詳細介紹了C++的動態(tài)內(nèi)存管理,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • 解析C++編程中的#include和條件編譯

    解析C++編程中的#include和條件編譯

    這篇文章主要介紹了解析C++編程中的#include和條件編譯,是C++入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下
    2015-09-09
  • C語言與java語言中關(guān)于二維數(shù)組的區(qū)別

    C語言與java語言中關(guān)于二維數(shù)組的區(qū)別

    這篇文章主要介紹了C語言與java語言中關(guān)于二維數(shù)組的區(qū)別,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • C語言實現(xiàn)制作通訊錄(新手推薦)

    C語言實現(xiàn)制作通訊錄(新手推薦)

    本文推薦給C語言學(xué)習(xí)到結(jié)構(gòu)體的新手們,供其練習(xí)。這篇文章主要是利用C語言制作一個簡單的通訊錄功能,感興趣的小伙伴可以跟隨小編一起了解一下
    2022-09-09
  • C語言詳解格式控制符scanf與printf的輸入輸出

    C語言詳解格式控制符scanf與printf的輸入輸出

    這篇文章主要介紹了C語言格式控制符中輸入scanf()和輸出printf()的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2022-04-04
  • 基于C語言實現(xiàn)簡易掃雷游戲

    基于C語言實現(xiàn)簡易掃雷游戲

    這篇文章主要為大家詳細介紹了基于C語言實現(xiàn)簡易掃雷游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下<BR>
    2022-01-01
  • 數(shù)據(jù)結(jié)構(gòu) 數(shù)組順序存儲詳細介紹

    數(shù)據(jù)結(jié)構(gòu) 數(shù)組順序存儲詳細介紹

    這篇文章主要介紹了數(shù)據(jù)結(jié)構(gòu) 數(shù)組順序存儲詳細介紹的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • C++詳解實現(xiàn)Stack方法

    C++詳解實現(xiàn)Stack方法

    C++ Stack(堆棧)是一個容器類的改編,為程序員提供了堆棧的全部功能,也就是說實現(xiàn)了一個先進后出(FILO)的數(shù)據(jù)結(jié)構(gòu)
    2022-06-06

最新評論