C# 位圖BitArray 小試牛刀

前面聊了布隆過濾器,迴歸認識一下位圖BitMap,閱讀前文的同學應該發現了布隆過濾器本身就是基於位圖,是位圖的一種改進。

位圖

先看一個問題, 假如有1千萬個整數,整數範圍在1到1億之間,如何快速確定某個整數是否在這個1千萬個整數中呢?

乍一看是一個查找問題,循環、二分查找都是常規思路。

一個好的答案是存儲結構和算法的完美結合, 基於題幹上的特徵和條件,我們是否有其他思路。

對於題幹我們使用高中排列組合的思維:有1億個有編號的空籃子,我們拿出這1千萬個有數字的球,放進對應的籃子。

最後,所有的籃子有兩種狀態:有球/無球,我們要確定某個數字是否存在,就看對應籃子是否爲空。

什麼是位圖?每一位存放某種狀態,適用於海量數據,通常用於判斷數據是否存在。位圖的空間由數據的最大值決定。

位圖這種數據結構來大大節省內存的使用量。


我們只需要構造一個長度爲1億的bit數組,將有球位置標記爲1,無球位置默認記爲0; 這樣我們就將數字轉換成了一個被壓縮緊緻的數組索引,1億bit數組不到16M空間。

確定某位置有球,只需要O(1)的時間複雜度。

C# 有專業的位圖數組: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($"找到數字{num}");
            }
            else
            {
                Console.WriteLine($"未找到數字{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是管理位值的緊湊數組,用布爾值表示,其中true表示位是開啓的(1),false表示位是關閉的(0), 是引用類型,位於System.Collections命名空間。

以上只是小試牛刀,我們針對原題再發散一下,如何找到以上1千萬數字中重複的數字?

還是籃子中放球的思路,這次我們要兩排籃子,也就是兩個BitMap,利用位AND運算(同時爲True,結果纔是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天然支持位圖

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章