C# 位圖BitArray的使用
前面聊了布隆過濾器,回歸認(rèn)識一下位圖BitMap,閱讀前文的同學(xué)應(yīng)該發(fā)現(xiàn)了布隆過濾器本身就是基于位圖,是位圖的一種改進(jìn)。
位圖
先看一個(gè)問題, 假如有1千萬個(gè)整數(shù),整數(shù)范圍在1到1億之間,如何快速確定某個(gè)整數(shù)是否在這個(gè)1千萬個(gè)整數(shù)中呢?
乍一看是一個(gè)查找問題,循環(huán)、二分查找都是常規(guī)思路。
一個(gè)好的答案是存儲(chǔ)結(jié)構(gòu)和算法的完美結(jié)合, 基于題干上的特征和條件,我們是否有其他思路。
對于題干我們使用高中排列組合的思維:有1億個(gè)有編號的空籃子,我們拿出這1千萬個(gè)有數(shù)字的球,放進(jìn)對應(yīng)的籃子。
最后,所有的籃子有兩種狀態(tài):有球/無球,我們要確定某個(gè)數(shù)字是否存在,就看對應(yīng)籃子是否為空。
什么是位圖?每一位存放某種狀態(tài),適用于海量數(shù)據(jù),通常用于判斷數(shù)據(jù)是否存在。位圖的空間由數(shù)據(jù)的最大值決定。
位圖這種數(shù)據(jù)結(jié)構(gòu)來大大節(jié)省內(nèi)存的使用量。
我們只需要構(gòu)造一個(gè)長度為1億的bit數(shù)組,將有球位置標(biāo)記為1,無球位置默認(rèn)記為0; 這樣我們就將數(shù)字轉(zhuǎn)換成了一個(gè)被壓縮緊致的數(shù)組索引,1億bit數(shù)組不到16M空間。
確定某位置有球,只需要O(1)的時(shí)間復(fù)雜度。
常用屬性
Count BitArray中包含實(shí)例的個(gè)數(shù)
IsReadOnly 獲取一個(gè)值,該值指示BitArray是否為只讀
Item 獲取或設(shè)置BitArray中特定位置的值
Length 獲取或設(shè)置BitArray中元素的數(shù)目
常用的方法
And 和指定的BitArray中相應(yīng)的元素做and運(yùn)算
Or 按位或運(yùn)算
Xor 按位異或運(yùn)算
Not 取反所有元素
Get 獲取特定位置處的值
Set 設(shè)定特定位置處的值
SetAll 將BitArray中所有的元素設(shè)定為指定的值
public sealed class BitArray : ICollection, IEnumerable, ICloneable { public BitArray(BitArray bits); //用已有的BitArray給新的BitArray初始化 public BitArray(bool[] values); //用布爾數(shù)組初始化 public BitArray(byte[] bytes); //用字節(jié)數(shù)組初始化 public BitArray(int length); //初始化并設(shè)置位數(shù)值,此值會(huì)在使用中自動(dòng)增長 public BitArray(int[] values); //用int數(shù)組初始化 public BitArray(int length, bool defaultValue); //初始化并設(shè)置默認(rèn)值 public int Count { get; } //位數(shù)組中現(xiàn)存的位的個(gè)數(shù) public bool IsReadOnly { get; } //確定位數(shù)組是否只讀 public bool IsSynchronized { get; } //是否同步對此BitArray的操作,用在線程安全上 public int Length { get; set; } //位數(shù)組的位數(shù) public object SyncRoot { get; } public bool this[int index] { get; set; } //索引器,利用索引讀位值 public BitArray And(BitArray value); //按位與 public object Clone(); //創(chuàng)建BitArray 的淺表副本。 public void CopyTo(Array array, int index); //將BitArray拷貝到其他數(shù)組中 public bool Get(int index); //按下標(biāo)讀取位值 public IEnumerator GetEnumerator(); //返回循環(huán)訪問BitArray 的枚舉數(shù) public BitArray Not(); //按位非 public BitArray Or(BitArray value); //按位或 public void Set(int index, bool value); //按位設(shè)置值 public void SetAll(bool value); //設(shè)置所有位為指定值 public BitArray Xor(BitArray value); //按位異或 }
C# 有專業(yè)的位圖數(shù)組:BitArray
using System; using System.Collections; namespace Bitmap { class Program { static void Main(string[] args) { var input = Console.ReadLine(); var num = int.Parse(input); var bitmap = InitBitMap(); if (bitmap.Get(num)) { Console.WriteLine($"找到數(shù)字{num}"); } else { Console.WriteLine($"未找到數(shù)字{num}"); } } public static BitArray InitBitMap() { var myBA1 = new BitArray(10000); var arr1 = new int[] { 1, 2, 4, 6, 77, 77, 88, 99, 100, 500, 600, 700, 999, 8888 }; foreach (int element in arr1) { myBA1[element] = true; } return myBA1; } } }
BitArray是管理位值的緊湊數(shù)組,用布爾值表示,其中true表示位是開啟的(1),false表示位是關(guān)閉的(0), 是引用類型,位于System.Collections命名空間。
以上只是小試牛刀,我們針對原題再發(fā)散一下,如何找到以上1千萬數(shù)字中重復(fù)的數(shù)字?
還是籃子中放球的思路,這次我們要兩排籃子,也就是兩個(gè)BitMap,利用位AND運(yùn)算(同時(shí)為True,結(jié)果才是True)找到兩排籃子中均有球的位置。
using System; using System.Collections; namespace Bitmap { class Program { static void Main(string[] args) { var bitmap = InitBitMap(); for (int i = 0; i < bitmap.Length; i++) { if(bitmap[i] == true) { Console.WriteLine(i); } } } public static BitArray InitBitMap() { var myBA1 = new BitArray(10000); var myBA2 = new BitArray(10000); var arr1 = new int[] { 1, 2, 4, 6, 77, 77, 88, 99, 100, 500, 600, 700, 999, 8888 }; foreach (int element in arr1) { if (myBA1[element] == false) { myBA1[element] = true; } else { myBA2[element] = true; } } myBA1 = myBA1.And(myBA2); return myBA1; } } }
最后提醒各位:寶藏組件Redis天然支持位圖
到此這篇關(guān)于C# 位圖BitArray的使用的文章就介紹到這了,更多相關(guān)C# 位圖BitArray內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
CPF?使用C#的Native?AOT?發(fā)布程序的詳細(xì)過程
這篇文章主要介紹了CPF?使用C#的Native?AOT?發(fā)布程序,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具體一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-03-03C#讀取XML的CDATA節(jié)點(diǎn)內(nèi)容實(shí)例詳解
在本篇文章里小編給大家整理了關(guān)于C# 讀取XML的CDATA節(jié)點(diǎn)內(nèi)容的相關(guān)知識點(diǎn)內(nèi)容,有需要的朋友們參考學(xué)習(xí)下。2019-09-09C# 9.0新特性——擴(kuò)展方法GetEnumerator支持foreach循環(huán)
這篇文章主要介紹了C# 9.0新特性——擴(kuò)展方法GetEnumerator支持foreach循環(huán)的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)c# 9.0,感興趣的朋友可以了解下2020-11-11解析C#中斷言與異常的應(yīng)用方式及異常處理的流程控制
這篇文章主要介紹了C#中斷言與異常的應(yīng)用方式及異常處理的流程控制,一般來說斷言用于修正程序員自己的錯(cuò)誤而異常用于應(yīng)對程序運(yùn)行過程中可能出現(xiàn)的錯(cuò)誤,需要的朋友可以參考下2016-01-01C#中LINQ?to?DataSet操作及DataTable與LINQ相互轉(zhuǎn)換
這篇文章介紹了C#中LINQ?to?DataSet操作及DataTable與LINQ相互轉(zhuǎn)換,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-05-05Winform下實(shí)現(xiàn)圖片切換特效的方法
這篇文章主要介紹了Winform下實(shí)現(xiàn)圖片切換特效的方法,包括百葉窗、淡入、旋轉(zhuǎn)等多種效果,需要的朋友可以參考下2014-08-08Unity3D游戲開發(fā)數(shù)據(jù)持久化PlayerPrefs的用法詳解
在本篇文章里小編給大家整理了關(guān)于Unity3D游戲開發(fā)之?dāng)?shù)據(jù)持久化PlayerPrefs的使用的相關(guān)知識點(diǎn)內(nèi)容,需要的朋友們參考下。2019-08-08C#判斷字符串中是否包含指定字符串及contains與indexof方法效率問題
這篇文章主要介紹了C#判斷字符串中是否包含指定字符串及contains與indexof方法效率問題 ,文中給大家列舉通過兩種方法來判斷,需要的朋友可以參考下2018-10-10