真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

【C++】哈希-bitset位圖與模擬-創(chuàng)新互聯(lián)

目錄

創(chuàng)新互聯(lián)公司是一家專注于成都網(wǎng)站制作、做網(wǎng)站、外貿(mào)營銷網(wǎng)站建設與策劃設計,云龍網(wǎng)站建設哪家好?創(chuàng)新互聯(lián)公司做網(wǎng)站,專注于網(wǎng)站建設十載,網(wǎng)設計領域的專業(yè)建站公司;建站業(yè)務涵蓋:云龍等地區(qū)。云龍做網(wǎng)站價格咨詢:028-86922220

1.位圖

1.1什么是位圖?

1.2位圖的作用?

2.bitset應用

2.1bitset構造

2.2bitset成員函數(shù)與使用?

3.bitset模擬實現(xiàn)?

構造函數(shù)?

set

reset

test

flip

count?

size?

none,any


1.位圖

在前文中我們介紹了哈希的一些內容,接下來我們介紹一個新奇的玩意,位圖。?

1.1什么是位圖?
  • 位圖其實就是哈希的變形,同樣通過映射來處理數(shù)據(jù)。
  • 位圖本身并不存儲數(shù)據(jù),而是存儲標記通過一個比特位來標記這個數(shù)據(jù)是否存在,1代表存在,0代表不存在。
  • 位圖通常情況下用在數(shù)據(jù)量龐大,且數(shù)據(jù)不重復的情景下判斷某個數(shù)據(jù)是否存在。

相比通過上面的介紹,各位還是不知道位圖有啥作用。接下來我們說一下位圖的作用。

1.2位圖的作用?

騰訊出過一個面試題:?給40億個不重復的無符號整數(shù),沒排過序。給一個無符號整數(shù),如何快速判斷一個數(shù)是否在這40億個數(shù)中。

1整數(shù)=4字節(jié)=32bit。

40億個整數(shù) = 160億個字節(jié)
而1GB = 1024MB
1024MB = 1024 * 1024KB
1024 * 1024KB = 1024 * 1024 * 1024B(yte )≈ 10億字節(jié)
綜上1GB ≈ 10億字節(jié)
? ?16GB ≈ 160億字節(jié)

遍歷時間復雜度O(N);排序(O(NlogN))利用二分查找: logN;這兩種方式除了效率不夠高,還有個問題是內存無法完全同時加載40億個整數(shù)需要的16G大小空間。

我們也可以用set容器,但是底層的紅黑樹存放這么多數(shù)據(jù)也吃不消所以我們用位圖來解決這個問題。

1個整形是32bit位,就比如整數(shù)在計算機中以二進制來存儲的。而這32個位置上只有0或1,那我們可以讓1表示有數(shù)據(jù),0表示沒存放數(shù)據(jù)。我們以32比特位表示一個單元。

如果采用這種方法,只需占500M內存就可以:

1G = 2^30Byte ≈ 10億字節(jié)
(2^32 - 1)Byte ≈ 40億字節(jié) ≈ 4G
1Byte = 8bit
(2^32 - 1)bit = 4G/8 ≈ 500MB

例如:int a[]={2,5,7,19,24,30}

2.bitset應用 ?2.1bitset構造

位圖構造有三種形式,這里我們直接上代碼。

void testbitset1()
{
    //1.創(chuàng)建一個16位位圖,初始0
	std::bitset<16>foo;  // 創(chuàng)建一個16位位圖
    //2.賦值16進制
	std::bitset<16>bar(0xfa2);   //16進制 4002
   //3.用0,1賦值或者string
	std::bitset<16>baz(std::string("0101111001"));
	std::bitset<16>bs1("011010001");
	//foo : 0000000000000000
	//bar : 0000111110100010   4002
	//baz : 0000000101111001
	//bs1 : 0000000011010001
	std::cout<< "foo: "<< foo<< '\n';
	std::cout<< "bar: "<< bar<< '\n';
	std::cout<< "baz: "<< baz<< '\n';
	std::cout<< "bs1: "<< bs1<< '\n';
}
2.2bitset成員函數(shù)與使用?
成員函數(shù)? ? ? 功能
set? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?設置指定位或所有位
reset??清空指定位或所有位
test??獲取指定位的狀態(tài)
flip??反轉指定位或所有位
count? ?獲取被設置位的個數(shù)
size??獲取可以容納的位的個數(shù)
any? ??如果有任何一個位被設置則返回true
none? ??如果沒有位被設置則返回true
all? ??如果所有位都被設置則返回true

void testbitset2()
{
	std::bitset<16>bs1;
	bs1.set(2);  //0000000000000100
	cout<< bs1<< endl;
	bs1.set(4);
	bs1.set(5);  //0000000000110100
	cout<< bs1<< endl;
	//獲取指定位置的狀態(tài)
	cout<< bs1.test(5)<< endl;  //位置5的狀態(tài)是1
	cout<< bs1.test(10)<< endl; //位置10的狀態(tài)是0
	//反轉
	cout<< bs1.flip(4)<< endl;   //反轉第4位
	cout<< bs1.flip()<< endl;    //反轉所有位
	//清空
	cout<< bs1.reset(10)<< endl;   //清空第10位
	cout<< bs1.reset()<

bitset運算符那個就不講了。我們直接模擬實現(xiàn)一下。

3.bitset模擬實現(xiàn)?
  • 模擬bitset就是用一個普通的數(shù)組來存儲數(shù)據(jù)以達到模擬的目的。
  • 一個單元我們分成4個小組,每個小組8個位置。存放一個數(shù)據(jù)要先判斷在那個單元,然后是那個小組,那個位置。
  • 找到對應單元后,數(shù)據(jù)/8=對應小組;數(shù)據(jù)%8=對應位置。
  • 如果我們以一個整型作為比特位的容器,那么如果要求0~N范圍的比特位,就需要有N/32+1個整型來容納這些比特位,同理如果以char為容器,則需要N/8+1個char來容納N個比特位。這里我們用vector數(shù)組作為底層容納比特位的容器。之所以+1是怕開的空間存不下,所以多開一個,就算剩下也剩不了多少。
namespace cpp
{
	//N個比特位的位圖
	templateclass bitset
	{
	public:
		//構造函數(shù)
		bitset();
		//把value映射的位標記成1
		void set(size_t value);
		//把value映射的位標記成0
		void reset(size_t value);
		//判斷指定位value的狀態(tài)是否為1
		bool test(size_t value);
		//翻轉指定位置
		void flip(size_t value);
		//獲取位圖中可以容納位N的個數(shù)
		size_t size()
		//統(tǒng)計set中1的位數(shù)
		size_t count();
		//判斷所有比特位若無置為1,返回true
		bool none();
		//判斷位圖中是否有位被置為1,若有則返回true
		bool any();
		//全部NUM個bit位被set返回true
		bool all();
	private:
		vector_bits;//位圖
	};
}

這里我們用的存儲類型是char。

構造函數(shù)?

構造還是構造,但是文章已不是當年的文章了。

public :
		//構造函數(shù)
		bit_set
		{
			_bits.resize(N / 8 + 1,0);   // 全部賦值0
		}

之所以+1是因為如果數(shù)據(jù)的個數(shù)不是8的倍數(shù)時,可以再存進去,要不那多余的數(shù)據(jù)咋弄?

set

把映射的位置標記為1(把設置位置標記為1)。

例如:value=13;

//映射的位置標為1
		void set(size_t value)
		{
			size_t i = value / 8;  //找到小組
			size_t j = value % 8;   //找到位置
			//把對應位置標記為1
			_bits[i] |= 1<< j;     //或運算,有1則1
		}
reset

清空指定位或所有位?

這個和set正好相反,這個是把指定位置的數(shù)變成0,最后一步變化,其他不變,先按位取反,在按位與即可。j<<1按位取反后變成1,在按位與_bits[i]后就設置成0了。

//把value映射的位標記成0
		void reset(size_t value)
		{
			size_t i = value / 8;  //找到小組
			size_t j = value % 8;   //找到位置
			//把對應位置標記為1
			_bits[i] &=~(( 1<< j));     //先按位取反在與運算
		}
test

判斷指定位置是否為1

這個跟上面的reset就缺少一個按位取反。只進行一個按位與運算即可

//判斷指定位value的狀態(tài)是否為1
		bool test(size_t value)
		{
			size_t i = value / 8;  //找到小組
			size_t j = value % 8;   //找到位置
			//把對應位置標記為1
			_bits[i] &= (1<< j);  
		}
flip

指定位置數(shù)據(jù)翻轉:?如果是1變成0,0變成1。

這個按位異或就行了 ,相同為0,1變成0,相異為1,0^1=1

//翻轉指定pos
		void flip(size_t value)
		{
			size_t i = value / 8;  //找到小組
			size_t j = value % 8;   //找到位置
			//把對應位置標記為1
			_bits[i] ^= (1<< j);
		}
count?

統(tǒng)計位圖中出現(xiàn)的1的次數(shù)?

這個跟前面幾個就不一樣了。

這個是n&n-1

size_t count()
		{
			size_t count = 0;
			for (auto e : _bits)
			{
				int n = e;   //再設置個中間變量,別直接用e
				while (n)
				{
					n = n & (n - 1);
					count++;
				}
			}
			return count;
		}
size?

size的作用是獲取位圖中可以容納位N的個數(shù)

size_t size()
		{
			return N;
		}
none,any

none是查找位圖中是否全部是0,是就返回true,不是返回false。

any是查找位圖中是否有1,是就返回true,沒有返回false。any可以復用none。完整

bool none()
		{
			//遍歷每個char
			for (auto e : _bits)
			{
				if (e != 0)//位圖中有位置被置為1,返回false
					return false;
			}
			return true;//說明全為0,返回true
		}
		//若有位置為1,返回true
		bool any()
		{
			 return !none;
		}

完整代碼可到gitee查看

C++ 進階: 本倉庫存放一些較難C++代碼https://gitee.com/j-jun-jie/c---advanced.git

你是否還在尋找穩(wěn)定的海外服務器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調度確保服務器高可用性,企業(yè)級服務器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧


網(wǎng)站名稱:【C++】哈希-bitset位圖與模擬-創(chuàng)新互聯(lián)
文章路徑:http://weahome.cn/article/jjpjd.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部