1. 程式人生 > >BloomFilter(布隆過濾器)的C#實現

BloomFilter(布隆過濾器)的C#實現

BloomFilterTest的程式碼如下:

static void Main()
        {
            BloomFilter<string> bf = new BloomFilter<string>(20, 3);

            bf.Add("testing");
            bf.Add("nottesting");
            bf.Add("testingagain");

            Console.WriteLine(bf.Contains("badstring")); // False
            Console.WriteLine(bf.Contains("testing")); // True

            List<string> testItems = new List<string>() { "badstring", "testing", "test" };

            Console.WriteLine(bf.ContainsAll(testItems)); // False
            Console.WriteLine(bf.ContainsAny(testItems)); // True

            //誤檢率: 0.040894188143892
            Console.WriteLine("False Positive Probability: " + bf.FalsePositiveProbability());

            Console.ReadKey();
        }
BloomFilter類如下:
  /// <summary>
    /// 一個布隆過濾器是一個空間有效的概率資料結構
    /// 用於測試一個元素是否是一個集合的成員。誤檢率是可能的,但漏檢率是不存在的。元素可以被新增到集合,但不能從集合刪除。
    /// </summary>
    /// <typeparam name="Type">泛型資料型別</typeparam>
    public class BloomFilter<T>
    {
        Random _random;
        int _bitSize, _numberOfHashes, _setSize;
        BitArray _bitArray;

        #region Constructors
        /// <summary>
        /// 初始化bloom濾波器並設定hash雜湊的最佳數目
        /// </summary>
        /// <param name="bitSize">布隆過濾器的大小(m)</param>
        /// <param name="setSize">集合的大小 (n)</param>
        public BloomFilter(int bitSize, int setSize)
        {
            _bitSize = bitSize;
            _bitArray = new BitArray(bitSize);
            _setSize = setSize;
            _numberOfHashes = OptimalNumberOfHashes(_bitSize, _setSize);
        }

        //<param name="numberOfHashes">hash雜湊函式的數量(k)</param>
        public BloomFilter(int bitSize, int setSize, int numberOfHashes)
        {
            _bitSize = bitSize;
            _bitArray = new BitArray(bitSize);
            _setSize = setSize;
            _numberOfHashes = numberOfHashes;
        }
        #endregion

        #region 屬性
        public int NumberOfHashes
        {
            set
            {
                _numberOfHashes = value;
            }
            get
            {
                return _numberOfHashes;
            }
        }
        public int SetSize
        {
            set
            {
                _setSize = value;
            }
            get
            {
                return _setSize;
            }
        }
        public int BitSize
        {
            set
            {
                _bitSize = value;
            }
            get
            {
                return _bitSize;
            }
        }
        #endregion

        #region 公共方法
        public void Add(T item)
        {
            _random = new Random(Hash(item));

            for (int i = 0; i < _numberOfHashes; i++)
                _bitArray[_random.Next(_bitSize)] = true;
        }
        public bool Contains(T item)
        {
            _random = new Random(Hash(item));

            for (int i = 0; i < _numberOfHashes; i++)
            {
                if (!_bitArray[_random.Next(_bitSize)])
                    return false;
            }
            return true;
        }
       
        //檢查列表中的任何項是否可能是在集合。
        //如果布隆過濾器包含列表中的任何一項,返回真
        public bool ContainsAny(List<T> items)
        {
            foreach (T item in items)
            {
                if (Contains(item))
                    return true;
            }
            return false;
        }

        //檢查列表中的所有專案是否都在集合。
        public bool ContainsAll(List<T> items)
        {
            foreach (T item in items)
            {
                if (!Contains(item))
                    return false;
            }

            return true;
        }

        /// <summary>
        /// 計算遇到誤檢率的概率。
        /// </summary>
        /// <returns>Probability of a false positive</returns>
        public double FalsePositiveProbability()
        {
            return Math.Pow((1 - Math.Exp(-_numberOfHashes * _setSize / (double)_bitSize)), _numberOfHashes);
        }
        #endregion

        #region 私有方法
        private int Hash(T item) {
            return item.GetHashCode();
        }

        //計算基於布隆過濾器雜湊的最佳數量
        private int OptimalNumberOfHashes(int bitSize, int setSize)
        {
            return (int)Math.Ceiling((bitSize / setSize) * Math.Log(2.0));
        }
        #endregion
    }
結果如圖: