【算法一】布隆过滤器算法学习附维基百科详细说明PDF文件

示例一 来源:https://www.cnblogs.com/yueyue184/p/10037587.html

    /// 
    /// 布隆过滤器
    /// 
    public class BloomFilter
    {
        public BitArray _bloomArray;
        /// 
        /// 布隆数组的大小
        /// 
        public Int64 BloomArrayLength { get; set; }
        /// 
        /// 数据长度
        /// 
        public Int64 DataArrayLength { get; set; }
        /// 
        /// hash数
        /// 
        public Int64 BitIndexCount { get; set; }

        /// 
        /// 布隆过滤器初始化
        /// 
        /// 布隆数组的大小
        /// 数据长度
        /// hash数
        public BloomFilter(int bloomArrayLength, int dataArrayLength, int bitIndexCount)
        {
            _bloomArray = new BitArray(bloomArrayLength);

            this.BloomArrayLength = bloomArrayLength;
            this.DataArrayLength = dataArrayLength;
            this.BitIndexCount = bitIndexCount;
        }

        /// 
        /// 添加
        /// 
        /// 
        public void Add(string str)
        {
            var hashCode=str.GetHashCode();
            var random = new Random(hashCode);

            for (int i = 0; i < BitIndexCount; i++)
            {
                var c=random.Next((int)this.BloomArrayLength - 1);
                _bloomArray[c] = true;
            }
        }

        /// 
        /// 判断是否存在
        /// 
        /// 字符串
        /// 
        public bool IsExists(string str)
        {
            var hashCode = str.GetHashCode();
            var random = new Random(hashCode);
            for (int i = 0; i < BitIndexCount; i++)
            {
                if (!_bloomArray[random.Next((int)this.BloomArrayLength-1)])
                {
                    return false;
                }
            }
            return true;
        }

        /// 
        /// 获取错误概率
        /// 
        /// 
        public double GetFalsePositiveProbability()
        {
            // (1 - e^(-k * n / m)) ^ k
            return Math.Pow((1 - Math.Exp(-BitIndexCount * (double)DataArrayLength / BloomArrayLength)), BitIndexCount);
        }

    }

 

    class Program
    {
        static void Main(string[] args)
        {
            //五千万条数据
            var bloomFilter = new BloomFilter(200000000, 50000000, 3);

            //添加5千万个数做测试
            for (int i = 0; i < bloomFilter.DataArrayLength; i++)
            {
                bloomFilter.Add(i.ToString());
            }

            do
            {
                var str = Console.ReadLine();

                var stopwatch = new Stopwatch();
                stopwatch.Start();

                var temp = bloomFilter.IsExists(str);

                stopwatch.Stop();
                Console.WriteLine($"查找:{str}\n结果:{temp}\n总耗时:{stopwatch.ElapsedTicks}\n错误概率:{bloomFilter.GetFalsePositiveProbability()}");
            } while (true);
        }
    }

大数据量的查找结果及错误概率

【算法一】布隆过滤器算法学习附维基百科详细说明PDF文件_第1张图片

内存占用情况

 小数据量下的查找结果及错误概率

【算法一】布隆过滤器算法学习附维基百科详细说明PDF文件_第2张图片

布隆数组很大,但是数据长度很小的情况下错误概率就会很大,所以两者之间有相关关系,并且查找都很快

【算法一】布隆过滤器算法学习附维基百科详细说明PDF文件_第3张图片

Bloom filter是Bloom在1970年提出的二进制向量数据结构 

 

可控制性

 

       根据其数组长度m、集合大小n、hash函数个数k、误判率p,简单得出下:

 

  1. 其他不变,集合大小n越大,越多位被设置1,误判率p越大。
  2. 其他不变,数组涨肚m越大,剩余为0的位越多,误判率p越小
  3. 其他不变,添加时k越多,位数组越多被设置为1,即会增大误判率。查询时k越多,明显误判率可能就会越小。

 

hash函数个数取值公式 k = ln 2 * m/n 。

 

通常应用在一些大数据下需要快速判断某个元素是否属于集合,但是并不严格要求100%正确的场合。

例如:

爬虫过程中的重复URL检测。

缓存命中率,垃圾邮件过滤。

内存挡一层,减轻db空查压力。

黑名单验证。

优点在于:

  • 插入和查询复杂度都是O(n)
  • 空间利用率极高。

算法步骤:

  1. 创建长度为m的位数组,全部置为0。
  2. 取出邮件地址集合(m)中的某一个地址(a), 分别使用k个hash函数对a计算。
  3. 将结果分别映射到位数组中,并设置为1。
  4. 其他成员依次处理。

其他参考:https://www.cnblogs.com/heaad/archive/2011/01/02/1924195.html

布隆算法维基百科中文说明PDF文件:

https://files.cnblogs.com/files/wgx0428/%E5%B8%83%E9%9A%86%E8%BF%87%E6%BB%A4%E5%99%A8%E7%BB%B4%E5%9F%BA%E7%99%BE%E7%A7%91%E4%B8%AD%E6%96%87%E8%AF%B4%E6%98%8E.7z

你可能感兴趣的:(【算法一】布隆过滤器算法学习附维基百科详细说明PDF文件)