ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

【C# 数据结构】BitMap算法的c#实现

2022-06-16 22:06:36  阅读:231  来源: 互联网

标签:存储 C# BitMap c# int num 数组 byte public


 

1.BitMap的应用

在网络同步中(尤其是帧同步),往往需要找一种数据在序列化之后,体积小,数据信息量可观的数据存储方式。

帧同步为例,一个相当复杂的ACT游戏,采用同步交互量最省的帧同步方式进行网络同步,每关键帧只同步玩家的键位操作数据,此时如果使用BitMap算法进行数据结构的设计,只要1byte就可以存8个键位操作,1int则可以存32个键位操作,每一个关键帧的传输量很小。

在c#语言中,已经设计了BitArray这一数据结构,可直接投入使用。本文旨在详解BitMap算法,所以重新用最基础的byte[]数组以及简单的位运算,来重新实现一遍。

 

2.BitMap算法的原理介绍

首先,我们来看一个byte的结构组成

 

 

 

一个byte的有8位,每一位都可以用来存储0或1的值,默认每一位都是0。

 

我们把每一位的位置信息,作为计数,如0就把第0位的值存为1,1就放在第1位的值存为1,2就放在第2位的值存为1,想要表达的数据超过了8位,就再建立一个byte,继续存放。

 

 

 

 

Magic! 如果现在有10亿的数据,原本按32位int存一个数组,需要 4字节*10亿 = 3.7G左右的空间,如果转换成上述的bitmap算法,从4字节存一个数,变成了1字节存8个数,则只需要3.7G / 32 的空间了。

 

3.具体实现与源码解析

 

按照上述分析,我们主要实现目标其实就是对众多byte组成的这一数据结构,可以进行便利的增删改查。

其中要点可以分为以下三点

1.能够快速的根据存入的数据,定位到其在bitmap中的索引位置。
2.定位到位置后,可以方便的修改其值。(0或1)
3.对于多个byte进行恰当的存储。

首先针对第3点,我们可以很快联系到申明一个byte数组,这样数据连续存储,也方便整体遍历。

再者,针对第1点,也不难想到,既然bitmap本质意义是一个byte数组,那么对于存储其中的数据,我们需要定位到其存储在数组的第几号元素,以及在该元素也就是单个byte中,存储于第几位上。

 

一个byte有8位,首位存0,直接上超级简单的数学算法

对于数据N
在数组中的序号(N) = N / 8 = N >> 3
定位到当前序号的byte后
在byte中的位置(N) = N % 8 = N & 0X07

解决了定位,我们再来看第2点,修改当前位置的值

对于当前byte中,第P位的值
设定一个同为8位byte类型的模板值,由1左移P位得到
byte M = (byte)(1 << P) 
1.如果存入,则需将第P位设为1
	byte = byte | M
2.如果清除,则需将P位设为0
	2.1 将模板值M取反,Z = ~M
	2.2 byte = byte & Z

 

 

 

 

 

 

 

同理,我们还可以扩展出算法,对当前的bitmap是否存储了某个值进行判断

byte isContain = byte & M
如果 isContain 不为0,则存在数据N,反之则不存在

 

 

 

所有源码如下

public class CustomBitMap
{
    public byte[] Bits { get; private set; }

    /// <summary>
    /// 数组中的第几个byte
    /// </summary>
    public byte Index { get; private set; }
    
    /// <summary>
    /// 在单个byte中 第几位
    /// </summary>
    public byte Position { get; private set; }

    public CustomBitMap(int length = 8)
    {
        Bits = new byte[length];
        Index = 0;
        Position = 0;
    }


    /// <summary>
    /// byte[] 中 所在的num位置变为1 其他位置不变
    /// </summary>
    /// <param name="num"></param>
    public void Add(int num)
    {
        //num / 8 得到位于数组的第几个byte
        int arrayIndex = num >> 3;
        // num % 8 得到位于单个byte中 第几位
        int position = num & 0x07;

        byte arg = (byte) (1 << position);
        Bits[arrayIndex] |= arg;
    }


    public void Clear(int num)
    {
        //num / 8 得到位于数组的第几个byte
        int arrayIndex = num >> 3;
        // num % 8 得到位于单个byte中 第几位
        int position = num & 0x07;

        //将1 左移并取反
        byte arg = (byte) ~(1 << position);
        
        //随后&上即清除
        Bits[arrayIndex] &= arg;
    }


    public bool Contains(int num)
    {
        //num / 8 得到位于数组的第几个byte
        int arrayIndex = num >> 3;
        // num % 8 得到位于单个byte中 第几位
        int position = num & 0x07;

        //将1 左移并取反
        byte arg = (byte)(1 << position);
        
        return (Bits[arrayIndex] & arg) != 0;
    }
}

 

 

标签:存储,C#,BitMap,c#,int,num,数组,byte,public
来源: https://www.cnblogs.com/cdaniu/p/16383679.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有